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; 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. */ 67abff1abfSPaolo Bonzini #include "decode-insns.c.inc" 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 { 132af42d354SRichard Henderson gen_helper_exception(cpu_env, tcg_constant_i32(excp)); 133bbe418f2SJia Liu } 134bbe418f2SJia Liu 135bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc) 136bbe418f2SJia Liu { 1371ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 138bbe418f2SJia Liu gen_exception(dc, EXCP_ILLEGAL); 1391ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 140bbe418f2SJia Liu } 141bbe418f2SJia Liu 1422b13b4b9SRichard Henderson static bool check_v1_3(DisasContext *dc) 1432b13b4b9SRichard Henderson { 1442b13b4b9SRichard Henderson return dc->avr >= 0x01030000; 1452b13b4b9SRichard Henderson } 1462b13b4b9SRichard Henderson 147fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc) 148bbe418f2SJia Liu { 149fe636d37SRichard Henderson return dc->cpucfgr & CPUCFGR_OF32S; 150bbe418f2SJia Liu } 151bbe418f2SJia Liu 15262f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc) 15362f2b038SRichard Henderson { 15462f2b038SRichard Henderson return dc->cpucfgr & CPUCFGR_OF64A32S; 15562f2b038SRichard Henderson } 15662f2b038SRichard Henderson 1578bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1588bba7619SRichard Henderson { 159d29f4368SRichard Henderson if (reg == 0) { 160d29f4368SRichard Henderson return dc->R0; 161d29f4368SRichard Henderson } else { 1628bba7619SRichard Henderson return cpu_regs[reg]; 1638bba7619SRichard Henderson } 164d29f4368SRichard Henderson } 1658bba7619SRichard Henderson 166cdd0f459SRichard Henderson /* 167cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 168cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 169cdd0f459SRichard Henderson */ 170cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 171cdd0f459SRichard Henderson { 172cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 173d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 174cdd0f459SRichard Henderson } 175cdd0f459SRichard Henderson } 1766597c28dSRichard Henderson 17797458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1789ecaa27eSRichard Henderson { 1790c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18097458071SRichard Henderson gen_helper_ove_cy(cpu_env); 1819ecaa27eSRichard Henderson } 1820c53d734SRichard Henderson } 1839ecaa27eSRichard Henderson 18497458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1859ecaa27eSRichard Henderson { 1860c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 18797458071SRichard Henderson gen_helper_ove_ov(cpu_env); 1889ecaa27eSRichard Henderson } 1890c53d734SRichard Henderson } 1909ecaa27eSRichard Henderson 19197458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1929ecaa27eSRichard Henderson { 1930c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19497458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 1959ecaa27eSRichard Henderson } 1960c53d734SRichard Henderson } 1979ecaa27eSRichard Henderson 1989ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 1999ecaa27eSRichard Henderson { 2009ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2019ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2029ecaa27eSRichard Henderson 20397458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 20497458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2059ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 20697458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2079ecaa27eSRichard Henderson tcg_temp_free(t0); 2089ecaa27eSRichard Henderson 2099ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2109ecaa27eSRichard Henderson tcg_temp_free(res); 2119ecaa27eSRichard Henderson 21297458071SRichard Henderson gen_ove_cyov(dc); 2139ecaa27eSRichard Henderson } 2149ecaa27eSRichard Henderson 2159ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2169ecaa27eSRichard Henderson { 2179ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2189ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2199ecaa27eSRichard Henderson 22097458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 22197458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 22297458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2239ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22497458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2259ecaa27eSRichard Henderson tcg_temp_free(t0); 2269ecaa27eSRichard Henderson 2279ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2289ecaa27eSRichard Henderson tcg_temp_free(res); 2299ecaa27eSRichard Henderson 23097458071SRichard Henderson gen_ove_cyov(dc); 2319ecaa27eSRichard Henderson } 2329ecaa27eSRichard Henderson 2339ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2349ecaa27eSRichard Henderson { 2359ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2369ecaa27eSRichard Henderson 2379ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 23897458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 23997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 24097458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 24197458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2429ecaa27eSRichard Henderson 2439ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2449ecaa27eSRichard Henderson tcg_temp_free(res); 2459ecaa27eSRichard Henderson 24697458071SRichard Henderson gen_ove_cyov(dc); 2479ecaa27eSRichard Henderson } 2489ecaa27eSRichard Henderson 2499ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2509ecaa27eSRichard Henderson { 2519ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2529ecaa27eSRichard Henderson 25397458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2549ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 25597458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2569ecaa27eSRichard Henderson tcg_temp_free(t0); 2579ecaa27eSRichard Henderson 25897458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 25997458071SRichard Henderson gen_ove_ov(dc); 2609ecaa27eSRichard Henderson } 2619ecaa27eSRichard Henderson 2629ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2639ecaa27eSRichard Henderson { 26497458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 26597458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2669ecaa27eSRichard Henderson 26797458071SRichard Henderson gen_ove_cy(dc); 2689ecaa27eSRichard Henderson } 2699ecaa27eSRichard Henderson 2709ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2719ecaa27eSRichard Henderson { 2729ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2739ecaa27eSRichard Henderson 27497458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2759ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2769ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 27797458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2789ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2799ecaa27eSRichard Henderson tcg_temp_free(t0); 2809ecaa27eSRichard Henderson 28197458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 28297458071SRichard Henderson gen_ove_ov(dc); 2839ecaa27eSRichard Henderson } 2849ecaa27eSRichard Henderson 2859ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2869ecaa27eSRichard Henderson { 2879ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2889ecaa27eSRichard Henderson 28997458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2909ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2919ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 29297458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2939ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2949ecaa27eSRichard Henderson tcg_temp_free(t0); 2959ecaa27eSRichard Henderson 29697458071SRichard Henderson gen_ove_cy(dc); 2979ecaa27eSRichard Henderson } 298da1d7759SSebastian Macke 299cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 300cc5de49eSRichard Henderson { 301cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 302cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 303cc5de49eSRichard Henderson 304cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 305cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 306cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 307cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 308cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 309cc5de49eSRichard Henderson } else { 310cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 311cc5de49eSRichard Henderson 312cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 313cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 314cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 315cc5de49eSRichard Henderson tcg_temp_free_i64(high); 316cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 317cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 318cc5de49eSRichard Henderson 319cc5de49eSRichard Henderson gen_ove_ov(dc); 320cc5de49eSRichard Henderson } 321cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 322cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 323cc5de49eSRichard Henderson } 324cc5de49eSRichard Henderson 325cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 326cc5de49eSRichard Henderson { 327cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 328cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 329cc5de49eSRichard Henderson 330cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 331cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 332cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 333cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 334cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 335cc5de49eSRichard Henderson } else { 336cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 337cc5de49eSRichard Henderson 338cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 339cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 340cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 341cc5de49eSRichard Henderson tcg_temp_free_i64(high); 342cc5de49eSRichard Henderson 343cc5de49eSRichard Henderson gen_ove_cy(dc); 344cc5de49eSRichard Henderson } 345cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 346cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 347cc5de49eSRichard Henderson } 348cc5de49eSRichard Henderson 3496f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3506f7332baSRichard Henderson { 3516f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3526f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3536f7332baSRichard Henderson 3546f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3556f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3566f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3576f7332baSRichard Henderson 3586f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3596f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3606f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3616f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3626f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3636f7332baSRichard Henderson tcg_temp_free_i64(t2); 3646f7332baSRichard Henderson 3656f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3666f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3676f7332baSRichard Henderson #else 3686f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3696f7332baSRichard Henderson #endif 3706f7332baSRichard Henderson tcg_temp_free_i64(t1); 3716f7332baSRichard Henderson 3726f7332baSRichard Henderson gen_ove_ov(dc); 3736f7332baSRichard Henderson } 3746f7332baSRichard Henderson 375cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 376cc5de49eSRichard Henderson { 377cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 378cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 379cc5de49eSRichard Henderson 380cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 381cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 382cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 383cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 384cc5de49eSRichard Henderson 385cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 386cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 387cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 388cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 389cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 390cc5de49eSRichard Henderson 391cc5de49eSRichard Henderson gen_ove_cy(dc); 392cc5de49eSRichard Henderson } 393cc5de49eSRichard Henderson 3946f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3956f7332baSRichard Henderson { 3966f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3976f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3986f7332baSRichard Henderson 3996f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4006f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4016f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4026f7332baSRichard Henderson 4036f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4046f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4056f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4066f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4076f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4086f7332baSRichard Henderson tcg_temp_free_i64(t2); 4096f7332baSRichard Henderson 4106f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4116f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4126f7332baSRichard Henderson #else 4136f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4146f7332baSRichard Henderson #endif 4156f7332baSRichard Henderson tcg_temp_free_i64(t1); 4166f7332baSRichard Henderson 4176f7332baSRichard Henderson gen_ove_ov(dc); 4186f7332baSRichard Henderson } 4196f7332baSRichard Henderson 420cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 421cc5de49eSRichard Henderson { 422cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 423cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 424cc5de49eSRichard Henderson 425cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 426cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 427cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 428cc5de49eSRichard Henderson 429cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 430cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 431cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 432cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 433cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 434cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 435cc5de49eSRichard Henderson 436cc5de49eSRichard Henderson gen_ove_cy(dc); 437cc5de49eSRichard Henderson } 438cc5de49eSRichard Henderson 4393a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 440bbe418f2SJia Liu { 441cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4428bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4436ad216abSRichard Henderson return true; 444bbe418f2SJia Liu } 445bbe418f2SJia Liu 4463a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 447bbe418f2SJia Liu { 448cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4498bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4506ad216abSRichard Henderson return true; 4516ad216abSRichard Henderson } 4526ad216abSRichard Henderson 4533a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4546ad216abSRichard Henderson { 455cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4568bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4576ad216abSRichard Henderson return true; 4586ad216abSRichard Henderson } 4596ad216abSRichard Henderson 4603a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4616ad216abSRichard Henderson { 462cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4638bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4646ad216abSRichard Henderson return true; 4656ad216abSRichard Henderson } 4666ad216abSRichard Henderson 4673a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4686ad216abSRichard Henderson { 469cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4708bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4716ad216abSRichard Henderson return true; 4726ad216abSRichard Henderson } 4736ad216abSRichard Henderson 4743a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4756ad216abSRichard Henderson { 476cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4778bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4786ad216abSRichard Henderson return true; 4796ad216abSRichard Henderson } 4806ad216abSRichard Henderson 4813a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4826ad216abSRichard Henderson { 483cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4848bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4856ad216abSRichard Henderson return true; 4866ad216abSRichard Henderson } 4876ad216abSRichard Henderson 4883a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4896ad216abSRichard Henderson { 490cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4918bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4926ad216abSRichard Henderson return true; 4936ad216abSRichard Henderson } 4946ad216abSRichard Henderson 4953a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 4966ad216abSRichard Henderson { 497cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4988bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4996ad216abSRichard Henderson return true; 5006ad216abSRichard Henderson } 5016ad216abSRichard Henderson 5023a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 5036ad216abSRichard Henderson { 504cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5058bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5066ad216abSRichard Henderson return true; 5076ad216abSRichard Henderson } 5086ad216abSRichard Henderson 5093a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 5106ad216abSRichard Henderson { 511cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5128bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5136ad216abSRichard Henderson return true; 5146ad216abSRichard Henderson } 5156ad216abSRichard Henderson 5163a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 5176ad216abSRichard Henderson { 518cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5198bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5206ad216abSRichard Henderson return true; 5216ad216abSRichard Henderson } 5226ad216abSRichard Henderson 5233a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5246ad216abSRichard Henderson { 525cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5268bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5276ad216abSRichard Henderson return true; 5286ad216abSRichard Henderson } 5296ad216abSRichard Henderson 5303a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5316ad216abSRichard Henderson { 532cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5338bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5346ad216abSRichard Henderson return true; 5356ad216abSRichard Henderson } 5366ad216abSRichard Henderson 5373a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5386ad216abSRichard Henderson { 539af42d354SRichard Henderson TCGv zero = tcg_constant_tl(0); 5406ad216abSRichard Henderson 541cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5428bba7619SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, 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); 633af42d354SRichard Henderson TCGv t_zero = tcg_constant_tl(0); 634136e13aeSRichard Henderson 635136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 636136e13aeSRichard Henderson dc->delayed_branch = 2; 637136e13aeSRichard Henderson } 638136e13aeSRichard Henderson 6393a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 640136e13aeSRichard Henderson { 641136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 642136e13aeSRichard Henderson return true; 643136e13aeSRichard Henderson } 644136e13aeSRichard Henderson 6453a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 646136e13aeSRichard Henderson { 647136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 648136e13aeSRichard Henderson return true; 649136e13aeSRichard Henderson } 650136e13aeSRichard Henderson 6513a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 652136e13aeSRichard Henderson { 6538bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 654136e13aeSRichard Henderson dc->delayed_branch = 2; 655136e13aeSRichard Henderson return true; 656136e13aeSRichard Henderson } 657136e13aeSRichard Henderson 6583a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 659136e13aeSRichard Henderson { 6608bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6618bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 662136e13aeSRichard Henderson dc->delayed_branch = 2; 663136e13aeSRichard Henderson return true; 664136e13aeSRichard Henderson } 665136e13aeSRichard Henderson 6663a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 667d80bff19SRichard Henderson { 668d80bff19SRichard Henderson TCGv ea; 669d80bff19SRichard Henderson 670cdd0f459SRichard Henderson check_r0_write(dc, a->d); 671d80bff19SRichard Henderson ea = tcg_temp_new(); 6728bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6738bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 674d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6758bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 676d80bff19SRichard Henderson tcg_temp_free(ea); 677d80bff19SRichard Henderson return true; 678d80bff19SRichard Henderson } 679d80bff19SRichard Henderson 68014776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 681d80bff19SRichard Henderson { 682d80bff19SRichard Henderson TCGv ea; 683d80bff19SRichard Henderson 684cdd0f459SRichard Henderson check_r0_write(dc, a->d); 685d80bff19SRichard Henderson ea = tcg_temp_new(); 6868bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6878bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 688d80bff19SRichard Henderson tcg_temp_free(ea); 689d80bff19SRichard Henderson } 690d80bff19SRichard Henderson 6913a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 692d80bff19SRichard Henderson { 693d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 694d80bff19SRichard Henderson return true; 695d80bff19SRichard Henderson } 696d80bff19SRichard Henderson 6973a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 698d80bff19SRichard Henderson { 699d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 700d80bff19SRichard Henderson return true; 701d80bff19SRichard Henderson } 702d80bff19SRichard Henderson 7033a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 704d80bff19SRichard Henderson { 705d80bff19SRichard Henderson do_load(dc, a, MO_UB); 706d80bff19SRichard Henderson return true; 707d80bff19SRichard Henderson } 708d80bff19SRichard Henderson 7093a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 710d80bff19SRichard Henderson { 711d80bff19SRichard Henderson do_load(dc, a, MO_SB); 712d80bff19SRichard Henderson return true; 713d80bff19SRichard Henderson } 714d80bff19SRichard Henderson 7153a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 716d80bff19SRichard Henderson { 717d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 718d80bff19SRichard Henderson return true; 719d80bff19SRichard Henderson } 720d80bff19SRichard Henderson 7213a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 722d80bff19SRichard Henderson { 723d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 724d80bff19SRichard Henderson return true; 725d80bff19SRichard Henderson } 726d80bff19SRichard Henderson 7273a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 728d80bff19SRichard Henderson { 729d80bff19SRichard Henderson TCGv ea, val; 730d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 731d80bff19SRichard Henderson 732d80bff19SRichard Henderson ea = tcg_temp_new(); 7338bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 734d80bff19SRichard Henderson 735d80bff19SRichard Henderson lab_fail = gen_new_label(); 736d80bff19SRichard Henderson lab_done = gen_new_label(); 737d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 738d80bff19SRichard Henderson tcg_temp_free(ea); 739d80bff19SRichard Henderson 740d80bff19SRichard Henderson val = tcg_temp_new(); 741d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 742*4d10fa0fSRichard Henderson cpu_R(dc, a->b), dc->mem_idx, MO_TEUL); 743d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 744d80bff19SRichard Henderson tcg_temp_free(val); 745d80bff19SRichard Henderson 746d80bff19SRichard Henderson tcg_gen_br(lab_done); 747d80bff19SRichard Henderson 748d80bff19SRichard Henderson gen_set_label(lab_fail); 749d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 750d80bff19SRichard Henderson 751d80bff19SRichard Henderson gen_set_label(lab_done); 752d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 753d80bff19SRichard Henderson return true; 754d80bff19SRichard Henderson } 755d80bff19SRichard Henderson 75614776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 757d80bff19SRichard Henderson { 758d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7598bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7608bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 761d80bff19SRichard Henderson tcg_temp_free(t0); 762d80bff19SRichard Henderson } 763d80bff19SRichard Henderson 7643a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 765d80bff19SRichard Henderson { 766d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 767d80bff19SRichard Henderson return true; 768d80bff19SRichard Henderson } 769d80bff19SRichard Henderson 7703a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 771d80bff19SRichard Henderson { 772d80bff19SRichard Henderson do_store(dc, a, MO_UB); 773d80bff19SRichard Henderson return true; 774d80bff19SRichard Henderson } 775d80bff19SRichard Henderson 7763a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 777d80bff19SRichard Henderson { 778d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 779d80bff19SRichard Henderson return true; 780d80bff19SRichard Henderson } 781d80bff19SRichard Henderson 7823a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 783bbe418f2SJia Liu { 7848816f70bSRichard Henderson return true; 7858816f70bSRichard Henderson } 7868816f70bSRichard Henderson 7873e0e41efSRichard Henderson static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a) 7883e0e41efSRichard Henderson { 7893e0e41efSRichard Henderson if (!check_v1_3(dc)) { 7903e0e41efSRichard Henderson return false; 7913e0e41efSRichard Henderson } 7923e0e41efSRichard Henderson check_r0_write(dc, a->d); 7933e0e41efSRichard Henderson 7943e0e41efSRichard Henderson tcg_gen_movi_i32(cpu_R(dc, a->d), 7953e0e41efSRichard Henderson (dc->base.pc_next & TARGET_PAGE_MASK) + 7963e0e41efSRichard Henderson ((target_long)a->i << TARGET_PAGE_BITS)); 7973e0e41efSRichard Henderson return true; 7983e0e41efSRichard Henderson } 7993e0e41efSRichard Henderson 8003a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 8018816f70bSRichard Henderson { 802cdd0f459SRichard Henderson check_r0_write(dc, a->d); 803af42d354SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8048816f70bSRichard Henderson return true; 8058816f70bSRichard Henderson } 806bbe418f2SJia Liu 8073a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 808bbe418f2SJia Liu { 809cdd0f459SRichard Henderson check_r0_write(dc, a->d); 810af42d354SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8118816f70bSRichard Henderson return true; 8128816f70bSRichard Henderson } 8138816f70bSRichard Henderson 8143a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 8158816f70bSRichard Henderson { 816cdd0f459SRichard Henderson check_r0_write(dc, a->d); 817af42d354SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8188816f70bSRichard Henderson return true; 8198816f70bSRichard Henderson } 8208816f70bSRichard Henderson 8213a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 8228816f70bSRichard Henderson { 823af42d354SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i)); 8248816f70bSRichard Henderson return true; 8258816f70bSRichard Henderson } 8268816f70bSRichard Henderson 8273a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8288816f70bSRichard Henderson { 829cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8308bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8318816f70bSRichard Henderson return true; 8328816f70bSRichard Henderson } 8338816f70bSRichard Henderson 8343a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8358816f70bSRichard Henderson { 836cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8378bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8388816f70bSRichard Henderson return true; 8398816f70bSRichard Henderson } 8408816f70bSRichard Henderson 8413a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8428816f70bSRichard Henderson { 843cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8448bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8458816f70bSRichard Henderson return true; 8468816f70bSRichard Henderson } 8478816f70bSRichard Henderson 8483a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8498816f70bSRichard Henderson { 850cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8518816f70bSRichard Henderson 8522ba65417SRichard Henderson if (is_user(dc)) { 853bbe418f2SJia Liu gen_illegal_exception(dc); 8548816f70bSRichard Henderson } else { 855c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 856b9e40bacSPavel Dovgalyuk 857b9e40bacSPavel Dovgalyuk if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { 858b9e40bacSPavel Dovgalyuk gen_io_start(); 859b9e40bacSPavel Dovgalyuk if (dc->delayed_branch) { 860b9e40bacSPavel Dovgalyuk tcg_gen_mov_tl(cpu_pc, jmp_pc); 861b9e40bacSPavel Dovgalyuk tcg_gen_discard_tl(jmp_pc); 862b9e40bacSPavel Dovgalyuk } else { 863b9e40bacSPavel Dovgalyuk tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 864b9e40bacSPavel Dovgalyuk } 865b9e40bacSPavel Dovgalyuk dc->base.is_jmp = DISAS_EXIT; 866b9e40bacSPavel Dovgalyuk } 867b9e40bacSPavel Dovgalyuk 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 882b9e40bacSPavel Dovgalyuk if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { 883b9e40bacSPavel Dovgalyuk gen_io_start(); 884b9e40bacSPavel Dovgalyuk } 88501ec3ec9SRichard Henderson /* For SR, we will need to exit the TB to recognize the new 88601ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 88701ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 88801ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 88901ec3ec9SRichard Henderson */ 89001ec3ec9SRichard Henderson if (dc->delayed_branch) { 89101ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 89201ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 89301ec3ec9SRichard Henderson } else { 89401ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 89501ec3ec9SRichard Henderson } 89601ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 89701ec3ec9SRichard Henderson 898c28fa81fSRichard Henderson spr = tcg_temp_new(); 8998bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 9008bba7619SRichard Henderson gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b)); 901c28fa81fSRichard Henderson tcg_temp_free(spr); 9024dd044c6SJia Liu } 9038816f70bSRichard Henderson return true; 904bbe418f2SJia Liu } 905bbe418f2SJia Liu 9063a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 907bbe418f2SJia Liu { 9088bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 90999d863d6SRichard Henderson return true; 910bbe418f2SJia Liu } 91199d863d6SRichard Henderson 9123a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 91399d863d6SRichard Henderson { 9148bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 91599d863d6SRichard Henderson return true; 91699d863d6SRichard Henderson } 91799d863d6SRichard Henderson 9183a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 91999d863d6SRichard Henderson { 9208bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92199d863d6SRichard Henderson return true; 92299d863d6SRichard Henderson } 92399d863d6SRichard Henderson 9243a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 92599d863d6SRichard Henderson { 9268bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 92799d863d6SRichard Henderson return true; 928bbe418f2SJia Liu } 929bbe418f2SJia Liu 9303a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 931bbe418f2SJia Liu { 932cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9338bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9348bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 935e20c2592SRichard Henderson return true; 936bbe418f2SJia Liu } 937e20c2592SRichard Henderson 9383a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 939e20c2592SRichard Henderson { 940cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9418bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9428bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 943e20c2592SRichard Henderson return true; 944e20c2592SRichard Henderson } 945e20c2592SRichard Henderson 9463a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 947e20c2592SRichard Henderson { 948cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9498bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9508bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 951e20c2592SRichard Henderson return true; 952e20c2592SRichard Henderson } 953e20c2592SRichard Henderson 9543a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 955e20c2592SRichard Henderson { 956cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9578bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9588bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 959e20c2592SRichard Henderson return true; 960bbe418f2SJia Liu } 961bbe418f2SJia Liu 9623a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 963bbe418f2SJia Liu { 964cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9658bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 966e720a571SRichard Henderson return true; 967bbe418f2SJia Liu } 968e720a571SRichard Henderson 9693a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 970e720a571SRichard Henderson { 971cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9728bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 973e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 974e720a571SRichard Henderson return true; 975bbe418f2SJia Liu } 976bbe418f2SJia Liu 9773a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 978bbe418f2SJia Liu { 9798bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9808bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 981fbb3e29aSRichard Henderson return true; 982bbe418f2SJia Liu } 983fbb3e29aSRichard Henderson 9843a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 985fbb3e29aSRichard Henderson { 9868bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 9878bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 988fbb3e29aSRichard Henderson return true; 989fbb3e29aSRichard Henderson } 990fbb3e29aSRichard Henderson 9913a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 992fbb3e29aSRichard Henderson { 9938bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 9948bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 995fbb3e29aSRichard Henderson return true; 996fbb3e29aSRichard Henderson } 997fbb3e29aSRichard Henderson 9983a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 999fbb3e29aSRichard Henderson { 10008bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 10018bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1002fbb3e29aSRichard Henderson return true; 1003fbb3e29aSRichard Henderson } 1004fbb3e29aSRichard Henderson 10053a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 1006fbb3e29aSRichard Henderson { 10078bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 10088bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1009fbb3e29aSRichard Henderson return true; 1010fbb3e29aSRichard Henderson } 1011fbb3e29aSRichard Henderson 10123a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 1013fbb3e29aSRichard Henderson { 10148bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 10158bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1016fbb3e29aSRichard Henderson return true; 1017fbb3e29aSRichard Henderson } 1018fbb3e29aSRichard Henderson 10193a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 1020fbb3e29aSRichard Henderson { 10218bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 10228bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1023fbb3e29aSRichard Henderson return true; 1024fbb3e29aSRichard Henderson } 1025fbb3e29aSRichard Henderson 10263a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 1027fbb3e29aSRichard Henderson { 10288bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 10298bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1030fbb3e29aSRichard Henderson return true; 1031fbb3e29aSRichard Henderson } 1032fbb3e29aSRichard Henderson 10333a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 1034fbb3e29aSRichard Henderson { 10358bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 10368bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1037fbb3e29aSRichard Henderson return true; 1038fbb3e29aSRichard Henderson } 1039fbb3e29aSRichard Henderson 10403a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1041fbb3e29aSRichard Henderson { 10428bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10438bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1044fbb3e29aSRichard Henderson return true; 1045bbe418f2SJia Liu } 1046bbe418f2SJia Liu 10473a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1048bbe418f2SJia Liu { 10498bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1050032de4fcSRichard Henderson return true; 1051bbe418f2SJia Liu } 1052032de4fcSRichard Henderson 10533a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1054032de4fcSRichard Henderson { 10558bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1056032de4fcSRichard Henderson return true; 1057032de4fcSRichard Henderson } 1058032de4fcSRichard Henderson 10593a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1060032de4fcSRichard Henderson { 10618bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1062032de4fcSRichard Henderson return true; 1063032de4fcSRichard Henderson } 1064032de4fcSRichard Henderson 10653a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1066032de4fcSRichard Henderson { 10678bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1068032de4fcSRichard Henderson return true; 1069032de4fcSRichard Henderson } 1070032de4fcSRichard Henderson 10713a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1072032de4fcSRichard Henderson { 10738bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1074032de4fcSRichard Henderson return true; 1075032de4fcSRichard Henderson } 1076032de4fcSRichard Henderson 10773a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1078032de4fcSRichard Henderson { 10798bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1080032de4fcSRichard Henderson return true; 1081032de4fcSRichard Henderson } 1082032de4fcSRichard Henderson 10833a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1084032de4fcSRichard Henderson { 10858bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1086032de4fcSRichard Henderson return true; 1087032de4fcSRichard Henderson } 1088032de4fcSRichard Henderson 10893a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1090032de4fcSRichard Henderson { 10918bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1092032de4fcSRichard Henderson return true; 1093032de4fcSRichard Henderson } 1094032de4fcSRichard Henderson 10953a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1096032de4fcSRichard Henderson { 10978bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1098032de4fcSRichard Henderson return true; 1099032de4fcSRichard Henderson } 1100032de4fcSRichard Henderson 11013a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1102032de4fcSRichard Henderson { 11038bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1104032de4fcSRichard Henderson return true; 1105bbe418f2SJia Liu } 1106bbe418f2SJia Liu 11073a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1108bbe418f2SJia Liu { 11091ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1110bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11111ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11127de9729fSRichard Henderson return true; 11137de9729fSRichard Henderson } 1114bbe418f2SJia Liu 11153a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 11167de9729fSRichard Henderson { 11171ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1118bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11191ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11207de9729fSRichard Henderson return true; 11217de9729fSRichard Henderson } 1122bbe418f2SJia Liu 11233a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 11247de9729fSRichard Henderson { 112524fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 11267de9729fSRichard Henderson return true; 1127bbe418f2SJia Liu } 11287de9729fSRichard Henderson 11293a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 11307de9729fSRichard Henderson { 11317de9729fSRichard Henderson return true; 11327de9729fSRichard Henderson } 11337de9729fSRichard Henderson 11343a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 11357de9729fSRichard Henderson { 11367de9729fSRichard Henderson return true; 1137bbe418f2SJia Liu } 1138bbe418f2SJia Liu 11393a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11408816f70bSRichard Henderson { 11412ba65417SRichard Henderson if (is_user(dc)) { 11428816f70bSRichard Henderson gen_illegal_exception(dc); 11438816f70bSRichard Henderson } else { 11448816f70bSRichard Henderson gen_helper_rfe(cpu_env); 114564e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11468816f70bSRichard Henderson } 11478816f70bSRichard Henderson return true; 11488816f70bSRichard Henderson } 11498816f70bSRichard Henderson 1150fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a, 11516fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1152bbe418f2SJia Liu { 1153fe636d37SRichard Henderson if (!check_of32s(dc)) { 1154fe636d37SRichard Henderson return false; 1155fe636d37SRichard Henderson } 1156cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11578bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a)); 11584e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1159fe636d37SRichard Henderson return true; 1160bbe418f2SJia Liu } 11616fd204a2SRichard Henderson 1162fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a, 11636fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11646fd204a2SRichard Henderson { 1165fe636d37SRichard Henderson if (!check_of32s(dc)) { 1166fe636d37SRichard Henderson return false; 1167fe636d37SRichard Henderson } 1168cdd0f459SRichard Henderson check_r0_write(dc, a->d); 11698bba7619SRichard Henderson fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11706fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1171fe636d37SRichard Henderson return true; 11726fd204a2SRichard Henderson } 11736fd204a2SRichard Henderson 1174fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a, 11756fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11766fd204a2SRichard Henderson bool inv, bool swap) 11776fd204a2SRichard Henderson { 1178fe636d37SRichard Henderson if (!check_of32s(dc)) { 1179fe636d37SRichard Henderson return false; 1180fe636d37SRichard Henderson } 11816fd204a2SRichard Henderson if (swap) { 11828bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11836fd204a2SRichard Henderson } else { 11848bba7619SRichard Henderson fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11856fd204a2SRichard Henderson } 11866fd204a2SRichard Henderson if (inv) { 11876fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11886fd204a2SRichard Henderson } 11896fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1190fe636d37SRichard Henderson return true; 11916fd204a2SRichard Henderson } 11926fd204a2SRichard Henderson 11933a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11946fd204a2SRichard Henderson { 1195fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_add_s); 11966fd204a2SRichard Henderson } 11976fd204a2SRichard Henderson 11983a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11996fd204a2SRichard Henderson { 1200fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_sub_s); 12016fd204a2SRichard Henderson } 12026fd204a2SRichard Henderson 12033a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 12046fd204a2SRichard Henderson { 1205fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_mul_s); 12066fd204a2SRichard Henderson } 12076fd204a2SRichard Henderson 12083a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 12096fd204a2SRichard Henderson { 1210fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_div_s); 12116fd204a2SRichard Henderson } 12126fd204a2SRichard Henderson 12133a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 12146fd204a2SRichard Henderson { 1215fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_rem_s); 12166fd204a2SRichard Henderson return true; 12176fd204a2SRichard Henderson } 12186fd204a2SRichard Henderson 12193a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 12206fd204a2SRichard Henderson { 1221fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_itofs); 12226fd204a2SRichard Henderson } 12236fd204a2SRichard Henderson 12243a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 12256fd204a2SRichard Henderson { 1226fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_ftois); 12276fd204a2SRichard Henderson } 12286fd204a2SRichard Henderson 12293a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 12306fd204a2SRichard Henderson { 1231fe636d37SRichard Henderson if (!check_of32s(dc)) { 1232fe636d37SRichard Henderson return false; 1233fe636d37SRichard Henderson } 1234cdd0f459SRichard Henderson check_r0_write(dc, a->d); 12358bba7619SRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), 12368bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 12376fd204a2SRichard Henderson gen_helper_update_fpcsr(cpu_env); 12386fd204a2SRichard Henderson return true; 12396fd204a2SRichard Henderson } 12406fd204a2SRichard Henderson 12413a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12426fd204a2SRichard Henderson { 1243fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12446fd204a2SRichard Henderson } 12456fd204a2SRichard Henderson 12463a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12476fd204a2SRichard Henderson { 1248fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12496fd204a2SRichard Henderson } 12506fd204a2SRichard Henderson 12513a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12526fd204a2SRichard Henderson { 1253fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12546fd204a2SRichard Henderson } 12556fd204a2SRichard Henderson 12563a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12576fd204a2SRichard Henderson { 1258fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12596fd204a2SRichard Henderson } 12606fd204a2SRichard Henderson 12613a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12626fd204a2SRichard Henderson { 1263fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12646fd204a2SRichard Henderson } 12656fd204a2SRichard Henderson 12663a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12676fd204a2SRichard Henderson { 1268fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 1269bbe418f2SJia Liu } 1270bbe418f2SJia Liu 12712b13b4b9SRichard Henderson static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a) 12722b13b4b9SRichard Henderson { 12732b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12742b13b4b9SRichard Henderson return false; 12752b13b4b9SRichard Henderson } 12762b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false); 12772b13b4b9SRichard Henderson } 12782b13b4b9SRichard Henderson 12792b13b4b9SRichard Henderson static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a) 12802b13b4b9SRichard Henderson { 12812b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12822b13b4b9SRichard Henderson return false; 12832b13b4b9SRichard Henderson } 12842b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false); 12852b13b4b9SRichard Henderson } 12862b13b4b9SRichard Henderson 12872b13b4b9SRichard Henderson static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a) 12882b13b4b9SRichard Henderson { 12892b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12902b13b4b9SRichard Henderson return false; 12912b13b4b9SRichard Henderson } 12922b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true); 12932b13b4b9SRichard Henderson } 12942b13b4b9SRichard Henderson 12952b13b4b9SRichard Henderson static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a) 12962b13b4b9SRichard Henderson { 12972b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12982b13b4b9SRichard Henderson return false; 12992b13b4b9SRichard Henderson } 13002b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false); 13012b13b4b9SRichard Henderson } 13022b13b4b9SRichard Henderson 13032b13b4b9SRichard Henderson static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a) 13042b13b4b9SRichard Henderson { 13052b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 13062b13b4b9SRichard Henderson return false; 13072b13b4b9SRichard Henderson } 13082b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true); 13092b13b4b9SRichard Henderson } 13102b13b4b9SRichard Henderson 13112b13b4b9SRichard Henderson static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a) 13122b13b4b9SRichard Henderson { 13132b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 13142b13b4b9SRichard Henderson return false; 13152b13b4b9SRichard Henderson } 13162b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_un_s, false, false); 13172b13b4b9SRichard Henderson } 13182b13b4b9SRichard Henderson 131962f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p) 132062f2b038SRichard Henderson { 132162f2b038SRichard Henderson return r + 1 + p < 32; 132262f2b038SRichard Henderson } 132362f2b038SRichard Henderson 132462f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 132562f2b038SRichard Henderson { 132662f2b038SRichard Henderson tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r)); 132762f2b038SRichard Henderson } 132862f2b038SRichard Henderson 132962f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 133062f2b038SRichard Henderson { 133162f2b038SRichard Henderson tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t); 133262f2b038SRichard Henderson } 133362f2b038SRichard Henderson 133462f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a, 133562f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 133662f2b038SRichard Henderson { 133762f2b038SRichard Henderson TCGv_i64 t0, t1; 133862f2b038SRichard Henderson 133962f2b038SRichard Henderson if (!check_of64a32s(dc) || 134062f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 134162f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 134262f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 134362f2b038SRichard Henderson return false; 134462f2b038SRichard Henderson } 134562f2b038SRichard Henderson check_r0_write(dc, a->d); 134662f2b038SRichard Henderson 134762f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 134862f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 134962f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 135062f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 135162f2b038SRichard Henderson fn(t0, cpu_env, t0, t1); 135262f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 135362f2b038SRichard Henderson tcg_temp_free_i64(t0); 135462f2b038SRichard Henderson tcg_temp_free_i64(t1); 135562f2b038SRichard Henderson 135662f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 135762f2b038SRichard Henderson return true; 135862f2b038SRichard Henderson } 135962f2b038SRichard Henderson 136062f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a, 136162f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64)) 136262f2b038SRichard Henderson { 136362f2b038SRichard Henderson TCGv_i64 t0; 136462f2b038SRichard Henderson 136562f2b038SRichard Henderson if (!check_of64a32s(dc) || 136662f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 136762f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 136862f2b038SRichard Henderson return false; 136962f2b038SRichard Henderson } 137062f2b038SRichard Henderson check_r0_write(dc, a->d); 137162f2b038SRichard Henderson 137262f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 137362f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 137462f2b038SRichard Henderson fn(t0, cpu_env, t0); 137562f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 137662f2b038SRichard Henderson tcg_temp_free_i64(t0); 137762f2b038SRichard Henderson 137862f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 137962f2b038SRichard Henderson return true; 138062f2b038SRichard Henderson } 138162f2b038SRichard Henderson 138262f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a, 138362f2b038SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64), 138462f2b038SRichard Henderson bool inv, bool swap) 138562f2b038SRichard Henderson { 138662f2b038SRichard Henderson TCGv_i64 t0, t1; 138762f2b038SRichard Henderson 138862f2b038SRichard Henderson if (!check_of64a32s(dc) || 138962f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 139062f2b038SRichard Henderson !check_pair(dc, a->b, a->bp)) { 139162f2b038SRichard Henderson return false; 139262f2b038SRichard Henderson } 139362f2b038SRichard Henderson 139462f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 139562f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 139662f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 139762f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 139862f2b038SRichard Henderson if (swap) { 139962f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t1, t0); 140062f2b038SRichard Henderson } else { 140162f2b038SRichard Henderson fn(cpu_sr_f, cpu_env, t0, t1); 140262f2b038SRichard Henderson } 140362f2b038SRichard Henderson tcg_temp_free_i64(t0); 140462f2b038SRichard Henderson tcg_temp_free_i64(t1); 140562f2b038SRichard Henderson 140662f2b038SRichard Henderson if (inv) { 140762f2b038SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 140862f2b038SRichard Henderson } 140962f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 141062f2b038SRichard Henderson return true; 141162f2b038SRichard Henderson } 141262f2b038SRichard Henderson 141362f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a) 141462f2b038SRichard Henderson { 141562f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_add_d); 141662f2b038SRichard Henderson } 141762f2b038SRichard Henderson 141862f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a) 141962f2b038SRichard Henderson { 142062f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_sub_d); 142162f2b038SRichard Henderson } 142262f2b038SRichard Henderson 142362f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a) 142462f2b038SRichard Henderson { 142562f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_mul_d); 142662f2b038SRichard Henderson } 142762f2b038SRichard Henderson 142862f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a) 142962f2b038SRichard Henderson { 143062f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_div_d); 143162f2b038SRichard Henderson } 143262f2b038SRichard Henderson 143362f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a) 143462f2b038SRichard Henderson { 143562f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_rem_d); 143662f2b038SRichard Henderson } 143762f2b038SRichard Henderson 143862f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a) 143962f2b038SRichard Henderson { 144062f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_itofd); 144162f2b038SRichard Henderson } 144262f2b038SRichard Henderson 144362f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a) 144462f2b038SRichard Henderson { 144562f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_ftoid); 144662f2b038SRichard Henderson } 144762f2b038SRichard Henderson 144862f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a) 144962f2b038SRichard Henderson { 145062f2b038SRichard Henderson TCGv_i64 t0; 145162f2b038SRichard Henderson 145262f2b038SRichard Henderson if (!check_of64a32s(dc) || 145362f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 145462f2b038SRichard Henderson return false; 145562f2b038SRichard Henderson } 145662f2b038SRichard Henderson check_r0_write(dc, a->d); 145762f2b038SRichard Henderson 145862f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 145962f2b038SRichard Henderson gen_helper_stod(t0, cpu_env, cpu_R(dc, a->a)); 146062f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 146162f2b038SRichard Henderson tcg_temp_free_i64(t0); 146262f2b038SRichard Henderson 146362f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 146462f2b038SRichard Henderson return true; 146562f2b038SRichard Henderson } 146662f2b038SRichard Henderson 146762f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a) 146862f2b038SRichard Henderson { 146962f2b038SRichard Henderson TCGv_i64 t0; 147062f2b038SRichard Henderson 147162f2b038SRichard Henderson if (!check_of64a32s(dc) || 147262f2b038SRichard Henderson !check_pair(dc, a->a, a->ap)) { 147362f2b038SRichard Henderson return false; 147462f2b038SRichard Henderson } 147562f2b038SRichard Henderson check_r0_write(dc, a->d); 147662f2b038SRichard Henderson 147762f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 147862f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 147962f2b038SRichard Henderson gen_helper_dtos(cpu_R(dc, a->d), cpu_env, t0); 148062f2b038SRichard Henderson tcg_temp_free_i64(t0); 148162f2b038SRichard Henderson 148262f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 148362f2b038SRichard Henderson return true; 148462f2b038SRichard Henderson } 148562f2b038SRichard Henderson 148662f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a) 148762f2b038SRichard Henderson { 148862f2b038SRichard Henderson TCGv_i64 t0, t1, t2; 148962f2b038SRichard Henderson 149062f2b038SRichard Henderson if (!check_of64a32s(dc) || 149162f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 149262f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 149362f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 149462f2b038SRichard Henderson return false; 149562f2b038SRichard Henderson } 149662f2b038SRichard Henderson check_r0_write(dc, a->d); 149762f2b038SRichard Henderson 149862f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 149962f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 150062f2b038SRichard Henderson t2 = tcg_temp_new_i64(); 150162f2b038SRichard Henderson load_pair(dc, t0, a->d, a->dp); 150262f2b038SRichard Henderson load_pair(dc, t1, a->a, a->ap); 150362f2b038SRichard Henderson load_pair(dc, t2, a->b, a->bp); 150462f2b038SRichard Henderson gen_helper_float_madd_d(t0, cpu_env, t0, t1, t2); 150562f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 150662f2b038SRichard Henderson tcg_temp_free_i64(t0); 150762f2b038SRichard Henderson tcg_temp_free_i64(t1); 150862f2b038SRichard Henderson tcg_temp_free_i64(t2); 150962f2b038SRichard Henderson 151062f2b038SRichard Henderson gen_helper_update_fpcsr(cpu_env); 151162f2b038SRichard Henderson return true; 151262f2b038SRichard Henderson } 151362f2b038SRichard Henderson 151462f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a) 151562f2b038SRichard Henderson { 151662f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false); 151762f2b038SRichard Henderson } 151862f2b038SRichard Henderson 151962f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a) 152062f2b038SRichard Henderson { 152162f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false); 152262f2b038SRichard Henderson } 152362f2b038SRichard Henderson 152462f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a) 152562f2b038SRichard Henderson { 152662f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true); 152762f2b038SRichard Henderson } 152862f2b038SRichard Henderson 152962f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a) 153062f2b038SRichard Henderson { 153162f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, true); 153262f2b038SRichard Henderson } 153362f2b038SRichard Henderson 153462f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a) 153562f2b038SRichard Henderson { 153662f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false); 153762f2b038SRichard Henderson } 153862f2b038SRichard Henderson 153962f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a) 154062f2b038SRichard Henderson { 154162f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, false); 154262f2b038SRichard Henderson } 154362f2b038SRichard Henderson 15442b13b4b9SRichard Henderson static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a) 15452b13b4b9SRichard Henderson { 15462b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false); 15472b13b4b9SRichard Henderson } 15482b13b4b9SRichard Henderson 15492b13b4b9SRichard Henderson static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a) 15502b13b4b9SRichard Henderson { 15512b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false); 15522b13b4b9SRichard Henderson } 15532b13b4b9SRichard Henderson 15542b13b4b9SRichard Henderson static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a) 15552b13b4b9SRichard Henderson { 15562b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true); 15572b13b4b9SRichard Henderson } 15582b13b4b9SRichard Henderson 15592b13b4b9SRichard Henderson static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a) 15602b13b4b9SRichard Henderson { 15612b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false); 15622b13b4b9SRichard Henderson } 15632b13b4b9SRichard Henderson 15642b13b4b9SRichard Henderson static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a) 15652b13b4b9SRichard Henderson { 15662b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true); 15672b13b4b9SRichard Henderson } 15682b13b4b9SRichard Henderson 15692b13b4b9SRichard Henderson static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a) 15702b13b4b9SRichard Henderson { 15712b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_un_d, false, false); 15722b13b4b9SRichard Henderson } 15732b13b4b9SRichard Henderson 1574a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1575e67db06eSJia Liu { 1576a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 15779c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1578a4fd3ec3SEmilio G. Cota int bound; 1579bbe418f2SJia Liu 1580a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 15811ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1582a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1583fe636d37SRichard Henderson dc->cpucfgr = env->cpucfgr; 15842b13b4b9SRichard Henderson dc->avr = env->avr; 15858000ba56SRichard Henderson dc->jmp_pc_imm = -1; 15868000ba56SRichard Henderson 1587a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1588a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1589190ce7fbSRichard Henderson } 1590bbe418f2SJia Liu 1591a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1592a4fd3ec3SEmilio G. Cota { 1593a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1594bbe418f2SJia Liu 15956597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15966597c28dSRichard Henderson when it's true, which is the common case. */ 15976597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1598*4d10fa0fSRichard Henderson dc->R0 = tcg_constant_tl(0); 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 bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1613a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1614a4fd3ec3SEmilio G. Cota { 1615a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1616a4fd3ec3SEmilio G. Cota 16171ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1618b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 16191ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1620522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1621522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1622522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1623522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 16241ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1625a4fd3ec3SEmilio G. Cota return true; 1626b933066aSRichard Henderson } 1627b933066aSRichard Henderson 1628a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1629a4fd3ec3SEmilio G. Cota { 1630a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1631a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 16327f93879eSEmilio G. Cota uint32_t insn = translator_ldl(&cpu->env, dc->base.pc_next); 1633a4fd3ec3SEmilio G. Cota 1634c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1635c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1636c7b6f54bSRichard Henderson } 16371ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 163824c32852SRichard Henderson 16398000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 16408000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 16418000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 16428000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 16438000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 16448000ba56SRichard Henderson */ 16458000ba56SRichard Henderson if (dc->delayed_branch 16468000ba56SRichard Henderson && --dc->delayed_branch == 0 16478000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 16488000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1649bbe418f2SJia Liu } 1650a4fd3ec3SEmilio G. Cota } 1651bbe418f2SJia Liu 1652a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1653a4fd3ec3SEmilio G. Cota { 1654a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 16558000ba56SRichard Henderson target_ulong jmp_dest; 165624c32852SRichard Henderson 1657e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1658e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1659e0a369cfSRichard Henderson return; 1660e0a369cfSRichard Henderson } 1661e0a369cfSRichard Henderson 16628000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1663a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1664a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1665a01deb36SRichard Henderson } 1666a01deb36SRichard Henderson 16678000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 16688000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 16698000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 16708000ba56SRichard Henderson 16711ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 16728000ba56SRichard Henderson case DISAS_JUMP: 16738000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 16748000ba56SRichard Henderson if (jmp_dest == -1) { 16758000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 16768000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 16778000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16788000ba56SRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 16798000ba56SRichard Henderson gen_exception(dc, EXCP_DEBUG); 16808000ba56SRichard Henderson } else { 16818000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 16828000ba56SRichard Henderson } 1683bbe418f2SJia Liu break; 16848000ba56SRichard Henderson } 16858000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 16868000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 16878000ba56SRichard Henderson we know now that it wasn't needed. */ 16888000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16898000ba56SRichard Henderson /* fallthru */ 16908000ba56SRichard Henderson 16918000ba56SRichard Henderson case DISAS_TOO_MANY: 1692adf1f3deSRichard Henderson if (translator_use_goto_tb(&dc->base, jmp_dest)) { 16938000ba56SRichard Henderson tcg_gen_goto_tb(0); 16948000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16958000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 1696adf1f3deSRichard Henderson break; 1697adf1f3deSRichard Henderson } 1698adf1f3deSRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 1699adf1f3deSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1700adf1f3deSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1701adf1f3deSRichard Henderson } else { 1702adf1f3deSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 17038000ba56SRichard Henderson } 17048000ba56SRichard Henderson break; 17058000ba56SRichard Henderson 170664e46c95SRichard Henderson case DISAS_EXIT: 1707e0a369cfSRichard Henderson if (unlikely(dc->base.singlestep_enabled)) { 1708e0a369cfSRichard Henderson gen_exception(dc, EXCP_DEBUG); 1709e0a369cfSRichard Henderson } else { 171007ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1711e0a369cfSRichard Henderson } 1712bbe418f2SJia Liu break; 1713a4fd3ec3SEmilio G. Cota default: 1714a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1715a4fd3ec3SEmilio G. Cota } 1716bbe418f2SJia Liu } 1717bbe418f2SJia Liu 1718a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1719a4fd3ec3SEmilio G. Cota { 1720a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 17210a7df5daSRichard Henderson 1722a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1723a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1724bbe418f2SJia Liu } 1725a4fd3ec3SEmilio G. Cota 1726a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1727a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1728a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1729a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1730a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1731a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1732a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1733a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1734a4fd3ec3SEmilio G. Cota }; 1735a4fd3ec3SEmilio G. Cota 17368b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 1737a4fd3ec3SEmilio G. Cota { 1738a4fd3ec3SEmilio G. Cota DisasContext ctx; 1739a4fd3ec3SEmilio G. Cota 17408b86d6d2SRichard Henderson translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); 1741e67db06eSJia Liu } 1742e67db06eSJia Liu 174390c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1744e67db06eSJia Liu { 1745878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1746878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1747e67db06eSJia Liu int i; 1748878096eeSAndreas Färber 174990c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1750e67db06eSJia Liu for (i = 0; i < 32; ++i) { 175190c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1752e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1753e67db06eSJia Liu } 1754e67db06eSJia Liu } 1755e67db06eSJia Liu 1756e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1757bad729e2SRichard Henderson target_ulong *data) 1758e67db06eSJia Liu { 1759bad729e2SRichard Henderson env->pc = data[0]; 1760a01deb36SRichard Henderson env->dflag = data[1] & 1; 1761a01deb36SRichard Henderson if (data[1] & 2) { 176224c32852SRichard Henderson env->ppc = env->pc - 4; 176324c32852SRichard Henderson } 1764e67db06eSJia Liu } 1765