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" 25dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/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 36508127e2SPaolo Bonzini #include "exec/log.h" 37a7e30d84SLluís Vilanova 3877fc6f5eSLluís Vilanova /* is_jmp field values */ 3964e46c95SRichard Henderson #define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */ 408000ba56SRichard Henderson #define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */ 4177fc6f5eSLluís Vilanova 42bbe418f2SJia Liu typedef struct DisasContext { 431ffa4bceSEmilio G. Cota DisasContextBase base; 44bbe418f2SJia Liu uint32_t mem_idx; 45a01deb36SRichard Henderson uint32_t tb_flags; 46bbe418f2SJia Liu uint32_t delayed_branch; 47fe636d37SRichard Henderson uint32_t cpucfgr; 482b13b4b9SRichard Henderson uint32_t avr; 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; 55118671f0SRichard Henderson /* The constant zero. */ 56118671f0SRichard Henderson TCGv zero; 57bbe418f2SJia Liu } DisasContext; 58bbe418f2SJia Liu 592ba65417SRichard Henderson static inline bool is_user(DisasContext *dc) 602ba65417SRichard Henderson { 612ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY 622ba65417SRichard Henderson return true; 632ba65417SRichard Henderson #else 64b9bed1b9SRichard Henderson return !(dc->tb_flags & TB_FLAGS_SM); 652ba65417SRichard Henderson #endif 662ba65417SRichard Henderson } 672ba65417SRichard Henderson 687de9729fSRichard Henderson /* Include the auto-generated decoder. */ 69abff1abfSPaolo Bonzini #include "decode-insns.c.inc" 707de9729fSRichard Henderson 71bbe418f2SJia Liu static TCGv cpu_sr; 728bba7619SRichard Henderson static TCGv cpu_regs[32]; 73bbe418f2SJia Liu static TCGv cpu_pc; 74bbe418f2SJia Liu static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 75bbe418f2SJia Liu static TCGv cpu_ppc; 7684775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 7797458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 7897458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 79930c3d00SRichard Henderson static TCGv cpu_lock_addr; 80930c3d00SRichard Henderson static TCGv cpu_lock_value; 81bbe418f2SJia Liu static TCGv_i32 fpcsr; 826f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 83a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 84bbe418f2SJia Liu 85e67db06eSJia Liu void openrisc_translate_init(void) 86e67db06eSJia Liu { 87bbe418f2SJia Liu static const char * const regnames[] = { 88bbe418f2SJia Liu "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 89bbe418f2SJia Liu "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 90bbe418f2SJia Liu "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 91bbe418f2SJia Liu "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 92bbe418f2SJia Liu }; 93bbe418f2SJia Liu int i; 94bbe418f2SJia Liu 95e1ccc054SRichard Henderson cpu_sr = tcg_global_mem_new(cpu_env, 96bbe418f2SJia Liu offsetof(CPUOpenRISCState, sr), "sr"); 97a01deb36SRichard Henderson cpu_dflag = tcg_global_mem_new_i32(cpu_env, 98a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 99a01deb36SRichard Henderson "dflag"); 100e1ccc054SRichard Henderson cpu_pc = tcg_global_mem_new(cpu_env, 101bbe418f2SJia Liu offsetof(CPUOpenRISCState, pc), "pc"); 102e1ccc054SRichard Henderson cpu_ppc = tcg_global_mem_new(cpu_env, 103bbe418f2SJia Liu offsetof(CPUOpenRISCState, ppc), "ppc"); 104e1ccc054SRichard Henderson jmp_pc = tcg_global_mem_new(cpu_env, 105bbe418f2SJia Liu offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 10684775c43SRichard Henderson cpu_sr_f = tcg_global_mem_new(cpu_env, 10784775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 10897458071SRichard Henderson cpu_sr_cy = tcg_global_mem_new(cpu_env, 10997458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 11097458071SRichard Henderson cpu_sr_ov = tcg_global_mem_new(cpu_env, 11197458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 112930c3d00SRichard Henderson cpu_lock_addr = tcg_global_mem_new(cpu_env, 113930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 114930c3d00SRichard Henderson "lock_addr"); 115930c3d00SRichard Henderson cpu_lock_value = tcg_global_mem_new(cpu_env, 116930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 117930c3d00SRichard Henderson "lock_value"); 118e1ccc054SRichard Henderson fpcsr = tcg_global_mem_new_i32(cpu_env, 119bbe418f2SJia Liu offsetof(CPUOpenRISCState, fpcsr), 120bbe418f2SJia Liu "fpcsr"); 1216f7332baSRichard Henderson cpu_mac = tcg_global_mem_new_i64(cpu_env, 1226f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1236f7332baSRichard Henderson "mac"); 124bbe418f2SJia Liu for (i = 0; i < 32; i++) { 1258bba7619SRichard Henderson cpu_regs[i] = tcg_global_mem_new(cpu_env, 126d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 127d89e71e8SStafford Horne shadow_gpr[0][i]), 128bbe418f2SJia Liu regnames[i]); 129bbe418f2SJia Liu } 130bbe418f2SJia Liu } 131bbe418f2SJia Liu 132bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp) 133bbe418f2SJia Liu { 134af42d354SRichard Henderson gen_helper_exception(cpu_env, tcg_constant_i32(excp)); 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 1442b13b4b9SRichard Henderson static bool check_v1_3(DisasContext *dc) 1452b13b4b9SRichard Henderson { 1462b13b4b9SRichard Henderson return dc->avr >= 0x01030000; 1472b13b4b9SRichard Henderson } 1482b13b4b9SRichard Henderson 149fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc) 150bbe418f2SJia Liu { 151fe636d37SRichard Henderson return dc->cpucfgr & CPUCFGR_OF32S; 152bbe418f2SJia Liu } 153bbe418f2SJia Liu 15462f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc) 15562f2b038SRichard Henderson { 15662f2b038SRichard Henderson return dc->cpucfgr & CPUCFGR_OF64A32S; 15762f2b038SRichard Henderson } 15862f2b038SRichard Henderson 1598bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1608bba7619SRichard Henderson { 161d29f4368SRichard Henderson if (reg == 0) { 162d29f4368SRichard Henderson return dc->R0; 163d29f4368SRichard Henderson } else { 1648bba7619SRichard Henderson return cpu_regs[reg]; 1658bba7619SRichard Henderson } 166d29f4368SRichard Henderson } 1678bba7619SRichard Henderson 168cdd0f459SRichard Henderson /* 169cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 170cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 171cdd0f459SRichard Henderson */ 172cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 173cdd0f459SRichard Henderson { 174cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 175d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 176cdd0f459SRichard Henderson } 177cdd0f459SRichard Henderson } 1786597c28dSRichard Henderson 17997458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1809ecaa27eSRichard Henderson { 1810c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18297458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1839ecaa27eSRichard Henderson } 1840c53d734SRichard Henderson } 1859ecaa27eSRichard Henderson 18697458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1879ecaa27eSRichard Henderson { 1880c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18997458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1909ecaa27eSRichard Henderson } 1910c53d734SRichard Henderson } 1929ecaa27eSRichard Henderson 19397458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1949ecaa27eSRichard Henderson { 1950c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19697458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 1979ecaa27eSRichard Henderson } 1980c53d734SRichard Henderson } 1999ecaa27eSRichard Henderson 2009ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2019ecaa27eSRichard Henderson { 202e0efc48fSRichard Henderson TCGv t0 = tcg_temp_new(); 2039ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2049ecaa27eSRichard Henderson 205e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero); 20697458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2079ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 20897458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2099ecaa27eSRichard Henderson tcg_temp_free(t0); 2109ecaa27eSRichard Henderson 2119ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2129ecaa27eSRichard Henderson tcg_temp_free(res); 2139ecaa27eSRichard Henderson 21497458071SRichard Henderson gen_ove_cyov(dc); 2159ecaa27eSRichard Henderson } 2169ecaa27eSRichard Henderson 2179ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2189ecaa27eSRichard Henderson { 219e0efc48fSRichard Henderson TCGv t0 = tcg_temp_new(); 2209ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2219ecaa27eSRichard Henderson 222e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero); 223e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero); 22497458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2259ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22697458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2279ecaa27eSRichard Henderson tcg_temp_free(t0); 2289ecaa27eSRichard Henderson 2299ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2309ecaa27eSRichard Henderson tcg_temp_free(res); 2319ecaa27eSRichard Henderson 23297458071SRichard Henderson gen_ove_cyov(dc); 2339ecaa27eSRichard Henderson } 2349ecaa27eSRichard Henderson 2359ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2369ecaa27eSRichard Henderson { 2379ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2389ecaa27eSRichard Henderson 2399ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 24097458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 24197458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 24297458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 24397458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2449ecaa27eSRichard Henderson 2459ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2469ecaa27eSRichard Henderson tcg_temp_free(res); 2479ecaa27eSRichard Henderson 24897458071SRichard Henderson gen_ove_cyov(dc); 2499ecaa27eSRichard Henderson } 2509ecaa27eSRichard Henderson 2519ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2529ecaa27eSRichard Henderson { 2539ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2549ecaa27eSRichard Henderson 25597458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2569ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 25797458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2589ecaa27eSRichard Henderson tcg_temp_free(t0); 2599ecaa27eSRichard Henderson 26097458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 26197458071SRichard Henderson gen_ove_ov(dc); 2629ecaa27eSRichard Henderson } 2639ecaa27eSRichard Henderson 2649ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2659ecaa27eSRichard Henderson { 26697458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 26797458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2689ecaa27eSRichard Henderson 26997458071SRichard Henderson gen_ove_cy(dc); 2709ecaa27eSRichard Henderson } 2719ecaa27eSRichard Henderson 2729ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2739ecaa27eSRichard Henderson { 2749ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2759ecaa27eSRichard Henderson 27697458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2779ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2789ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 27997458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2809ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2819ecaa27eSRichard Henderson tcg_temp_free(t0); 2829ecaa27eSRichard Henderson 28397458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 28497458071SRichard Henderson gen_ove_ov(dc); 2859ecaa27eSRichard Henderson } 2869ecaa27eSRichard Henderson 2879ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2889ecaa27eSRichard Henderson { 2899ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2909ecaa27eSRichard Henderson 29197458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2929ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2939ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 29497458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2959ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2969ecaa27eSRichard Henderson tcg_temp_free(t0); 2979ecaa27eSRichard Henderson 29897458071SRichard Henderson gen_ove_cy(dc); 2999ecaa27eSRichard Henderson } 300da1d7759SSebastian Macke 301cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 302cc5de49eSRichard Henderson { 303cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 304cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 305cc5de49eSRichard Henderson 306cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 307cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 308cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 309cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 310cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 311cc5de49eSRichard Henderson } else { 312cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 313cc5de49eSRichard Henderson 314cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 315cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 316cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 317cc5de49eSRichard Henderson tcg_temp_free_i64(high); 318cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 319cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 320cc5de49eSRichard Henderson 321cc5de49eSRichard Henderson gen_ove_ov(dc); 322cc5de49eSRichard Henderson } 323cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 324cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 325cc5de49eSRichard Henderson } 326cc5de49eSRichard Henderson 327cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 328cc5de49eSRichard Henderson { 329cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 330cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 331cc5de49eSRichard Henderson 332cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 333cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 334cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 335cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 336cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 337cc5de49eSRichard Henderson } else { 338cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 339cc5de49eSRichard Henderson 340cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 341cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 342cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 343cc5de49eSRichard Henderson tcg_temp_free_i64(high); 344cc5de49eSRichard Henderson 345cc5de49eSRichard Henderson gen_ove_cy(dc); 346cc5de49eSRichard Henderson } 347cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 348cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 349cc5de49eSRichard Henderson } 350cc5de49eSRichard Henderson 3516f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3526f7332baSRichard Henderson { 3536f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3546f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3556f7332baSRichard Henderson 3566f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3576f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3586f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3596f7332baSRichard Henderson 3606f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3616f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3626f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3636f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3646f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3656f7332baSRichard Henderson tcg_temp_free_i64(t2); 3666f7332baSRichard Henderson 3676f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3686f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3696f7332baSRichard Henderson #else 3706f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3716f7332baSRichard Henderson #endif 3726f7332baSRichard Henderson tcg_temp_free_i64(t1); 3736f7332baSRichard Henderson 3746f7332baSRichard Henderson gen_ove_ov(dc); 3756f7332baSRichard Henderson } 3766f7332baSRichard Henderson 377cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 378cc5de49eSRichard Henderson { 379cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 380cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 381cc5de49eSRichard Henderson 382cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 383cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 384cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 385cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 386cc5de49eSRichard Henderson 387cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 388cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 389cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 390cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 391cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 392cc5de49eSRichard Henderson 393cc5de49eSRichard Henderson gen_ove_cy(dc); 394cc5de49eSRichard Henderson } 395cc5de49eSRichard Henderson 3966f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3976f7332baSRichard Henderson { 3986f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3996f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4006f7332baSRichard Henderson 4016f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4026f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4036f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4046f7332baSRichard Henderson 4056f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4066f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4076f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4086f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4096f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4106f7332baSRichard Henderson tcg_temp_free_i64(t2); 4116f7332baSRichard Henderson 4126f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4136f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4146f7332baSRichard Henderson #else 4156f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4166f7332baSRichard Henderson #endif 4176f7332baSRichard Henderson tcg_temp_free_i64(t1); 4186f7332baSRichard Henderson 4196f7332baSRichard Henderson gen_ove_ov(dc); 4206f7332baSRichard Henderson } 4216f7332baSRichard Henderson 422cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 423cc5de49eSRichard Henderson { 424cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 425cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 426cc5de49eSRichard Henderson 427cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 428cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 429cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 430cc5de49eSRichard Henderson 431cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 432cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 433cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 434cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 435cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 436cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 437cc5de49eSRichard Henderson 438cc5de49eSRichard Henderson gen_ove_cy(dc); 439cc5de49eSRichard Henderson } 440cc5de49eSRichard Henderson 4413a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 442bbe418f2SJia Liu { 443cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4448bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4456ad216abSRichard Henderson return true; 446bbe418f2SJia Liu } 447bbe418f2SJia Liu 4483a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 449bbe418f2SJia Liu { 450cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4518bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4526ad216abSRichard Henderson return true; 4536ad216abSRichard Henderson } 4546ad216abSRichard Henderson 4553a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4566ad216abSRichard Henderson { 457cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4588bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4596ad216abSRichard Henderson return true; 4606ad216abSRichard Henderson } 4616ad216abSRichard Henderson 4623a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4636ad216abSRichard Henderson { 464cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4658bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4666ad216abSRichard Henderson return true; 4676ad216abSRichard Henderson } 4686ad216abSRichard Henderson 4693a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4706ad216abSRichard Henderson { 471cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4728bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4736ad216abSRichard Henderson return true; 4746ad216abSRichard Henderson } 4756ad216abSRichard Henderson 4763a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4776ad216abSRichard Henderson { 478cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4798bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4806ad216abSRichard Henderson return true; 4816ad216abSRichard Henderson } 4826ad216abSRichard Henderson 4833a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4846ad216abSRichard Henderson { 485cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4868bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4876ad216abSRichard Henderson return true; 4886ad216abSRichard Henderson } 4896ad216abSRichard Henderson 4903a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4916ad216abSRichard Henderson { 492cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4938bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4946ad216abSRichard Henderson return true; 4956ad216abSRichard Henderson } 4966ad216abSRichard Henderson 4973a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 4986ad216abSRichard Henderson { 499cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5008bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5016ad216abSRichard Henderson return true; 5026ad216abSRichard Henderson } 5036ad216abSRichard Henderson 5043a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 5056ad216abSRichard Henderson { 506cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5078bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5086ad216abSRichard Henderson return true; 5096ad216abSRichard Henderson } 5106ad216abSRichard Henderson 5113a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5126ad216abSRichard Henderson { 513cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5148bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5156ad216abSRichard Henderson return true; 5166ad216abSRichard Henderson } 5176ad216abSRichard Henderson 5183a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5196ad216abSRichard Henderson { 520cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5218bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5226ad216abSRichard Henderson return true; 5236ad216abSRichard Henderson } 5246ad216abSRichard Henderson 5253a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5266ad216abSRichard Henderson { 527cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5288bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5296ad216abSRichard Henderson return true; 5306ad216abSRichard Henderson } 5316ad216abSRichard Henderson 5323a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5336ad216abSRichard Henderson { 534cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5358bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5366ad216abSRichard Henderson return true; 5376ad216abSRichard Henderson } 5386ad216abSRichard Henderson 5393a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5406ad216abSRichard Henderson { 541cdd0f459SRichard Henderson check_r0_write(dc, a->d); 542118671f0SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero, 5438bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 5446ad216abSRichard Henderson return true; 545bbe418f2SJia Liu } 546bbe418f2SJia Liu 5473a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5486ad216abSRichard Henderson { 549cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5508bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 5518bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5526ad216abSRichard Henderson return true; 553cf2ae442SRichard Henderson } 554cf2ae442SRichard Henderson 5553a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5566ad216abSRichard Henderson { 557cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5588bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 5598bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5606ad216abSRichard Henderson return true; 561bbe418f2SJia Liu } 562bbe418f2SJia Liu 5633a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5646ad216abSRichard Henderson { 565cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5668bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5676ad216abSRichard Henderson return true; 568bbe418f2SJia Liu } 5696ad216abSRichard Henderson 5703a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5716ad216abSRichard Henderson { 572cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5738bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5746ad216abSRichard Henderson return true; 575bbe418f2SJia Liu } 5766ad216abSRichard Henderson 5773a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5786ad216abSRichard Henderson { 579cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5808bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5816ad216abSRichard Henderson return true; 5826ad216abSRichard Henderson } 5836ad216abSRichard Henderson 5843a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5856ad216abSRichard Henderson { 586cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5878bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5886ad216abSRichard Henderson return true; 5896ad216abSRichard Henderson } 5906ad216abSRichard Henderson 5913a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 5926ad216abSRichard Henderson { 5938bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5946ad216abSRichard Henderson return true; 5956ad216abSRichard Henderson } 5966ad216abSRichard Henderson 5973a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 5986ad216abSRichard Henderson { 5998bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 6006ad216abSRichard Henderson return true; 601bbe418f2SJia Liu } 602bbe418f2SJia Liu 6033a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 604136e13aeSRichard Henderson { 605136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 606136e13aeSRichard Henderson 607136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6088000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 609136e13aeSRichard Henderson dc->delayed_branch = 2; 610136e13aeSRichard Henderson return true; 611136e13aeSRichard Henderson } 612136e13aeSRichard Henderson 6133a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 614136e13aeSRichard Henderson { 615136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 616136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 617136e13aeSRichard Henderson 6188bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 619136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 620136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 621136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6228000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 623136e13aeSRichard Henderson dc->delayed_branch = 2; 624136e13aeSRichard Henderson } 625136e13aeSRichard Henderson return true; 626136e13aeSRichard Henderson } 627136e13aeSRichard Henderson 628136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 629136e13aeSRichard Henderson { 630136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 631af42d354SRichard Henderson TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8); 632af42d354SRichard Henderson TCGv t_true = tcg_constant_tl(tmp_pc); 633136e13aeSRichard Henderson 634118671f0SRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next); 635136e13aeSRichard Henderson dc->delayed_branch = 2; 636136e13aeSRichard Henderson } 637136e13aeSRichard Henderson 6383a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 639136e13aeSRichard Henderson { 640136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 641136e13aeSRichard Henderson return true; 642136e13aeSRichard Henderson } 643136e13aeSRichard Henderson 6443a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 645136e13aeSRichard Henderson { 646136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 647136e13aeSRichard Henderson return true; 648136e13aeSRichard Henderson } 649136e13aeSRichard Henderson 6503a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 651136e13aeSRichard Henderson { 6528bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 653136e13aeSRichard Henderson dc->delayed_branch = 2; 654136e13aeSRichard Henderson return true; 655136e13aeSRichard Henderson } 656136e13aeSRichard Henderson 6573a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 658136e13aeSRichard Henderson { 6598bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6608bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 661136e13aeSRichard Henderson dc->delayed_branch = 2; 662136e13aeSRichard Henderson return true; 663136e13aeSRichard Henderson } 664136e13aeSRichard Henderson 6653a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 666d80bff19SRichard Henderson { 667d80bff19SRichard Henderson TCGv ea; 668d80bff19SRichard Henderson 669cdd0f459SRichard Henderson check_r0_write(dc, a->d); 670d80bff19SRichard Henderson ea = tcg_temp_new(); 6718bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6728bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 673d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6748bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 675d80bff19SRichard Henderson tcg_temp_free(ea); 676d80bff19SRichard Henderson return true; 677d80bff19SRichard Henderson } 678d80bff19SRichard Henderson 67914776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 680d80bff19SRichard Henderson { 681d80bff19SRichard Henderson TCGv ea; 682d80bff19SRichard Henderson 683cdd0f459SRichard Henderson check_r0_write(dc, a->d); 684d80bff19SRichard Henderson ea = tcg_temp_new(); 6858bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6868bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 687d80bff19SRichard Henderson tcg_temp_free(ea); 688d80bff19SRichard Henderson } 689d80bff19SRichard Henderson 6903a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 691d80bff19SRichard Henderson { 692d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 693d80bff19SRichard Henderson return true; 694d80bff19SRichard Henderson } 695d80bff19SRichard Henderson 6963a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 697d80bff19SRichard Henderson { 698d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 699d80bff19SRichard Henderson return true; 700d80bff19SRichard Henderson } 701d80bff19SRichard Henderson 7023a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 703d80bff19SRichard Henderson { 704d80bff19SRichard Henderson do_load(dc, a, MO_UB); 705d80bff19SRichard Henderson return true; 706d80bff19SRichard Henderson } 707d80bff19SRichard Henderson 7083a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 709d80bff19SRichard Henderson { 710d80bff19SRichard Henderson do_load(dc, a, MO_SB); 711d80bff19SRichard Henderson return true; 712d80bff19SRichard Henderson } 713d80bff19SRichard Henderson 7143a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 715d80bff19SRichard Henderson { 716d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 717d80bff19SRichard Henderson return true; 718d80bff19SRichard Henderson } 719d80bff19SRichard Henderson 7203a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 721d80bff19SRichard Henderson { 722d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 723d80bff19SRichard Henderson return true; 724d80bff19SRichard Henderson } 725d80bff19SRichard Henderson 7263a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 727d80bff19SRichard Henderson { 728d80bff19SRichard Henderson TCGv ea, val; 729d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 730d80bff19SRichard Henderson 731d80bff19SRichard Henderson ea = tcg_temp_new(); 7328bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 733d80bff19SRichard Henderson 734d80bff19SRichard Henderson lab_fail = gen_new_label(); 735d80bff19SRichard Henderson lab_done = gen_new_label(); 736d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 737d80bff19SRichard Henderson tcg_temp_free(ea); 738d80bff19SRichard Henderson 739d80bff19SRichard Henderson val = tcg_temp_new(); 740d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 7414d10fa0fSRichard Henderson cpu_R(dc, a->b), dc->mem_idx, MO_TEUL); 742d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 743d80bff19SRichard Henderson tcg_temp_free(val); 744d80bff19SRichard Henderson 745d80bff19SRichard Henderson tcg_gen_br(lab_done); 746d80bff19SRichard Henderson 747d80bff19SRichard Henderson gen_set_label(lab_fail); 748d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 749d80bff19SRichard Henderson 750d80bff19SRichard Henderson gen_set_label(lab_done); 751d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 752d80bff19SRichard Henderson return true; 753d80bff19SRichard Henderson } 754d80bff19SRichard Henderson 75514776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 756d80bff19SRichard Henderson { 757d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7588bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7598bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 760d80bff19SRichard Henderson tcg_temp_free(t0); 761d80bff19SRichard Henderson } 762d80bff19SRichard Henderson 7633a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 764d80bff19SRichard Henderson { 765d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 766d80bff19SRichard Henderson return true; 767d80bff19SRichard Henderson } 768d80bff19SRichard Henderson 7693a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 770d80bff19SRichard Henderson { 771d80bff19SRichard Henderson do_store(dc, a, MO_UB); 772d80bff19SRichard Henderson return true; 773d80bff19SRichard Henderson } 774d80bff19SRichard Henderson 7753a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 776d80bff19SRichard Henderson { 777d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 778d80bff19SRichard Henderson return true; 779d80bff19SRichard Henderson } 780d80bff19SRichard Henderson 7813a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 782bbe418f2SJia Liu { 7838816f70bSRichard Henderson return true; 7848816f70bSRichard Henderson } 7858816f70bSRichard Henderson 7863e0e41efSRichard Henderson static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a) 7873e0e41efSRichard Henderson { 7883e0e41efSRichard Henderson if (!check_v1_3(dc)) { 7893e0e41efSRichard Henderson return false; 7903e0e41efSRichard Henderson } 7913e0e41efSRichard Henderson check_r0_write(dc, a->d); 7923e0e41efSRichard Henderson 7933e0e41efSRichard Henderson tcg_gen_movi_i32(cpu_R(dc, a->d), 7943e0e41efSRichard Henderson (dc->base.pc_next & TARGET_PAGE_MASK) + 7953e0e41efSRichard Henderson ((target_long)a->i << TARGET_PAGE_BITS)); 7963e0e41efSRichard Henderson return true; 7973e0e41efSRichard Henderson } 7983e0e41efSRichard Henderson 7993a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 8008816f70bSRichard Henderson { 801cdd0f459SRichard Henderson check_r0_write(dc, a->d); 802af42d354SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8038816f70bSRichard Henderson return true; 8048816f70bSRichard Henderson } 805bbe418f2SJia Liu 8063a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 807bbe418f2SJia Liu { 808cdd0f459SRichard Henderson check_r0_write(dc, a->d); 809af42d354SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8108816f70bSRichard Henderson return true; 8118816f70bSRichard Henderson } 8128816f70bSRichard Henderson 8133a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8148816f70bSRichard Henderson { 815cdd0f459SRichard Henderson check_r0_write(dc, a->d); 816af42d354SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8178816f70bSRichard Henderson return true; 8188816f70bSRichard Henderson } 8198816f70bSRichard Henderson 8203a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8218816f70bSRichard Henderson { 822af42d354SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8238816f70bSRichard Henderson return true; 8248816f70bSRichard Henderson } 8258816f70bSRichard Henderson 8263a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8278816f70bSRichard Henderson { 828cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8298bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8308816f70bSRichard Henderson return true; 8318816f70bSRichard Henderson } 8328816f70bSRichard Henderson 8333a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8348816f70bSRichard Henderson { 835cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8368bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8378816f70bSRichard Henderson return true; 8388816f70bSRichard Henderson } 8398816f70bSRichard Henderson 8403a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8418816f70bSRichard Henderson { 842cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8438bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8448816f70bSRichard Henderson return true; 8458816f70bSRichard Henderson } 8468816f70bSRichard Henderson 8473a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8488816f70bSRichard Henderson { 849cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8508816f70bSRichard Henderson 8512ba65417SRichard Henderson if (is_user(dc)) { 852bbe418f2SJia Liu gen_illegal_exception(dc); 8538816f70bSRichard Henderson } else { 854c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 855b9e40bacSPavel Dovgalyuk 856b9e40bacSPavel Dovgalyuk if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { 857b9e40bacSPavel Dovgalyuk gen_io_start(); 858b9e40bacSPavel Dovgalyuk if (dc->delayed_branch) { 859b9e40bacSPavel Dovgalyuk tcg_gen_mov_tl(cpu_pc, jmp_pc); 860b9e40bacSPavel Dovgalyuk tcg_gen_discard_tl(jmp_pc); 861b9e40bacSPavel Dovgalyuk } else { 862b9e40bacSPavel Dovgalyuk tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 863b9e40bacSPavel Dovgalyuk } 864b9e40bacSPavel Dovgalyuk dc->base.is_jmp = DISAS_EXIT; 865b9e40bacSPavel Dovgalyuk } 866b9e40bacSPavel Dovgalyuk 8678bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8688bba7619SRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr); 869c28fa81fSRichard Henderson tcg_temp_free(spr); 8704dd044c6SJia Liu } 8718816f70bSRichard Henderson return true; 8728816f70bSRichard Henderson } 873bbe418f2SJia Liu 8743a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 8754dd044c6SJia Liu { 8762ba65417SRichard Henderson if (is_user(dc)) { 8774dd044c6SJia Liu gen_illegal_exception(dc); 8788816f70bSRichard Henderson } else { 879c28fa81fSRichard Henderson TCGv spr; 88001ec3ec9SRichard Henderson 881b9e40bacSPavel Dovgalyuk if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { 882b9e40bacSPavel Dovgalyuk gen_io_start(); 883b9e40bacSPavel Dovgalyuk } 88401ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 88501ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 88601ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 88701ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 88801ec3ec9SRichard Henderson */ 88901ec3ec9SRichard Henderson if (dc->delayed_branch) { 89001ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 89101ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 89201ec3ec9SRichard Henderson } else { 89301ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 89401ec3ec9SRichard Henderson } 89501ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 89601ec3ec9SRichard Henderson 897c28fa81fSRichard Henderson spr = tcg_temp_new(); 8988bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 8998bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 900c28fa81fSRichard Henderson tcg_temp_free(spr); 9014dd044c6SJia Liu } 9028816f70bSRichard Henderson return true; 903bbe418f2SJia Liu } 904bbe418f2SJia Liu 9053a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 906bbe418f2SJia Liu { 9078bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 90899d863d6SRichard Henderson return true; 909bbe418f2SJia Liu } 91099d863d6SRichard Henderson 9113a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 91299d863d6SRichard Henderson { 9138bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91499d863d6SRichard Henderson return true; 91599d863d6SRichard Henderson } 91699d863d6SRichard Henderson 9173a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 91899d863d6SRichard Henderson { 9198bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92099d863d6SRichard Henderson return true; 92199d863d6SRichard Henderson } 92299d863d6SRichard Henderson 9233a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 92499d863d6SRichard Henderson { 9258bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92699d863d6SRichard Henderson return true; 927bbe418f2SJia Liu } 928bbe418f2SJia Liu 9293a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 930bbe418f2SJia Liu { 931cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9328bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9338bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 934e20c2592SRichard Henderson return true; 935bbe418f2SJia Liu } 936e20c2592SRichard Henderson 9373a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 938e20c2592SRichard Henderson { 939cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9408bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9418bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 942e20c2592SRichard Henderson return true; 943e20c2592SRichard Henderson } 944e20c2592SRichard Henderson 9453a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 946e20c2592SRichard Henderson { 947cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9488bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9498bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 950e20c2592SRichard Henderson return true; 951e20c2592SRichard Henderson } 952e20c2592SRichard Henderson 9533a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 954e20c2592SRichard Henderson { 955cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9568bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9578bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 958e20c2592SRichard Henderson return true; 959bbe418f2SJia Liu } 960bbe418f2SJia Liu 9613a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 962bbe418f2SJia Liu { 963cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9648bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 965e720a571SRichard Henderson return true; 966bbe418f2SJia Liu } 967e720a571SRichard Henderson 9683a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 969e720a571SRichard Henderson { 970cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9718bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 972e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 973e720a571SRichard Henderson return true; 974bbe418f2SJia Liu } 975bbe418f2SJia Liu 9763a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 977bbe418f2SJia Liu { 9788bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9798bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 980fbb3e29aSRichard Henderson return true; 981bbe418f2SJia Liu } 982fbb3e29aSRichard Henderson 9833a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 984fbb3e29aSRichard Henderson { 9858bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, 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_sfgtu(DisasContext *dc, arg_ab *a) 991fbb3e29aSRichard Henderson { 9928bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, 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_sfgeu(DisasContext *dc, arg_ab *a) 998fbb3e29aSRichard Henderson { 9998bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, 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_sfltu(DisasContext *dc, arg_ab *a) 1005fbb3e29aSRichard Henderson { 10068bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, 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_sfleu(DisasContext *dc, arg_ab *a) 1012fbb3e29aSRichard Henderson { 10138bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, 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_sfgts(DisasContext *dc, arg_ab *a) 1019fbb3e29aSRichard Henderson { 10208bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, 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_sfges(DisasContext *dc, arg_ab *a) 1026fbb3e29aSRichard Henderson { 10278bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, 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_sflts(DisasContext *dc, arg_ab *a) 1033fbb3e29aSRichard Henderson { 10348bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 10358bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1036fbb3e29aSRichard Henderson return true; 1037fbb3e29aSRichard Henderson } 1038fbb3e29aSRichard Henderson 10393a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1040fbb3e29aSRichard Henderson { 10418bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10428bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1043fbb3e29aSRichard Henderson return true; 1044bbe418f2SJia Liu } 1045bbe418f2SJia Liu 10463a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1047bbe418f2SJia Liu { 10488bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1049032de4fcSRichard Henderson return true; 1050bbe418f2SJia Liu } 1051032de4fcSRichard Henderson 10523a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1053032de4fcSRichard Henderson { 10548bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1055032de4fcSRichard Henderson return true; 1056032de4fcSRichard Henderson } 1057032de4fcSRichard Henderson 10583a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1059032de4fcSRichard Henderson { 10608bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1061032de4fcSRichard Henderson return true; 1062032de4fcSRichard Henderson } 1063032de4fcSRichard Henderson 10643a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1065032de4fcSRichard Henderson { 10668bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1067032de4fcSRichard Henderson return true; 1068032de4fcSRichard Henderson } 1069032de4fcSRichard Henderson 10703a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1071032de4fcSRichard Henderson { 10728bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1073032de4fcSRichard Henderson return true; 1074032de4fcSRichard Henderson } 1075032de4fcSRichard Henderson 10763a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1077032de4fcSRichard Henderson { 10788bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1079032de4fcSRichard Henderson return true; 1080032de4fcSRichard Henderson } 1081032de4fcSRichard Henderson 10823a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1083032de4fcSRichard Henderson { 10848bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1085032de4fcSRichard Henderson return true; 1086032de4fcSRichard Henderson } 1087032de4fcSRichard Henderson 10883a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1089032de4fcSRichard Henderson { 10908bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1091032de4fcSRichard Henderson return true; 1092032de4fcSRichard Henderson } 1093032de4fcSRichard Henderson 10943a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1095032de4fcSRichard Henderson { 10968bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1097032de4fcSRichard Henderson return true; 1098032de4fcSRichard Henderson } 1099032de4fcSRichard Henderson 11003a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1101032de4fcSRichard Henderson { 11028bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1103032de4fcSRichard Henderson return true; 1104bbe418f2SJia Liu } 1105bbe418f2SJia Liu 11063a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1107bbe418f2SJia Liu { 11081ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1109bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11101ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11117de9729fSRichard Henderson return true; 11127de9729fSRichard Henderson } 1113bbe418f2SJia Liu 11143a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11157de9729fSRichard Henderson { 11161ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1117bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11181ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11197de9729fSRichard Henderson return true; 11207de9729fSRichard Henderson } 1121bbe418f2SJia Liu 11223a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11237de9729fSRichard Henderson { 112424fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11257de9729fSRichard Henderson return true; 1126bbe418f2SJia Liu } 11277de9729fSRichard Henderson 11283a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11297de9729fSRichard Henderson { 11307de9729fSRichard Henderson return true; 11317de9729fSRichard Henderson } 11327de9729fSRichard Henderson 11333a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11347de9729fSRichard Henderson { 11357de9729fSRichard Henderson return true; 1136bbe418f2SJia Liu } 1137bbe418f2SJia Liu 11383a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11398816f70bSRichard Henderson { 11402ba65417SRichard Henderson if (is_user(dc)) { 11418816f70bSRichard Henderson gen_illegal_exception(dc); 11428816f70bSRichard Henderson } else { 11438816f70bSRichard Henderson gen_helper_rfe(cpu_env); 114464e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11458816f70bSRichard Henderson } 11468816f70bSRichard Henderson return true; 11478816f70bSRichard Henderson } 11488816f70bSRichard Henderson 1149fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a, 11506fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1151bbe418f2SJia Liu { 1152fe636d37SRichard Henderson if (!check_of32s(dc)) { 1153fe636d37SRichard Henderson return false; 1154fe636d37SRichard Henderson } 1155cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11568bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11574e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1158fe636d37SRichard Henderson return true; 1159bbe418f2SJia Liu } 11606fd204a2SRichard Henderson 1161fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a, 11626fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11636fd204a2SRichard Henderson { 1164fe636d37SRichard Henderson if (!check_of32s(dc)) { 1165fe636d37SRichard Henderson return false; 1166fe636d37SRichard Henderson } 1167cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11688bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11696fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1170fe636d37SRichard Henderson return true; 11716fd204a2SRichard Henderson } 11726fd204a2SRichard Henderson 1173fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a, 11746fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11756fd204a2SRichard Henderson bool inv, bool swap) 11766fd204a2SRichard Henderson { 1177fe636d37SRichard Henderson if (!check_of32s(dc)) { 1178fe636d37SRichard Henderson return false; 1179fe636d37SRichard Henderson } 11806fd204a2SRichard Henderson if (swap) { 11818bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11826fd204a2SRichard Henderson } else { 11838bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11846fd204a2SRichard Henderson } 11856fd204a2SRichard Henderson if (inv) { 11866fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11876fd204a2SRichard Henderson } 11886fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1189fe636d37SRichard Henderson return true; 11906fd204a2SRichard Henderson } 11916fd204a2SRichard Henderson 11923a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11936fd204a2SRichard Henderson { 1194fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_add_s); 11956fd204a2SRichard Henderson } 11966fd204a2SRichard Henderson 11973a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11986fd204a2SRichard Henderson { 1199fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_sub_s); 12006fd204a2SRichard Henderson } 12016fd204a2SRichard Henderson 12023a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 12036fd204a2SRichard Henderson { 1204fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_mul_s); 12056fd204a2SRichard Henderson } 12066fd204a2SRichard Henderson 12073a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12086fd204a2SRichard Henderson { 1209fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_div_s); 12106fd204a2SRichard Henderson } 12116fd204a2SRichard Henderson 12123a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12136fd204a2SRichard Henderson { 1214fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_rem_s); 12156fd204a2SRichard Henderson return true; 12166fd204a2SRichard Henderson } 12176fd204a2SRichard Henderson 12183a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12196fd204a2SRichard Henderson { 1220fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_itofs); 12216fd204a2SRichard Henderson } 12226fd204a2SRichard Henderson 12233a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12246fd204a2SRichard Henderson { 1225fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_ftois); 12266fd204a2SRichard Henderson } 12276fd204a2SRichard Henderson 12283a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12296fd204a2SRichard Henderson { 1230fe636d37SRichard Henderson if (!check_of32s(dc)) { 1231fe636d37SRichard Henderson return false; 1232fe636d37SRichard Henderson } 1233cdd0f459SRichard Henderson check_r0_write(dc, a->d); 12348bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 12358bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12366fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12376fd204a2SRichard Henderson return true; 12386fd204a2SRichard Henderson } 12396fd204a2SRichard Henderson 12403a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12416fd204a2SRichard Henderson { 1242fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12436fd204a2SRichard Henderson } 12446fd204a2SRichard Henderson 12453a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12466fd204a2SRichard Henderson { 1247fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12486fd204a2SRichard Henderson } 12496fd204a2SRichard Henderson 12503a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12516fd204a2SRichard Henderson { 1252fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12536fd204a2SRichard Henderson } 12546fd204a2SRichard Henderson 12553a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12566fd204a2SRichard Henderson { 1257fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12586fd204a2SRichard Henderson } 12596fd204a2SRichard Henderson 12603a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12616fd204a2SRichard Henderson { 1262fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12636fd204a2SRichard Henderson } 12646fd204a2SRichard Henderson 12653a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12666fd204a2SRichard Henderson { 1267fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 1268bbe418f2SJia Liu } 1269bbe418f2SJia Liu 12702b13b4b9SRichard Henderson static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a) 12712b13b4b9SRichard Henderson { 12722b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12732b13b4b9SRichard Henderson return false; 12742b13b4b9SRichard Henderson } 12752b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false); 12762b13b4b9SRichard Henderson } 12772b13b4b9SRichard Henderson 12782b13b4b9SRichard Henderson static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a) 12792b13b4b9SRichard Henderson { 12802b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12812b13b4b9SRichard Henderson return false; 12822b13b4b9SRichard Henderson } 12832b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false); 12842b13b4b9SRichard Henderson } 12852b13b4b9SRichard Henderson 12862b13b4b9SRichard Henderson static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a) 12872b13b4b9SRichard Henderson { 12882b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12892b13b4b9SRichard Henderson return false; 12902b13b4b9SRichard Henderson } 12912b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true); 12922b13b4b9SRichard Henderson } 12932b13b4b9SRichard Henderson 12942b13b4b9SRichard Henderson static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a) 12952b13b4b9SRichard Henderson { 12962b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12972b13b4b9SRichard Henderson return false; 12982b13b4b9SRichard Henderson } 12992b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false); 13002b13b4b9SRichard Henderson } 13012b13b4b9SRichard Henderson 13022b13b4b9SRichard Henderson static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a) 13032b13b4b9SRichard Henderson { 13042b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 13052b13b4b9SRichard Henderson return false; 13062b13b4b9SRichard Henderson } 13072b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true); 13082b13b4b9SRichard Henderson } 13092b13b4b9SRichard Henderson 13102b13b4b9SRichard Henderson static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a) 13112b13b4b9SRichard Henderson { 13122b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 13132b13b4b9SRichard Henderson return false; 13142b13b4b9SRichard Henderson } 13152b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_un_s, false, false); 13162b13b4b9SRichard Henderson } 13172b13b4b9SRichard Henderson 131862f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p) 131962f2b038SRichard Henderson { 132062f2b038SRichard Henderson return r + 1 + p < 32; 132162f2b038SRichard Henderson } 132262f2b038SRichard Henderson 132362f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 132462f2b038SRichard Henderson { 132562f2b038SRichard Henderson tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r)); 132662f2b038SRichard Henderson } 132762f2b038SRichard Henderson 132862f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 132962f2b038SRichard Henderson { 133062f2b038SRichard Henderson tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t); 133162f2b038SRichard Henderson } 133262f2b038SRichard Henderson 133362f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a, 133462f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 133562f2b038SRichard Henderson { 133662f2b038SRichard Henderson TCGv_i64 t0, t1; 133762f2b038SRichard Henderson 133862f2b038SRichard Henderson if (!check_of64a32s(dc) || 133962f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 134062f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 134162f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 134262f2b038SRichard Henderson return false; 134362f2b038SRichard Henderson } 134462f2b038SRichard Henderson check_r0_write(dc, a->d); 134562f2b038SRichard Henderson 134662f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 134762f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 134862f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 134962f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 135062f2b038SRichard Henderson fn(t0, cpu_env, t0, t1); 135162f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 135262f2b038SRichard Henderson tcg_temp_free_i64(t0); 135362f2b038SRichard Henderson tcg_temp_free_i64(t1); 135462f2b038SRichard Henderson 135562f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 135662f2b038SRichard Henderson return true; 135762f2b038SRichard Henderson } 135862f2b038SRichard Henderson 135962f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a, 136062f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64)) 136162f2b038SRichard Henderson { 136262f2b038SRichard Henderson TCGv_i64 t0; 136362f2b038SRichard Henderson 136462f2b038SRichard Henderson if (!check_of64a32s(dc) || 136562f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 136662f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 136762f2b038SRichard Henderson return false; 136862f2b038SRichard Henderson } 136962f2b038SRichard Henderson check_r0_write(dc, a->d); 137062f2b038SRichard Henderson 137162f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 137262f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 137362f2b038SRichard Henderson fn(t0, cpu_env, t0); 137462f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 137562f2b038SRichard Henderson tcg_temp_free_i64(t0); 137662f2b038SRichard Henderson 137762f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 137862f2b038SRichard Henderson return true; 137962f2b038SRichard Henderson } 138062f2b038SRichard Henderson 138162f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a, 138262f2b038SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64), 138362f2b038SRichard Henderson bool inv, bool swap) 138462f2b038SRichard Henderson { 138562f2b038SRichard Henderson TCGv_i64 t0, t1; 138662f2b038SRichard Henderson 138762f2b038SRichard Henderson if (!check_of64a32s(dc) || 138862f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 138962f2b038SRichard Henderson !check_pair(dc, a->b, a->bp)) { 139062f2b038SRichard Henderson return false; 139162f2b038SRichard Henderson } 139262f2b038SRichard Henderson 139362f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 139462f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 139562f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 139662f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 139762f2b038SRichard Henderson if (swap) { 139862f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t1, t0); 139962f2b038SRichard Henderson } else { 140062f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t0, t1); 140162f2b038SRichard Henderson } 140262f2b038SRichard Henderson tcg_temp_free_i64(t0); 140362f2b038SRichard Henderson tcg_temp_free_i64(t1); 140462f2b038SRichard Henderson 140562f2b038SRichard Henderson if (inv) { 140662f2b038SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 140762f2b038SRichard Henderson } 140862f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 140962f2b038SRichard Henderson return true; 141062f2b038SRichard Henderson } 141162f2b038SRichard Henderson 141262f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a) 141362f2b038SRichard Henderson { 141462f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_add_d); 141562f2b038SRichard Henderson } 141662f2b038SRichard Henderson 141762f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a) 141862f2b038SRichard Henderson { 141962f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_sub_d); 142062f2b038SRichard Henderson } 142162f2b038SRichard Henderson 142262f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a) 142362f2b038SRichard Henderson { 142462f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_mul_d); 142562f2b038SRichard Henderson } 142662f2b038SRichard Henderson 142762f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a) 142862f2b038SRichard Henderson { 142962f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_div_d); 143062f2b038SRichard Henderson } 143162f2b038SRichard Henderson 143262f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a) 143362f2b038SRichard Henderson { 143462f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_rem_d); 143562f2b038SRichard Henderson } 143662f2b038SRichard Henderson 143762f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a) 143862f2b038SRichard Henderson { 143962f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_itofd); 144062f2b038SRichard Henderson } 144162f2b038SRichard Henderson 144262f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a) 144362f2b038SRichard Henderson { 144462f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_ftoid); 144562f2b038SRichard Henderson } 144662f2b038SRichard Henderson 144762f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a) 144862f2b038SRichard Henderson { 144962f2b038SRichard Henderson TCGv_i64 t0; 145062f2b038SRichard Henderson 145162f2b038SRichard Henderson if (!check_of64a32s(dc) || 145262f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 145362f2b038SRichard Henderson return false; 145462f2b038SRichard Henderson } 145562f2b038SRichard Henderson check_r0_write(dc, a->d); 145662f2b038SRichard Henderson 145762f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 145862f2b038SRichard Henderson gen_helper_stod(t0, cpu_env, cpu_R(dc, a->a)); 145962f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 146062f2b038SRichard Henderson tcg_temp_free_i64(t0); 146162f2b038SRichard Henderson 146262f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 146362f2b038SRichard Henderson return true; 146462f2b038SRichard Henderson } 146562f2b038SRichard Henderson 146662f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a) 146762f2b038SRichard Henderson { 146862f2b038SRichard Henderson TCGv_i64 t0; 146962f2b038SRichard Henderson 147062f2b038SRichard Henderson if (!check_of64a32s(dc) || 147162f2b038SRichard Henderson !check_pair(dc, a->a, a->ap)) { 147262f2b038SRichard Henderson return false; 147362f2b038SRichard Henderson } 147462f2b038SRichard Henderson check_r0_write(dc, a->d); 147562f2b038SRichard Henderson 147662f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 147762f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 147862f2b038SRichard Henderson gen_helper_dtos(cpu_R(dc, a->d), cpu_env, t0); 147962f2b038SRichard Henderson tcg_temp_free_i64(t0); 148062f2b038SRichard Henderson 148162f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 148262f2b038SRichard Henderson return true; 148362f2b038SRichard Henderson } 148462f2b038SRichard Henderson 148562f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a) 148662f2b038SRichard Henderson { 148762f2b038SRichard Henderson TCGv_i64 t0, t1, t2; 148862f2b038SRichard Henderson 148962f2b038SRichard Henderson if (!check_of64a32s(dc) || 149062f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 149162f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 149262f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 149362f2b038SRichard Henderson return false; 149462f2b038SRichard Henderson } 149562f2b038SRichard Henderson check_r0_write(dc, a->d); 149662f2b038SRichard Henderson 149762f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 149862f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 149962f2b038SRichard Henderson t2 = tcg_temp_new_i64(); 150062f2b038SRichard Henderson load_pair(dc, t0, a->d, a->dp); 150162f2b038SRichard Henderson load_pair(dc, t1, a->a, a->ap); 150262f2b038SRichard Henderson load_pair(dc, t2, a->b, a->bp); 150362f2b038SRichard Henderson gen_helper_float_madd_d(t0, cpu_env, t0, t1, t2); 150462f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 150562f2b038SRichard Henderson tcg_temp_free_i64(t0); 150662f2b038SRichard Henderson tcg_temp_free_i64(t1); 150762f2b038SRichard Henderson tcg_temp_free_i64(t2); 150862f2b038SRichard Henderson 150962f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 151062f2b038SRichard Henderson return true; 151162f2b038SRichard Henderson } 151262f2b038SRichard Henderson 151362f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a) 151462f2b038SRichard Henderson { 151562f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false); 151662f2b038SRichard Henderson } 151762f2b038SRichard Henderson 151862f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a) 151962f2b038SRichard Henderson { 152062f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false); 152162f2b038SRichard Henderson } 152262f2b038SRichard Henderson 152362f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a) 152462f2b038SRichard Henderson { 152562f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true); 152662f2b038SRichard Henderson } 152762f2b038SRichard Henderson 152862f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a) 152962f2b038SRichard Henderson { 153062f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, true); 153162f2b038SRichard Henderson } 153262f2b038SRichard Henderson 153362f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a) 153462f2b038SRichard Henderson { 153562f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false); 153662f2b038SRichard Henderson } 153762f2b038SRichard Henderson 153862f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a) 153962f2b038SRichard Henderson { 154062f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, false); 154162f2b038SRichard Henderson } 154262f2b038SRichard Henderson 15432b13b4b9SRichard Henderson static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a) 15442b13b4b9SRichard Henderson { 15452b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false); 15462b13b4b9SRichard Henderson } 15472b13b4b9SRichard Henderson 15482b13b4b9SRichard Henderson static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a) 15492b13b4b9SRichard Henderson { 15502b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false); 15512b13b4b9SRichard Henderson } 15522b13b4b9SRichard Henderson 15532b13b4b9SRichard Henderson static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a) 15542b13b4b9SRichard Henderson { 15552b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true); 15562b13b4b9SRichard Henderson } 15572b13b4b9SRichard Henderson 15582b13b4b9SRichard Henderson static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a) 15592b13b4b9SRichard Henderson { 15602b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false); 15612b13b4b9SRichard Henderson } 15622b13b4b9SRichard Henderson 15632b13b4b9SRichard Henderson static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a) 15642b13b4b9SRichard Henderson { 15652b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true); 15662b13b4b9SRichard Henderson } 15672b13b4b9SRichard Henderson 15682b13b4b9SRichard Henderson static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a) 15692b13b4b9SRichard Henderson { 15702b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_un_d, false, false); 15712b13b4b9SRichard Henderson } 15722b13b4b9SRichard Henderson 1573a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1574e67db06eSJia Liu { 1575a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 15769c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1577a4fd3ec3SEmilio G. Cota int bound; 1578bbe418f2SJia Liu 1579a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 15801ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1581a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1582fe636d37SRichard Henderson dc->cpucfgr = env->cpucfgr; 15832b13b4b9SRichard Henderson dc->avr = env->avr; 15848000ba56SRichard Henderson dc->jmp_pc_imm = -1; 15858000ba56SRichard Henderson 1586a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1587a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1588190ce7fbSRichard Henderson } 1589bbe418f2SJia Liu 1590a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1591a4fd3ec3SEmilio G. Cota { 1592a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1593bbe418f2SJia Liu 15946597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15956597c28dSRichard Henderson when it's true, which is the common case. */ 1596118671f0SRichard Henderson dc->zero = tcg_constant_tl(0); 15976597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1598118671f0SRichard Henderson dc->R0 = dc->zero; 15996597c28dSRichard Henderson } else { 1600d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 16016597c28dSRichard Henderson } 1602a4fd3ec3SEmilio G. Cota } 16036597c28dSRichard Henderson 1604a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1605a4fd3ec3SEmilio G. Cota { 1606a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1607a4fd3ec3SEmilio G. Cota 16081ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1609a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1610a4fd3ec3SEmilio G. Cota } 1611bbe418f2SJia Liu 1612a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1613a4fd3ec3SEmilio G. Cota { 1614a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1615a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 16164e116893SIlya Leoshkevich uint32_t insn = translator_ldl(&cpu->env, &dc->base, dc->base.pc_next); 1617a4fd3ec3SEmilio G. Cota 1618c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1619c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1620c7b6f54bSRichard Henderson } 16211ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 162224c32852SRichard Henderson 16238000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 16248000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 16258000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 16268000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 16278000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 16288000ba56SRichard Henderson */ 16298000ba56SRichard Henderson if (dc->delayed_branch 16308000ba56SRichard Henderson && --dc->delayed_branch == 0 16318000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 16328000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1633bbe418f2SJia Liu } 1634a4fd3ec3SEmilio G. Cota } 1635bbe418f2SJia Liu 1636a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1637a4fd3ec3SEmilio G. Cota { 1638a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 16398000ba56SRichard Henderson target_ulong jmp_dest; 164024c32852SRichard Henderson 1641e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1642e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1643e0a369cfSRichard Henderson return; 1644e0a369cfSRichard Henderson } 1645e0a369cfSRichard Henderson 16468000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1647a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1648a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1649a01deb36SRichard Henderson } 1650a01deb36SRichard Henderson 16518000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 16528000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 16538000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 16548000ba56SRichard Henderson 16551ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 16568000ba56SRichard Henderson case DISAS_JUMP: 16578000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 16588000ba56SRichard Henderson if (jmp_dest == -1) { 16598000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 16608000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 16618000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16628000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 1663bbe418f2SJia Liu break; 16648000ba56SRichard Henderson } 16658000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 16668000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 16678000ba56SRichard Henderson we know now that it wasn't needed. */ 16688000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16698000ba56SRichard Henderson /* fallthru */ 16708000ba56SRichard Henderson 16718000ba56SRichard Henderson case DISAS_TOO_MANY: 1672adf1f3deSRichard Henderson if (translator_use_goto_tb(&dc->base, jmp_dest)) { 16738000ba56SRichard Henderson tcg_gen_goto_tb(0); 16748000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16758000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 1676adf1f3deSRichard Henderson break; 1677adf1f3deSRichard Henderson } 1678adf1f3deSRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 1679adf1f3deSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 16808000ba56SRichard Henderson break; 16818000ba56SRichard Henderson 168264e46c95SRichard Henderson case DISAS_EXIT: 168307ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1684bbe418f2SJia Liu break; 1685a4fd3ec3SEmilio G. Cota default: 1686a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1687a4fd3ec3SEmilio G. Cota } 1688bbe418f2SJia Liu } 1689bbe418f2SJia Liu 16908eb806a7SRichard Henderson static void openrisc_tr_disas_log(const DisasContextBase *dcbase, 16918eb806a7SRichard Henderson CPUState *cs, FILE *logfile) 1692a4fd3ec3SEmilio G. Cota { 1693a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 16940a7df5daSRichard Henderson 16958eb806a7SRichard Henderson fprintf(logfile, "IN: %s\n", lookup_symbol(s->base.pc_first)); 16968eb806a7SRichard Henderson target_disas(logfile, cs, s->base.pc_first, s->base.tb->size); 1697bbe418f2SJia Liu } 1698a4fd3ec3SEmilio G. Cota 1699a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1700a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1701a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1702a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1703a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1704a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1705a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1706a4fd3ec3SEmilio G. Cota }; 1707a4fd3ec3SEmilio G. Cota 1708*306c8721SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, 1709*306c8721SRichard Henderson target_ulong pc, void *host_pc) 1710a4fd3ec3SEmilio G. Cota { 1711a4fd3ec3SEmilio G. Cota DisasContext ctx; 1712a4fd3ec3SEmilio G. Cota 1713*306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, 1714*306c8721SRichard Henderson &openrisc_tr_ops, &ctx.base); 1715e67db06eSJia Liu } 1716e67db06eSJia Liu 171790c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1718e67db06eSJia Liu { 1719878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1720878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1721e67db06eSJia Liu int i; 1722878096eeSAndreas Färber 172390c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1724e67db06eSJia Liu for (i = 0; i < 32; ++i) { 172590c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1726e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1727e67db06eSJia Liu } 1728e67db06eSJia Liu } 1729e67db06eSJia Liu 1730e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1731bad729e2SRichard Henderson target_ulong *data) 1732e67db06eSJia Liu { 1733bad729e2SRichard Henderson env->pc = data[0]; 1734a01deb36SRichard Henderson env->dflag = data[1] & 1; 1735a01deb36SRichard Henderson if (data[1] & 2) { 173624c32852SRichard Henderson env->ppc = env->pc - 4; 173724c32852SRichard Henderson } 1738e67db06eSJia Liu } 1739