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" 24dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h" 251de7afc9SPaolo Bonzini #include "qemu/log.h" 261de7afc9SPaolo Bonzini #include "qemu/bitops.h" 2790c84c56SMarkus Armbruster #include "qemu/qemu-print.h" 2877fc6f5eSLluís Vilanova #include "exec/translator.h" 2968df8c8dSPhilippe Mathieu-Daudé #include "exec/translation-block.h" 30bbe418f2SJia Liu 312ef6175aSRichard Henderson #include "exec/helper-proto.h" 322ef6175aSRichard Henderson #include "exec/helper-gen.h" 33e67db06eSJia Liu 34508127e2SPaolo Bonzini #include "exec/log.h" 35a7e30d84SLluís Vilanova 36d53106c9SRichard Henderson #define HELPER_H "helper.h" 37d53106c9SRichard Henderson #include "exec/helper-info.c.inc" 38d53106c9SRichard Henderson #undef HELPER_H 39d53106c9SRichard Henderson 40d53106c9SRichard Henderson 4177fc6f5eSLluís Vilanova /* is_jmp field values */ 4264e46c95SRichard Henderson #define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */ 438000ba56SRichard Henderson #define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */ 4477fc6f5eSLluís Vilanova 45bbe418f2SJia Liu typedef struct DisasContext { 461ffa4bceSEmilio G. Cota DisasContextBase base; 47bbe418f2SJia Liu uint32_t mem_idx; 48a01deb36SRichard Henderson uint32_t tb_flags; 49bbe418f2SJia Liu uint32_t delayed_branch; 50fe636d37SRichard Henderson uint32_t cpucfgr; 512b13b4b9SRichard Henderson uint32_t avr; 528000ba56SRichard Henderson 538000ba56SRichard Henderson /* If not -1, jmp_pc contains this value and so is a direct jump. */ 548000ba56SRichard Henderson target_ulong jmp_pc_imm; 55d29f4368SRichard Henderson 56d29f4368SRichard Henderson /* The temporary corresponding to register 0 for this compilation. */ 57d29f4368SRichard Henderson TCGv R0; 58118671f0SRichard Henderson /* The constant zero. */ 59118671f0SRichard Henderson TCGv zero; 60bbe418f2SJia Liu } DisasContext; 61bbe418f2SJia Liu 622ba65417SRichard Henderson static inline bool is_user(DisasContext *dc) 632ba65417SRichard Henderson { 642ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY 652ba65417SRichard Henderson return true; 662ba65417SRichard Henderson #else 67b9bed1b9SRichard Henderson return !(dc->tb_flags & TB_FLAGS_SM); 682ba65417SRichard Henderson #endif 692ba65417SRichard Henderson } 702ba65417SRichard Henderson 717de9729fSRichard Henderson /* Include the auto-generated decoder. */ 72abff1abfSPaolo Bonzini #include "decode-insns.c.inc" 737de9729fSRichard Henderson 74bbe418f2SJia Liu static TCGv cpu_sr; 758bba7619SRichard Henderson static TCGv cpu_regs[32]; 76bbe418f2SJia Liu static TCGv cpu_pc; 77bbe418f2SJia Liu static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 78bbe418f2SJia Liu static TCGv cpu_ppc; 7984775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 8097458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 8197458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 82930c3d00SRichard Henderson static TCGv cpu_lock_addr; 83930c3d00SRichard Henderson static TCGv cpu_lock_value; 84bbe418f2SJia Liu static TCGv_i32 fpcsr; 856f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 86a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 87bbe418f2SJia Liu 88e67db06eSJia Liu void openrisc_translate_init(void) 89e67db06eSJia Liu { 90bbe418f2SJia Liu static const char * const regnames[] = { 91bbe418f2SJia Liu "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 92bbe418f2SJia Liu "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 93bbe418f2SJia Liu "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 94bbe418f2SJia Liu "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 95bbe418f2SJia Liu }; 96bbe418f2SJia Liu int i; 97bbe418f2SJia Liu 98ad75a51eSRichard Henderson cpu_sr = tcg_global_mem_new(tcg_env, 99bbe418f2SJia Liu offsetof(CPUOpenRISCState, sr), "sr"); 100ad75a51eSRichard Henderson cpu_dflag = tcg_global_mem_new_i32(tcg_env, 101a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 102a01deb36SRichard Henderson "dflag"); 103ad75a51eSRichard Henderson cpu_pc = tcg_global_mem_new(tcg_env, 104bbe418f2SJia Liu offsetof(CPUOpenRISCState, pc), "pc"); 105ad75a51eSRichard Henderson cpu_ppc = tcg_global_mem_new(tcg_env, 106bbe418f2SJia Liu offsetof(CPUOpenRISCState, ppc), "ppc"); 107ad75a51eSRichard Henderson jmp_pc = tcg_global_mem_new(tcg_env, 108bbe418f2SJia Liu offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 109ad75a51eSRichard Henderson cpu_sr_f = tcg_global_mem_new(tcg_env, 11084775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 111ad75a51eSRichard Henderson cpu_sr_cy = tcg_global_mem_new(tcg_env, 11297458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 113ad75a51eSRichard Henderson cpu_sr_ov = tcg_global_mem_new(tcg_env, 11497458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 115ad75a51eSRichard Henderson cpu_lock_addr = tcg_global_mem_new(tcg_env, 116930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 117930c3d00SRichard Henderson "lock_addr"); 118ad75a51eSRichard Henderson cpu_lock_value = tcg_global_mem_new(tcg_env, 119930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 120930c3d00SRichard Henderson "lock_value"); 121ad75a51eSRichard Henderson fpcsr = tcg_global_mem_new_i32(tcg_env, 122bbe418f2SJia Liu offsetof(CPUOpenRISCState, fpcsr), 123bbe418f2SJia Liu "fpcsr"); 124ad75a51eSRichard Henderson cpu_mac = tcg_global_mem_new_i64(tcg_env, 1256f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1266f7332baSRichard Henderson "mac"); 127bbe418f2SJia Liu for (i = 0; i < 32; i++) { 128ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 129d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 130d89e71e8SStafford Horne shadow_gpr[0][i]), 131bbe418f2SJia Liu regnames[i]); 132bbe418f2SJia Liu } 133bbe418f2SJia Liu } 134bbe418f2SJia Liu 135bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp) 136bbe418f2SJia Liu { 137ad75a51eSRichard Henderson gen_helper_exception(tcg_env, tcg_constant_i32(excp)); 138bbe418f2SJia Liu } 139bbe418f2SJia Liu 140bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc) 141bbe418f2SJia Liu { 1421ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 143bbe418f2SJia Liu gen_exception(dc, EXCP_ILLEGAL); 1441ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 145bbe418f2SJia Liu } 146bbe418f2SJia Liu 1472b13b4b9SRichard Henderson static bool check_v1_3(DisasContext *dc) 1482b13b4b9SRichard Henderson { 1492b13b4b9SRichard Henderson return dc->avr >= 0x01030000; 1502b13b4b9SRichard Henderson } 1512b13b4b9SRichard Henderson 152fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc) 153bbe418f2SJia Liu { 154fe636d37SRichard Henderson return dc->cpucfgr & CPUCFGR_OF32S; 155bbe418f2SJia Liu } 156bbe418f2SJia Liu 15762f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc) 15862f2b038SRichard Henderson { 15962f2b038SRichard Henderson return dc->cpucfgr & CPUCFGR_OF64A32S; 16062f2b038SRichard Henderson } 16162f2b038SRichard Henderson 1628bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg) 1638bba7619SRichard Henderson { 164d29f4368SRichard Henderson if (reg == 0) { 165d29f4368SRichard Henderson return dc->R0; 166d29f4368SRichard Henderson } else { 1678bba7619SRichard Henderson return cpu_regs[reg]; 1688bba7619SRichard Henderson } 169d29f4368SRichard Henderson } 1708bba7619SRichard Henderson 171cdd0f459SRichard Henderson /* 172cdd0f459SRichard Henderson * We're about to write to REG. On the off-chance that the user is 173cdd0f459SRichard Henderson * writing to R0, re-instate the architectural register. 174cdd0f459SRichard Henderson */ 175cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg) 176cdd0f459SRichard Henderson { 177cdd0f459SRichard Henderson if (unlikely(reg == 0)) { 178d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 179cdd0f459SRichard Henderson } 180cdd0f459SRichard Henderson } 1816597c28dSRichard Henderson 18297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1839ecaa27eSRichard Henderson { 1840c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 185ad75a51eSRichard Henderson gen_helper_ove_cy(tcg_env); 1869ecaa27eSRichard Henderson } 1870c53d734SRichard Henderson } 1889ecaa27eSRichard Henderson 18997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 1909ecaa27eSRichard Henderson { 1910c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 192ad75a51eSRichard Henderson gen_helper_ove_ov(tcg_env); 1939ecaa27eSRichard Henderson } 1940c53d734SRichard Henderson } 1959ecaa27eSRichard Henderson 19697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 1979ecaa27eSRichard Henderson { 1980c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 199ad75a51eSRichard Henderson gen_helper_ove_cyov(tcg_env); 2009ecaa27eSRichard Henderson } 2010c53d734SRichard Henderson } 2029ecaa27eSRichard Henderson 2039ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2049ecaa27eSRichard Henderson { 205e0efc48fSRichard Henderson TCGv t0 = tcg_temp_new(); 2069ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2079ecaa27eSRichard Henderson 208e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero); 20997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2109ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 21197458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2129ecaa27eSRichard Henderson 2139ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2149ecaa27eSRichard Henderson 21597458071SRichard Henderson gen_ove_cyov(dc); 2169ecaa27eSRichard Henderson } 2179ecaa27eSRichard Henderson 2189ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2199ecaa27eSRichard Henderson { 220e0efc48fSRichard Henderson TCGv t0 = tcg_temp_new(); 2219ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2229ecaa27eSRichard Henderson 223e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero); 224e0efc48fSRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero); 22597458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2269ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22797458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2289ecaa27eSRichard Henderson 2299ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2309ecaa27eSRichard Henderson 23197458071SRichard Henderson gen_ove_cyov(dc); 2329ecaa27eSRichard Henderson } 2339ecaa27eSRichard Henderson 2349ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2359ecaa27eSRichard Henderson { 2369ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2379ecaa27eSRichard Henderson 2389ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 23997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 24097458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 24197458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 24297458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2439ecaa27eSRichard Henderson 2449ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, 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); 255cfe15887SRichard Henderson tcg_gen_negsetcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2569ecaa27eSRichard Henderson 25797458071SRichard Henderson gen_ove_ov(dc); 2589ecaa27eSRichard Henderson } 2599ecaa27eSRichard Henderson 2609ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2619ecaa27eSRichard Henderson { 26297458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 26397458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2649ecaa27eSRichard Henderson 26597458071SRichard Henderson gen_ove_cy(dc); 2669ecaa27eSRichard Henderson } 2679ecaa27eSRichard Henderson 2689ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2699ecaa27eSRichard Henderson { 2709ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2719ecaa27eSRichard Henderson 27297458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2739ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2748b81968cSMichael Tokarev Suppress the host-side exception by dividing by 1. */ 27597458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2769ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2779ecaa27eSRichard Henderson 27897458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 27997458071SRichard Henderson gen_ove_ov(dc); 2809ecaa27eSRichard Henderson } 2819ecaa27eSRichard Henderson 2829ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2839ecaa27eSRichard Henderson { 2849ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2859ecaa27eSRichard Henderson 28697458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 2879ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2888b81968cSMichael Tokarev Suppress the host-side exception by dividing by 1. */ 28997458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 2909ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 2919ecaa27eSRichard Henderson 29297458071SRichard Henderson gen_ove_cy(dc); 2939ecaa27eSRichard Henderson } 294da1d7759SSebastian Macke 295cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 296cc5de49eSRichard Henderson { 297cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 298cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 299cc5de49eSRichard Henderson 300cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 301cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 302cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 303cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 304cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 305cc5de49eSRichard Henderson } else { 306cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 307cc5de49eSRichard Henderson 308cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 309cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 310cfe15887SRichard Henderson tcg_gen_negsetcond_i64(TCG_COND_NE, t1, t1, high); 311cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 312cc5de49eSRichard Henderson 313cc5de49eSRichard Henderson gen_ove_ov(dc); 314cc5de49eSRichard Henderson } 315cc5de49eSRichard Henderson } 316cc5de49eSRichard Henderson 317cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 318cc5de49eSRichard Henderson { 319cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 320cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 321cc5de49eSRichard Henderson 322cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 323cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 324cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 325cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 326cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 327cc5de49eSRichard Henderson } else { 328cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 329cc5de49eSRichard Henderson 330cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 331cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 332cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 333cc5de49eSRichard Henderson 334cc5de49eSRichard Henderson gen_ove_cy(dc); 335cc5de49eSRichard Henderson } 336cc5de49eSRichard Henderson } 337cc5de49eSRichard Henderson 3386f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3396f7332baSRichard Henderson { 3406f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3416f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3426f7332baSRichard Henderson 3436f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3446f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3456f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3466f7332baSRichard Henderson 3476f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3486f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3496f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3506f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3516f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3526f7332baSRichard Henderson 3536f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3546f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3556f7332baSRichard Henderson #else 3566f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3576f7332baSRichard Henderson #endif 3586f7332baSRichard Henderson 3596f7332baSRichard Henderson gen_ove_ov(dc); 3606f7332baSRichard Henderson } 3616f7332baSRichard Henderson 362cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 363cc5de49eSRichard Henderson { 364cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 365cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 366cc5de49eSRichard Henderson 367cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 368cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 369cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 370cc5de49eSRichard Henderson 371cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 372cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 373cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 374cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 375cc5de49eSRichard Henderson 376cc5de49eSRichard Henderson gen_ove_cy(dc); 377cc5de49eSRichard Henderson } 378cc5de49eSRichard Henderson 3796f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 3806f7332baSRichard Henderson { 3816f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3826f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3836f7332baSRichard Henderson 3846f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3856f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3866f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3876f7332baSRichard Henderson 3886f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 3896f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3906f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 3916f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3926f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 3936f7332baSRichard Henderson 3946f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3956f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3966f7332baSRichard Henderson #else 3976f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3986f7332baSRichard Henderson #endif 3996f7332baSRichard Henderson 4006f7332baSRichard Henderson gen_ove_ov(dc); 4016f7332baSRichard Henderson } 4026f7332baSRichard Henderson 403cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 404cc5de49eSRichard Henderson { 405cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 406cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 407cc5de49eSRichard Henderson 408cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 409cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 410cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 411cc5de49eSRichard Henderson 412cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 413cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 414cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 415cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 416cc5de49eSRichard Henderson 417cc5de49eSRichard Henderson gen_ove_cy(dc); 418cc5de49eSRichard Henderson } 419cc5de49eSRichard Henderson 4203a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a) 421bbe418f2SJia Liu { 422cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4238bba7619SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4246ad216abSRichard Henderson return true; 425bbe418f2SJia Liu } 426bbe418f2SJia Liu 4273a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a) 428bbe418f2SJia Liu { 429cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4308bba7619SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4316ad216abSRichard Henderson return true; 4326ad216abSRichard Henderson } 4336ad216abSRichard Henderson 4343a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a) 4356ad216abSRichard Henderson { 436cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4378bba7619SRichard Henderson gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4386ad216abSRichard Henderson return true; 4396ad216abSRichard Henderson } 4406ad216abSRichard Henderson 4413a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a) 4426ad216abSRichard Henderson { 443cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4448bba7619SRichard Henderson tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4456ad216abSRichard Henderson return true; 4466ad216abSRichard Henderson } 4476ad216abSRichard Henderson 4483a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a) 4496ad216abSRichard Henderson { 450cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4518bba7619SRichard Henderson tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4526ad216abSRichard Henderson return true; 4536ad216abSRichard Henderson } 4546ad216abSRichard Henderson 4553a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a) 4566ad216abSRichard Henderson { 457cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4588bba7619SRichard Henderson tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4596ad216abSRichard Henderson return true; 4606ad216abSRichard Henderson } 4616ad216abSRichard Henderson 4623a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a) 4636ad216abSRichard Henderson { 464cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4658bba7619SRichard Henderson tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4666ad216abSRichard Henderson return true; 4676ad216abSRichard Henderson } 4686ad216abSRichard Henderson 4693a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a) 4706ad216abSRichard Henderson { 471cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4728bba7619SRichard Henderson tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4736ad216abSRichard Henderson return true; 4746ad216abSRichard Henderson } 4756ad216abSRichard Henderson 4763a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a) 4776ad216abSRichard Henderson { 478cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4798bba7619SRichard Henderson tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4806ad216abSRichard Henderson return true; 4816ad216abSRichard Henderson } 4826ad216abSRichard Henderson 4833a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a) 4846ad216abSRichard Henderson { 485cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4868bba7619SRichard Henderson tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 4876ad216abSRichard Henderson return true; 4886ad216abSRichard Henderson } 4896ad216abSRichard Henderson 4903a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a) 4916ad216abSRichard Henderson { 492cdd0f459SRichard Henderson check_r0_write(dc, a->d); 4938bba7619SRichard Henderson tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 4946ad216abSRichard Henderson return true; 4956ad216abSRichard Henderson } 4966ad216abSRichard Henderson 4973a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a) 4986ad216abSRichard Henderson { 499cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5008bba7619SRichard Henderson tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5016ad216abSRichard Henderson return true; 5026ad216abSRichard Henderson } 5036ad216abSRichard Henderson 5043a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a) 5056ad216abSRichard Henderson { 506cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5078bba7619SRichard Henderson tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5086ad216abSRichard Henderson return true; 5096ad216abSRichard Henderson } 5106ad216abSRichard Henderson 5113a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a) 5126ad216abSRichard Henderson { 513cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5148bba7619SRichard Henderson tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a)); 5156ad216abSRichard Henderson return true; 5166ad216abSRichard Henderson } 5176ad216abSRichard Henderson 5183a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a) 5196ad216abSRichard Henderson { 520cdd0f459SRichard Henderson check_r0_write(dc, a->d); 521118671f0SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero, 5228bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 5236ad216abSRichard Henderson return true; 524bbe418f2SJia Liu } 525bbe418f2SJia Liu 5263a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a) 5276ad216abSRichard Henderson { 528cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5298bba7619SRichard Henderson tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1); 5308bba7619SRichard Henderson tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1); 5316ad216abSRichard Henderson return true; 532cf2ae442SRichard Henderson } 533cf2ae442SRichard Henderson 5343a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a) 5356ad216abSRichard Henderson { 536cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5378bba7619SRichard Henderson tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS); 5388bba7619SRichard Henderson tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d)); 5396ad216abSRichard Henderson return true; 540bbe418f2SJia Liu } 541bbe418f2SJia Liu 5423a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a) 5436ad216abSRichard Henderson { 544cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5458bba7619SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5466ad216abSRichard Henderson return true; 547bbe418f2SJia Liu } 5486ad216abSRichard Henderson 5493a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a) 5506ad216abSRichard Henderson { 551cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5528bba7619SRichard Henderson gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5536ad216abSRichard Henderson return true; 554bbe418f2SJia Liu } 5556ad216abSRichard Henderson 5563a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a) 5576ad216abSRichard Henderson { 558cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5598bba7619SRichard Henderson gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5606ad216abSRichard Henderson return true; 5616ad216abSRichard Henderson } 5626ad216abSRichard Henderson 5633a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a) 5646ad216abSRichard Henderson { 565cdd0f459SRichard Henderson check_r0_write(dc, a->d); 5668bba7619SRichard Henderson gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b)); 5676ad216abSRichard Henderson return true; 5686ad216abSRichard Henderson } 5696ad216abSRichard Henderson 5703a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a) 5716ad216abSRichard Henderson { 5728bba7619SRichard Henderson gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5736ad216abSRichard Henderson return true; 5746ad216abSRichard Henderson } 5756ad216abSRichard Henderson 5763a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a) 5776ad216abSRichard Henderson { 5788bba7619SRichard Henderson gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 5796ad216abSRichard Henderson return true; 580bbe418f2SJia Liu } 581bbe418f2SJia Liu 5823a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a) 583136e13aeSRichard Henderson { 584136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 585136e13aeSRichard Henderson 586136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 5878000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 588136e13aeSRichard Henderson dc->delayed_branch = 2; 589136e13aeSRichard Henderson return true; 590136e13aeSRichard Henderson } 591136e13aeSRichard Henderson 5923a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) 593136e13aeSRichard Henderson { 594136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 595136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 596136e13aeSRichard Henderson 5978bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], ret_pc); 598136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 599136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 600136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 6018000ba56SRichard Henderson dc->jmp_pc_imm = tmp_pc; 602136e13aeSRichard Henderson dc->delayed_branch = 2; 603136e13aeSRichard Henderson } 604136e13aeSRichard Henderson return true; 605136e13aeSRichard Henderson } 606136e13aeSRichard Henderson 607136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 608136e13aeSRichard Henderson { 609136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 610af42d354SRichard Henderson TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8); 611af42d354SRichard Henderson TCGv t_true = tcg_constant_tl(tmp_pc); 612136e13aeSRichard Henderson 613118671f0SRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next); 614136e13aeSRichard Henderson dc->delayed_branch = 2; 615136e13aeSRichard Henderson } 616136e13aeSRichard Henderson 6173a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) 618136e13aeSRichard Henderson { 619136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 620136e13aeSRichard Henderson return true; 621136e13aeSRichard Henderson } 622136e13aeSRichard Henderson 6233a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) 624136e13aeSRichard Henderson { 625136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 626136e13aeSRichard Henderson return true; 627136e13aeSRichard Henderson } 628136e13aeSRichard Henderson 6293a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) 630136e13aeSRichard Henderson { 6318bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 632136e13aeSRichard Henderson dc->delayed_branch = 2; 633136e13aeSRichard Henderson return true; 634136e13aeSRichard Henderson } 635136e13aeSRichard Henderson 6363a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) 637136e13aeSRichard Henderson { 6388bba7619SRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b)); 6398bba7619SRichard Henderson tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8); 640136e13aeSRichard Henderson dc->delayed_branch = 2; 641136e13aeSRichard Henderson return true; 642136e13aeSRichard Henderson } 643136e13aeSRichard Henderson 6443a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a) 645d80bff19SRichard Henderson { 646d80bff19SRichard Henderson TCGv ea; 647d80bff19SRichard Henderson 648cdd0f459SRichard Henderson check_r0_write(dc, a->d); 649d80bff19SRichard Henderson ea = tcg_temp_new(); 6508bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6518bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL); 652d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 6538bba7619SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d)); 654d80bff19SRichard Henderson return true; 655d80bff19SRichard Henderson } 656d80bff19SRichard Henderson 65714776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop) 658d80bff19SRichard Henderson { 659d80bff19SRichard Henderson TCGv ea; 660d80bff19SRichard Henderson 661cdd0f459SRichard Henderson check_r0_write(dc, a->d); 662d80bff19SRichard Henderson ea = tcg_temp_new(); 6638bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 6648bba7619SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop); 665d80bff19SRichard Henderson } 666d80bff19SRichard Henderson 6673a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a) 668d80bff19SRichard Henderson { 669d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 670d80bff19SRichard Henderson return true; 671d80bff19SRichard Henderson } 672d80bff19SRichard Henderson 6733a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a) 674d80bff19SRichard Henderson { 675d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 676d80bff19SRichard Henderson return true; 677d80bff19SRichard Henderson } 678d80bff19SRichard Henderson 6793a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a) 680d80bff19SRichard Henderson { 681d80bff19SRichard Henderson do_load(dc, a, MO_UB); 682d80bff19SRichard Henderson return true; 683d80bff19SRichard Henderson } 684d80bff19SRichard Henderson 6853a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a) 686d80bff19SRichard Henderson { 687d80bff19SRichard Henderson do_load(dc, a, MO_SB); 688d80bff19SRichard Henderson return true; 689d80bff19SRichard Henderson } 690d80bff19SRichard Henderson 6913a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a) 692d80bff19SRichard Henderson { 693d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 694d80bff19SRichard Henderson return true; 695d80bff19SRichard Henderson } 696d80bff19SRichard Henderson 6973a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a) 698d80bff19SRichard Henderson { 699d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 700d80bff19SRichard Henderson return true; 701d80bff19SRichard Henderson } 702d80bff19SRichard Henderson 7033a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a) 704d80bff19SRichard Henderson { 705d80bff19SRichard Henderson TCGv ea, val; 706d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 707d80bff19SRichard Henderson 708d80bff19SRichard Henderson ea = tcg_temp_new(); 7098bba7619SRichard Henderson tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); 710d80bff19SRichard Henderson 711d80bff19SRichard Henderson lab_fail = gen_new_label(); 712d80bff19SRichard Henderson lab_done = gen_new_label(); 713d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 714d80bff19SRichard Henderson 715d80bff19SRichard Henderson val = tcg_temp_new(); 716d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 7174d10fa0fSRichard Henderson cpu_R(dc, a->b), dc->mem_idx, MO_TEUL); 718d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 719d80bff19SRichard Henderson 720d80bff19SRichard Henderson tcg_gen_br(lab_done); 721d80bff19SRichard Henderson 722d80bff19SRichard Henderson gen_set_label(lab_fail); 723d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 724d80bff19SRichard Henderson 725d80bff19SRichard Henderson gen_set_label(lab_done); 726d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 727d80bff19SRichard Henderson return true; 728d80bff19SRichard Henderson } 729d80bff19SRichard Henderson 73014776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop) 731d80bff19SRichard Henderson { 732d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 7338bba7619SRichard Henderson tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i); 7348bba7619SRichard Henderson tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop); 735d80bff19SRichard Henderson } 736d80bff19SRichard Henderson 7373a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a) 738d80bff19SRichard Henderson { 739d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 740d80bff19SRichard Henderson return true; 741d80bff19SRichard Henderson } 742d80bff19SRichard Henderson 7433a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a) 744d80bff19SRichard Henderson { 745d80bff19SRichard Henderson do_store(dc, a, MO_UB); 746d80bff19SRichard Henderson return true; 747d80bff19SRichard Henderson } 748d80bff19SRichard Henderson 7493a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a) 750d80bff19SRichard Henderson { 751d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 752d80bff19SRichard Henderson return true; 753d80bff19SRichard Henderson } 754d80bff19SRichard Henderson 7553a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) 756bbe418f2SJia Liu { 7578816f70bSRichard Henderson return true; 7588816f70bSRichard Henderson } 7598816f70bSRichard Henderson 7603e0e41efSRichard Henderson static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a) 7613e0e41efSRichard Henderson { 7623e0e41efSRichard Henderson if (!check_v1_3(dc)) { 7633e0e41efSRichard Henderson return false; 7643e0e41efSRichard Henderson } 7653e0e41efSRichard Henderson check_r0_write(dc, a->d); 7663e0e41efSRichard Henderson 7673e0e41efSRichard Henderson tcg_gen_movi_i32(cpu_R(dc, a->d), 7683e0e41efSRichard Henderson (dc->base.pc_next & TARGET_PAGE_MASK) + 7693e0e41efSRichard Henderson ((target_long)a->i << TARGET_PAGE_BITS)); 7703e0e41efSRichard Henderson return true; 7713e0e41efSRichard Henderson } 7723e0e41efSRichard Henderson 7733a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a) 7748816f70bSRichard Henderson { 775cdd0f459SRichard Henderson check_r0_write(dc, a->d); 776af42d354SRichard Henderson gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 7778816f70bSRichard Henderson return true; 7788816f70bSRichard Henderson } 779bbe418f2SJia Liu 7803a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a) 781bbe418f2SJia Liu { 782cdd0f459SRichard Henderson check_r0_write(dc, a->d); 783af42d354SRichard Henderson gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 7848816f70bSRichard Henderson return true; 7858816f70bSRichard Henderson } 7868816f70bSRichard Henderson 7873a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a) 7888816f70bSRichard Henderson { 789cdd0f459SRichard Henderson check_r0_write(dc, a->d); 790af42d354SRichard Henderson gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); 7918816f70bSRichard Henderson return true; 7928816f70bSRichard Henderson } 7938816f70bSRichard Henderson 7943a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) 7958816f70bSRichard Henderson { 796af42d354SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i)); 7978816f70bSRichard Henderson return true; 7988816f70bSRichard Henderson } 7998816f70bSRichard Henderson 8003a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a) 8018816f70bSRichard Henderson { 802cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8038bba7619SRichard Henderson tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8048816f70bSRichard Henderson return true; 8058816f70bSRichard Henderson } 8068816f70bSRichard Henderson 8073a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a) 8088816f70bSRichard Henderson { 809cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8108bba7619SRichard Henderson tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k); 8118816f70bSRichard Henderson return true; 8128816f70bSRichard Henderson } 8138816f70bSRichard Henderson 8143a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a) 8158816f70bSRichard Henderson { 816cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8178bba7619SRichard Henderson tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i); 8188816f70bSRichard Henderson return true; 8198816f70bSRichard Henderson } 8208816f70bSRichard Henderson 8213a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) 8228816f70bSRichard Henderson { 823c28fa81fSRichard Henderson TCGv spr = tcg_temp_new(); 824b9e40bacSPavel Dovgalyuk 82508f021deSStafford Horne check_r0_write(dc, a->d); 82608f021deSStafford Horne 827dfd1b812SRichard Henderson if (translator_io_start(&dc->base)) { 828b9e40bacSPavel Dovgalyuk if (dc->delayed_branch) { 829b9e40bacSPavel Dovgalyuk tcg_gen_mov_tl(cpu_pc, jmp_pc); 830b9e40bacSPavel Dovgalyuk tcg_gen_discard_tl(jmp_pc); 831b9e40bacSPavel Dovgalyuk } else { 832b9e40bacSPavel Dovgalyuk tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 833b9e40bacSPavel Dovgalyuk } 834b9e40bacSPavel Dovgalyuk dc->base.is_jmp = DISAS_EXIT; 835b9e40bacSPavel Dovgalyuk } 836b9e40bacSPavel Dovgalyuk 8378bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 838ad75a51eSRichard Henderson gen_helper_mfspr(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d), spr); 8398816f70bSRichard Henderson return true; 8408816f70bSRichard Henderson } 841bbe418f2SJia Liu 8423a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) 8434dd044c6SJia Liu { 84408f021deSStafford Horne TCGv spr = tcg_temp_new(); 84501ec3ec9SRichard Henderson 846dfd1b812SRichard Henderson translator_io_start(&dc->base); 847dfd1b812SRichard Henderson 84808f021deSStafford Horne /* 84908f021deSStafford Horne * For SR, we will need to exit the TB to recognize the new 85001ec3ec9SRichard Henderson * exception state. For NPC, in theory this counts as a branch 85101ec3ec9SRichard Henderson * (although the SPR only exists for use by an ICE). Save all 85201ec3ec9SRichard Henderson * of the cpu state first, allowing it to be overwritten. 85301ec3ec9SRichard Henderson */ 85401ec3ec9SRichard Henderson if (dc->delayed_branch) { 85501ec3ec9SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 85601ec3ec9SRichard Henderson tcg_gen_discard_tl(jmp_pc); 85701ec3ec9SRichard Henderson } else { 85801ec3ec9SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4); 85901ec3ec9SRichard Henderson } 86001ec3ec9SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 86101ec3ec9SRichard Henderson 8628bba7619SRichard Henderson tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k); 863ad75a51eSRichard Henderson gen_helper_mtspr(tcg_env, spr, cpu_R(dc, a->b)); 8648816f70bSRichard Henderson return true; 865bbe418f2SJia Liu } 866bbe418f2SJia Liu 8673a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a) 868bbe418f2SJia Liu { 8698bba7619SRichard Henderson gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 87099d863d6SRichard Henderson return true; 871bbe418f2SJia Liu } 87299d863d6SRichard Henderson 8733a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a) 87499d863d6SRichard Henderson { 8758bba7619SRichard Henderson gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 87699d863d6SRichard Henderson return true; 87799d863d6SRichard Henderson } 87899d863d6SRichard Henderson 8793a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a) 88099d863d6SRichard Henderson { 8818bba7619SRichard Henderson gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 88299d863d6SRichard Henderson return true; 88399d863d6SRichard Henderson } 88499d863d6SRichard Henderson 8853a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a) 88699d863d6SRichard Henderson { 8878bba7619SRichard Henderson gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b)); 88899d863d6SRichard Henderson return true; 889bbe418f2SJia Liu } 890bbe418f2SJia Liu 8913a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a) 892bbe418f2SJia Liu { 893cdd0f459SRichard Henderson check_r0_write(dc, a->d); 8948bba7619SRichard Henderson tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 8958bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 896e20c2592SRichard Henderson return true; 897bbe418f2SJia Liu } 898e20c2592SRichard Henderson 8993a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a) 900e20c2592SRichard Henderson { 901cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9028bba7619SRichard Henderson tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9038bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 904e20c2592SRichard Henderson return true; 905e20c2592SRichard Henderson } 906e20c2592SRichard Henderson 9073a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a) 908e20c2592SRichard Henderson { 909cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9108bba7619SRichard Henderson tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9118bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 912e20c2592SRichard Henderson return true; 913e20c2592SRichard Henderson } 914e20c2592SRichard Henderson 9153a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a) 916e20c2592SRichard Henderson { 917cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9188bba7619SRichard Henderson tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), 9198bba7619SRichard Henderson a->l & (TARGET_LONG_BITS - 1)); 920e20c2592SRichard Henderson return true; 921bbe418f2SJia Liu } 922bbe418f2SJia Liu 9233a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) 924bbe418f2SJia Liu { 925cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9268bba7619SRichard Henderson tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16); 927e720a571SRichard Henderson return true; 928bbe418f2SJia Liu } 929e720a571SRichard Henderson 9303a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) 931e720a571SRichard Henderson { 932cdd0f459SRichard Henderson check_r0_write(dc, a->d); 9338bba7619SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac); 934e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 935e720a571SRichard Henderson return true; 936bbe418f2SJia Liu } 937bbe418f2SJia Liu 9383a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) 939bbe418f2SJia Liu { 9408bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, 9418bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 942fbb3e29aSRichard Henderson return true; 943bbe418f2SJia Liu } 944fbb3e29aSRichard Henderson 9453a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a) 946fbb3e29aSRichard Henderson { 9478bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, 9488bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 949fbb3e29aSRichard Henderson return true; 950fbb3e29aSRichard Henderson } 951fbb3e29aSRichard Henderson 9523a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) 953fbb3e29aSRichard Henderson { 9548bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, 9558bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 956fbb3e29aSRichard Henderson return true; 957fbb3e29aSRichard Henderson } 958fbb3e29aSRichard Henderson 9593a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) 960fbb3e29aSRichard Henderson { 9618bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, 9628bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 963fbb3e29aSRichard Henderson return true; 964fbb3e29aSRichard Henderson } 965fbb3e29aSRichard Henderson 9663a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) 967fbb3e29aSRichard Henderson { 9688bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, 9698bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 970fbb3e29aSRichard Henderson return true; 971fbb3e29aSRichard Henderson } 972fbb3e29aSRichard Henderson 9733a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) 974fbb3e29aSRichard Henderson { 9758bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, 9768bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 977fbb3e29aSRichard Henderson return true; 978fbb3e29aSRichard Henderson } 979fbb3e29aSRichard Henderson 9803a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) 981fbb3e29aSRichard Henderson { 9828bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, 9838bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 984fbb3e29aSRichard Henderson return true; 985fbb3e29aSRichard Henderson } 986fbb3e29aSRichard Henderson 9873a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a) 988fbb3e29aSRichard Henderson { 9898bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, 9908bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 991fbb3e29aSRichard Henderson return true; 992fbb3e29aSRichard Henderson } 993fbb3e29aSRichard Henderson 9943a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a) 995fbb3e29aSRichard Henderson { 9968bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, 9978bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 998fbb3e29aSRichard Henderson return true; 999fbb3e29aSRichard Henderson } 1000fbb3e29aSRichard Henderson 10013a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a) 1002fbb3e29aSRichard Henderson { 10038bba7619SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, 10048bba7619SRichard Henderson cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1005fbb3e29aSRichard Henderson return true; 1006bbe418f2SJia Liu } 1007bbe418f2SJia Liu 10083a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) 1009bbe418f2SJia Liu { 10108bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i); 1011032de4fcSRichard Henderson return true; 1012bbe418f2SJia Liu } 1013032de4fcSRichard Henderson 10143a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) 1015032de4fcSRichard Henderson { 10168bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1017032de4fcSRichard Henderson return true; 1018032de4fcSRichard Henderson } 1019032de4fcSRichard Henderson 10203a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) 1021032de4fcSRichard Henderson { 10228bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1023032de4fcSRichard Henderson return true; 1024032de4fcSRichard Henderson } 1025032de4fcSRichard Henderson 10263a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) 1027032de4fcSRichard Henderson { 10288bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1029032de4fcSRichard Henderson return true; 1030032de4fcSRichard Henderson } 1031032de4fcSRichard Henderson 10323a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) 1033032de4fcSRichard Henderson { 10348bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1035032de4fcSRichard Henderson return true; 1036032de4fcSRichard Henderson } 1037032de4fcSRichard Henderson 10383a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) 1039032de4fcSRichard Henderson { 10408bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i); 1041032de4fcSRichard Henderson return true; 1042032de4fcSRichard Henderson } 1043032de4fcSRichard Henderson 10443a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) 1045032de4fcSRichard Henderson { 10468bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1047032de4fcSRichard Henderson return true; 1048032de4fcSRichard Henderson } 1049032de4fcSRichard Henderson 10503a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) 1051032de4fcSRichard Henderson { 10528bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1053032de4fcSRichard Henderson return true; 1054032de4fcSRichard Henderson } 1055032de4fcSRichard Henderson 10563a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) 1057032de4fcSRichard Henderson { 10588bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i); 1059032de4fcSRichard Henderson return true; 1060032de4fcSRichard Henderson } 1061032de4fcSRichard Henderson 10623a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) 1063032de4fcSRichard Henderson { 10648bba7619SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i); 1065032de4fcSRichard Henderson return true; 1066bbe418f2SJia Liu } 1067bbe418f2SJia Liu 10683a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) 1069bbe418f2SJia Liu { 10701ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1071bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 10721ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 10737de9729fSRichard Henderson return true; 10747de9729fSRichard Henderson } 1075bbe418f2SJia Liu 10763a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) 10777de9729fSRichard Henderson { 10781ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1079bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 10801ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 10817de9729fSRichard Henderson return true; 10827de9729fSRichard Henderson } 1083bbe418f2SJia Liu 10843a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) 10857de9729fSRichard Henderson { 108624fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 10877de9729fSRichard Henderson return true; 1088bbe418f2SJia Liu } 10897de9729fSRichard Henderson 10903a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) 10917de9729fSRichard Henderson { 10927de9729fSRichard Henderson return true; 10937de9729fSRichard Henderson } 10947de9729fSRichard Henderson 10953a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) 10967de9729fSRichard Henderson { 10977de9729fSRichard Henderson return true; 1098bbe418f2SJia Liu } 1099bbe418f2SJia Liu 11003a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) 11018816f70bSRichard Henderson { 11022ba65417SRichard Henderson if (is_user(dc)) { 11038816f70bSRichard Henderson gen_illegal_exception(dc); 11048816f70bSRichard Henderson } else { 1105ad75a51eSRichard Henderson gen_helper_rfe(tcg_env); 110664e46c95SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 11078816f70bSRichard Henderson } 11088816f70bSRichard Henderson return true; 11098816f70bSRichard Henderson } 11108816f70bSRichard Henderson 1111fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a, 11126fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv)) 1113bbe418f2SJia Liu { 1114fe636d37SRichard Henderson if (!check_of32s(dc)) { 1115fe636d37SRichard Henderson return false; 1116fe636d37SRichard Henderson } 1117cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1118ad75a51eSRichard Henderson fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a)); 1119ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 1120fe636d37SRichard Henderson return true; 1121bbe418f2SJia Liu } 11226fd204a2SRichard Henderson 1123fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a, 11246fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) 11256fd204a2SRichard Henderson { 1126fe636d37SRichard Henderson if (!check_of32s(dc)) { 1127fe636d37SRichard Henderson return false; 1128fe636d37SRichard Henderson } 1129cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1130ad75a51eSRichard Henderson fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 1131ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 1132fe636d37SRichard Henderson return true; 11336fd204a2SRichard Henderson } 11346fd204a2SRichard Henderson 1135fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a, 11366fd204a2SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv, TCGv), 11376fd204a2SRichard Henderson bool inv, bool swap) 11386fd204a2SRichard Henderson { 1139fe636d37SRichard Henderson if (!check_of32s(dc)) { 1140fe636d37SRichard Henderson return false; 1141fe636d37SRichard Henderson } 11426fd204a2SRichard Henderson if (swap) { 1143ad75a51eSRichard Henderson fn(cpu_sr_f, tcg_env, cpu_R(dc, a->b), cpu_R(dc, a->a)); 11446fd204a2SRichard Henderson } else { 1145ad75a51eSRichard Henderson fn(cpu_sr_f, tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b)); 11466fd204a2SRichard Henderson } 11476fd204a2SRichard Henderson if (inv) { 11486fd204a2SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 11496fd204a2SRichard Henderson } 1150ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 1151fe636d37SRichard Henderson return true; 11526fd204a2SRichard Henderson } 11536fd204a2SRichard Henderson 11543a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) 11556fd204a2SRichard Henderson { 1156fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_add_s); 11576fd204a2SRichard Henderson } 11586fd204a2SRichard Henderson 11593a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) 11606fd204a2SRichard Henderson { 1161fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_sub_s); 11626fd204a2SRichard Henderson } 11636fd204a2SRichard Henderson 11643a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) 11656fd204a2SRichard Henderson { 1166fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_mul_s); 11676fd204a2SRichard Henderson } 11686fd204a2SRichard Henderson 11693a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) 11706fd204a2SRichard Henderson { 1171fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_div_s); 11726fd204a2SRichard Henderson } 11736fd204a2SRichard Henderson 11743a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) 11756fd204a2SRichard Henderson { 1176fe636d37SRichard Henderson return do_fp3(dc, a, gen_helper_float_rem_s); 11776fd204a2SRichard Henderson return true; 11786fd204a2SRichard Henderson } 11796fd204a2SRichard Henderson 11803a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) 11816fd204a2SRichard Henderson { 1182fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_itofs); 11836fd204a2SRichard Henderson } 11846fd204a2SRichard Henderson 11853a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) 11866fd204a2SRichard Henderson { 1187fe636d37SRichard Henderson return do_fp2(dc, a, gen_helper_ftois); 11886fd204a2SRichard Henderson } 11896fd204a2SRichard Henderson 11903a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) 11916fd204a2SRichard Henderson { 1192fe636d37SRichard Henderson if (!check_of32s(dc)) { 1193fe636d37SRichard Henderson return false; 1194fe636d37SRichard Henderson } 1195cdd0f459SRichard Henderson check_r0_write(dc, a->d); 1196ad75a51eSRichard Henderson gen_helper_float_madd_s(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d), 11978bba7619SRichard Henderson cpu_R(dc, a->a), cpu_R(dc, a->b)); 1198ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 11996fd204a2SRichard Henderson return true; 12006fd204a2SRichard Henderson } 12016fd204a2SRichard Henderson 12023a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) 12036fd204a2SRichard Henderson { 1204fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); 12056fd204a2SRichard Henderson } 12066fd204a2SRichard Henderson 12073a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) 12086fd204a2SRichard Henderson { 1209fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); 12106fd204a2SRichard Henderson } 12116fd204a2SRichard Henderson 12123a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) 12136fd204a2SRichard Henderson { 1214fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); 12156fd204a2SRichard Henderson } 12166fd204a2SRichard Henderson 12173a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) 12186fd204a2SRichard Henderson { 1219fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, true); 12206fd204a2SRichard Henderson } 12216fd204a2SRichard Henderson 12223a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) 12236fd204a2SRichard Henderson { 1224fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); 12256fd204a2SRichard Henderson } 12266fd204a2SRichard Henderson 12273a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) 12286fd204a2SRichard Henderson { 1229fe636d37SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); 1230bbe418f2SJia Liu } 1231bbe418f2SJia Liu 12322b13b4b9SRichard Henderson static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a) 12332b13b4b9SRichard Henderson { 12342b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12352b13b4b9SRichard Henderson return false; 12362b13b4b9SRichard Henderson } 12372b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false); 12382b13b4b9SRichard Henderson } 12392b13b4b9SRichard Henderson 12402b13b4b9SRichard Henderson static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a) 12412b13b4b9SRichard Henderson { 12422b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12432b13b4b9SRichard Henderson return false; 12442b13b4b9SRichard Henderson } 12452b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false); 12462b13b4b9SRichard Henderson } 12472b13b4b9SRichard Henderson 12482b13b4b9SRichard Henderson static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a) 12492b13b4b9SRichard Henderson { 12502b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12512b13b4b9SRichard Henderson return false; 12522b13b4b9SRichard Henderson } 12532b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true); 12542b13b4b9SRichard Henderson } 12552b13b4b9SRichard Henderson 12562b13b4b9SRichard Henderson static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a) 12572b13b4b9SRichard Henderson { 12582b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12592b13b4b9SRichard Henderson return false; 12602b13b4b9SRichard Henderson } 12612b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false); 12622b13b4b9SRichard Henderson } 12632b13b4b9SRichard Henderson 12642b13b4b9SRichard Henderson static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a) 12652b13b4b9SRichard Henderson { 12662b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12672b13b4b9SRichard Henderson return false; 12682b13b4b9SRichard Henderson } 12692b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true); 12702b13b4b9SRichard Henderson } 12712b13b4b9SRichard Henderson 12722b13b4b9SRichard Henderson static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a) 12732b13b4b9SRichard Henderson { 12742b13b4b9SRichard Henderson if (!check_v1_3(dc)) { 12752b13b4b9SRichard Henderson return false; 12762b13b4b9SRichard Henderson } 12772b13b4b9SRichard Henderson return do_fpcmp(dc, a, gen_helper_float_un_s, false, false); 12782b13b4b9SRichard Henderson } 12792b13b4b9SRichard Henderson 128062f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p) 128162f2b038SRichard Henderson { 128262f2b038SRichard Henderson return r + 1 + p < 32; 128362f2b038SRichard Henderson } 128462f2b038SRichard Henderson 128562f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 128662f2b038SRichard Henderson { 128762f2b038SRichard Henderson tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r)); 128862f2b038SRichard Henderson } 128962f2b038SRichard Henderson 129062f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p) 129162f2b038SRichard Henderson { 129262f2b038SRichard Henderson tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t); 129362f2b038SRichard Henderson } 129462f2b038SRichard Henderson 129562f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a, 129662f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 129762f2b038SRichard Henderson { 129862f2b038SRichard Henderson TCGv_i64 t0, t1; 129962f2b038SRichard Henderson 130062f2b038SRichard Henderson if (!check_of64a32s(dc) || 130162f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 130262f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 130362f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 130462f2b038SRichard Henderson return false; 130562f2b038SRichard Henderson } 130662f2b038SRichard Henderson check_r0_write(dc, a->d); 130762f2b038SRichard Henderson 130862f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 130962f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 131062f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 131162f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 1312ad75a51eSRichard Henderson fn(t0, tcg_env, t0, t1); 131362f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 131462f2b038SRichard Henderson 1315ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 131662f2b038SRichard Henderson return true; 131762f2b038SRichard Henderson } 131862f2b038SRichard Henderson 131962f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a, 132062f2b038SRichard Henderson void (*fn)(TCGv_i64, TCGv_env, TCGv_i64)) 132162f2b038SRichard Henderson { 132262f2b038SRichard Henderson TCGv_i64 t0; 132362f2b038SRichard Henderson 132462f2b038SRichard Henderson if (!check_of64a32s(dc) || 132562f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 132662f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 132762f2b038SRichard Henderson return false; 132862f2b038SRichard Henderson } 132962f2b038SRichard Henderson check_r0_write(dc, a->d); 133062f2b038SRichard Henderson 133162f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 133262f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1333ad75a51eSRichard Henderson fn(t0, tcg_env, t0); 133462f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 133562f2b038SRichard Henderson 1336ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 133762f2b038SRichard Henderson return true; 133862f2b038SRichard Henderson } 133962f2b038SRichard Henderson 134062f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a, 134162f2b038SRichard Henderson void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64), 134262f2b038SRichard Henderson bool inv, bool swap) 134362f2b038SRichard Henderson { 134462f2b038SRichard Henderson TCGv_i64 t0, t1; 134562f2b038SRichard Henderson 134662f2b038SRichard Henderson if (!check_of64a32s(dc) || 134762f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 134862f2b038SRichard Henderson !check_pair(dc, a->b, a->bp)) { 134962f2b038SRichard Henderson return false; 135062f2b038SRichard Henderson } 135162f2b038SRichard Henderson 135262f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 135362f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 135462f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 135562f2b038SRichard Henderson load_pair(dc, t1, a->b, a->bp); 135662f2b038SRichard Henderson if (swap) { 1357ad75a51eSRichard Henderson fn(cpu_sr_f, tcg_env, t1, t0); 135862f2b038SRichard Henderson } else { 1359ad75a51eSRichard Henderson fn(cpu_sr_f, tcg_env, t0, t1); 136062f2b038SRichard Henderson } 136162f2b038SRichard Henderson 136262f2b038SRichard Henderson if (inv) { 136362f2b038SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 136462f2b038SRichard Henderson } 1365ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 136662f2b038SRichard Henderson return true; 136762f2b038SRichard Henderson } 136862f2b038SRichard Henderson 136962f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a) 137062f2b038SRichard Henderson { 137162f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_add_d); 137262f2b038SRichard Henderson } 137362f2b038SRichard Henderson 137462f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a) 137562f2b038SRichard Henderson { 137662f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_sub_d); 137762f2b038SRichard Henderson } 137862f2b038SRichard Henderson 137962f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a) 138062f2b038SRichard Henderson { 138162f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_mul_d); 138262f2b038SRichard Henderson } 138362f2b038SRichard Henderson 138462f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a) 138562f2b038SRichard Henderson { 138662f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_div_d); 138762f2b038SRichard Henderson } 138862f2b038SRichard Henderson 138962f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a) 139062f2b038SRichard Henderson { 139162f2b038SRichard Henderson return do_dp3(dc, a, gen_helper_float_rem_d); 139262f2b038SRichard Henderson } 139362f2b038SRichard Henderson 139462f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a) 139562f2b038SRichard Henderson { 139662f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_itofd); 139762f2b038SRichard Henderson } 139862f2b038SRichard Henderson 139962f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a) 140062f2b038SRichard Henderson { 140162f2b038SRichard Henderson return do_dp2(dc, a, gen_helper_ftoid); 140262f2b038SRichard Henderson } 140362f2b038SRichard Henderson 140462f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a) 140562f2b038SRichard Henderson { 140662f2b038SRichard Henderson TCGv_i64 t0; 140762f2b038SRichard Henderson 140862f2b038SRichard Henderson if (!check_of64a32s(dc) || 140962f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 141062f2b038SRichard Henderson return false; 141162f2b038SRichard Henderson } 141262f2b038SRichard Henderson check_r0_write(dc, a->d); 141362f2b038SRichard Henderson 141462f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 1415ad75a51eSRichard Henderson gen_helper_stod(t0, tcg_env, cpu_R(dc, a->a)); 141662f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 141762f2b038SRichard Henderson 1418ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 141962f2b038SRichard Henderson return true; 142062f2b038SRichard Henderson } 142162f2b038SRichard Henderson 142262f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a) 142362f2b038SRichard Henderson { 142462f2b038SRichard Henderson TCGv_i64 t0; 142562f2b038SRichard Henderson 142662f2b038SRichard Henderson if (!check_of64a32s(dc) || 142762f2b038SRichard Henderson !check_pair(dc, a->a, a->ap)) { 142862f2b038SRichard Henderson return false; 142962f2b038SRichard Henderson } 143062f2b038SRichard Henderson check_r0_write(dc, a->d); 143162f2b038SRichard Henderson 143262f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 143362f2b038SRichard Henderson load_pair(dc, t0, a->a, a->ap); 1434ad75a51eSRichard Henderson gen_helper_dtos(cpu_R(dc, a->d), tcg_env, t0); 143562f2b038SRichard Henderson 1436ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 143762f2b038SRichard Henderson return true; 143862f2b038SRichard Henderson } 143962f2b038SRichard Henderson 144062f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a) 144162f2b038SRichard Henderson { 144262f2b038SRichard Henderson TCGv_i64 t0, t1, t2; 144362f2b038SRichard Henderson 144462f2b038SRichard Henderson if (!check_of64a32s(dc) || 144562f2b038SRichard Henderson !check_pair(dc, a->a, a->ap) || 144662f2b038SRichard Henderson !check_pair(dc, a->b, a->bp) || 144762f2b038SRichard Henderson !check_pair(dc, a->d, a->dp)) { 144862f2b038SRichard Henderson return false; 144962f2b038SRichard Henderson } 145062f2b038SRichard Henderson check_r0_write(dc, a->d); 145162f2b038SRichard Henderson 145262f2b038SRichard Henderson t0 = tcg_temp_new_i64(); 145362f2b038SRichard Henderson t1 = tcg_temp_new_i64(); 145462f2b038SRichard Henderson t2 = tcg_temp_new_i64(); 145562f2b038SRichard Henderson load_pair(dc, t0, a->d, a->dp); 145662f2b038SRichard Henderson load_pair(dc, t1, a->a, a->ap); 145762f2b038SRichard Henderson load_pair(dc, t2, a->b, a->bp); 1458ad75a51eSRichard Henderson gen_helper_float_madd_d(t0, tcg_env, t0, t1, t2); 145962f2b038SRichard Henderson save_pair(dc, t0, a->d, a->dp); 146062f2b038SRichard Henderson 1461ad75a51eSRichard Henderson gen_helper_update_fpcsr(tcg_env); 146262f2b038SRichard Henderson return true; 146362f2b038SRichard Henderson } 146462f2b038SRichard Henderson 146562f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a) 146662f2b038SRichard Henderson { 146762f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false); 146862f2b038SRichard Henderson } 146962f2b038SRichard Henderson 147062f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a) 147162f2b038SRichard Henderson { 147262f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false); 147362f2b038SRichard Henderson } 147462f2b038SRichard Henderson 147562f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a) 147662f2b038SRichard Henderson { 147762f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true); 147862f2b038SRichard Henderson } 147962f2b038SRichard Henderson 148062f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a) 148162f2b038SRichard Henderson { 148262f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, true); 148362f2b038SRichard Henderson } 148462f2b038SRichard Henderson 148562f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a) 148662f2b038SRichard Henderson { 148762f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false); 148862f2b038SRichard Henderson } 148962f2b038SRichard Henderson 149062f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a) 149162f2b038SRichard Henderson { 149262f2b038SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_le_d, false, false); 149362f2b038SRichard Henderson } 149462f2b038SRichard Henderson 14952b13b4b9SRichard Henderson static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a) 14962b13b4b9SRichard Henderson { 14972b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false); 14982b13b4b9SRichard Henderson } 14992b13b4b9SRichard Henderson 15002b13b4b9SRichard Henderson static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a) 15012b13b4b9SRichard Henderson { 15022b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false); 15032b13b4b9SRichard Henderson } 15042b13b4b9SRichard Henderson 15052b13b4b9SRichard Henderson static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a) 15062b13b4b9SRichard Henderson { 15072b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true); 15082b13b4b9SRichard Henderson } 15092b13b4b9SRichard Henderson 15102b13b4b9SRichard Henderson static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a) 15112b13b4b9SRichard Henderson { 15122b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false); 15132b13b4b9SRichard Henderson } 15142b13b4b9SRichard Henderson 15152b13b4b9SRichard Henderson static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a) 15162b13b4b9SRichard Henderson { 15172b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true); 15182b13b4b9SRichard Henderson } 15192b13b4b9SRichard Henderson 15202b13b4b9SRichard Henderson static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a) 15212b13b4b9SRichard Henderson { 15222b13b4b9SRichard Henderson return do_dpcmp(dc, a, gen_helper_float_un_d, false, false); 15232b13b4b9SRichard Henderson } 15242b13b4b9SRichard Henderson 1525a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1526e67db06eSJia Liu { 1527a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 1528b77af26eSRichard Henderson CPUOpenRISCState *env = cpu_env(cs); 1529a4fd3ec3SEmilio G. Cota int bound; 1530bbe418f2SJia Liu 15313b916140SRichard Henderson dc->mem_idx = cpu_mmu_index(cs, false); 15321ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1533a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1534fe636d37SRichard Henderson dc->cpucfgr = env->cpucfgr; 15352b13b4b9SRichard Henderson dc->avr = env->avr; 15368000ba56SRichard Henderson dc->jmp_pc_imm = -1; 15378000ba56SRichard Henderson 1538a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1539a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1540190ce7fbSRichard Henderson } 1541bbe418f2SJia Liu 1542a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1543a4fd3ec3SEmilio G. Cota { 1544a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1545bbe418f2SJia Liu 15466597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15476597c28dSRichard Henderson when it's true, which is the common case. */ 1548118671f0SRichard Henderson dc->zero = tcg_constant_tl(0); 15496597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 1550118671f0SRichard Henderson dc->R0 = dc->zero; 15516597c28dSRichard Henderson } else { 1552d29f4368SRichard Henderson dc->R0 = cpu_regs[0]; 15536597c28dSRichard Henderson } 1554a4fd3ec3SEmilio G. Cota } 15556597c28dSRichard Henderson 1556a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1557a4fd3ec3SEmilio G. Cota { 1558a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1559a4fd3ec3SEmilio G. Cota 15601ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1561a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1562a4fd3ec3SEmilio G. Cota } 1563bbe418f2SJia Liu 1564a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1565a4fd3ec3SEmilio G. Cota { 1566a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1567074bd799SPhilippe Mathieu-Daudé uint32_t insn = translator_ldl(cpu_env(cs), &dc->base, dc->base.pc_next); 1568a4fd3ec3SEmilio G. Cota 1569c7b6f54bSRichard Henderson if (!decode(dc, insn)) { 1570c7b6f54bSRichard Henderson gen_illegal_exception(dc); 1571c7b6f54bSRichard Henderson } 15721ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 157324c32852SRichard Henderson 15748000ba56SRichard Henderson /* When exiting the delay slot normally, exit via jmp_pc. 15758000ba56SRichard Henderson * For DISAS_NORETURN, we have raised an exception and already exited. 15768000ba56SRichard Henderson * For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing 15778000ba56SRichard Henderson * in the manual saying this is illegal, but it surely it should. 15788000ba56SRichard Henderson * At least or1ksim overrides pcnext and ignores the branch. 15798000ba56SRichard Henderson */ 15808000ba56SRichard Henderson if (dc->delayed_branch 15818000ba56SRichard Henderson && --dc->delayed_branch == 0 15828000ba56SRichard Henderson && dc->base.is_jmp == DISAS_NEXT) { 15838000ba56SRichard Henderson dc->base.is_jmp = DISAS_JUMP; 1584bbe418f2SJia Liu } 1585a4fd3ec3SEmilio G. Cota } 1586bbe418f2SJia Liu 1587a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1588a4fd3ec3SEmilio G. Cota { 1589a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 15908000ba56SRichard Henderson target_ulong jmp_dest; 159124c32852SRichard Henderson 1592e0a369cfSRichard Henderson /* If we have already exited the TB, nothing following has effect. */ 1593e0a369cfSRichard Henderson if (dc->base.is_jmp == DISAS_NORETURN) { 1594e0a369cfSRichard Henderson return; 1595e0a369cfSRichard Henderson } 1596e0a369cfSRichard Henderson 15978000ba56SRichard Henderson /* Adjust the delayed branch state for the next TB. */ 1598a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1599a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1600a01deb36SRichard Henderson } 1601a01deb36SRichard Henderson 16028000ba56SRichard Henderson /* For DISAS_TOO_MANY, jump to the next insn. */ 16038000ba56SRichard Henderson jmp_dest = dc->base.pc_next; 16048000ba56SRichard Henderson tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4); 16058000ba56SRichard Henderson 16061ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 16078000ba56SRichard Henderson case DISAS_JUMP: 16088000ba56SRichard Henderson jmp_dest = dc->jmp_pc_imm; 16098000ba56SRichard Henderson if (jmp_dest == -1) { 16108000ba56SRichard Henderson /* The jump destination is indirect/computed; use jmp_pc. */ 16118000ba56SRichard Henderson tcg_gen_mov_tl(cpu_pc, jmp_pc); 16128000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16138000ba56SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 1614bbe418f2SJia Liu break; 16158000ba56SRichard Henderson } 16168000ba56SRichard Henderson /* The jump destination is direct; use jmp_pc_imm. 16178000ba56SRichard Henderson However, we will have stored into jmp_pc as well; 16188000ba56SRichard Henderson we know now that it wasn't needed. */ 16198000ba56SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16208000ba56SRichard Henderson /* fallthru */ 16218000ba56SRichard Henderson 16228000ba56SRichard Henderson case DISAS_TOO_MANY: 1623adf1f3deSRichard Henderson if (translator_use_goto_tb(&dc->base, jmp_dest)) { 16248000ba56SRichard Henderson tcg_gen_goto_tb(0); 16258000ba56SRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 16268000ba56SRichard Henderson tcg_gen_exit_tb(dc->base.tb, 0); 1627adf1f3deSRichard Henderson break; 1628adf1f3deSRichard Henderson } 1629adf1f3deSRichard Henderson tcg_gen_movi_tl(cpu_pc, jmp_dest); 1630adf1f3deSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 16318000ba56SRichard Henderson break; 16328000ba56SRichard Henderson 163364e46c95SRichard Henderson case DISAS_EXIT: 163407ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 1635bbe418f2SJia Liu break; 1636a4fd3ec3SEmilio G. Cota default: 1637a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1638a4fd3ec3SEmilio G. Cota } 1639bbe418f2SJia Liu } 1640bbe418f2SJia Liu 1641a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1642a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1643a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1644a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1645a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1646a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1647a4fd3ec3SEmilio G. Cota }; 1648a4fd3ec3SEmilio G. Cota 1649*e4a8e093SRichard Henderson void openrisc_translate_code(CPUState *cs, TranslationBlock *tb, 1650*e4a8e093SRichard Henderson int *max_insns, vaddr pc, void *host_pc) 1651a4fd3ec3SEmilio G. Cota { 1652a4fd3ec3SEmilio G. Cota DisasContext ctx; 1653a4fd3ec3SEmilio G. Cota 1654306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, 1655306c8721SRichard Henderson &openrisc_tr_ops, &ctx.base); 1656e67db06eSJia Liu } 1657e67db06eSJia Liu 165890c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1659e67db06eSJia Liu { 1660074bd799SPhilippe Mathieu-Daudé CPUOpenRISCState *env = cpu_env(cs); 1661e67db06eSJia Liu int i; 1662878096eeSAndreas Färber 166390c84c56SMarkus Armbruster qemu_fprintf(f, "PC=%08x\n", env->pc); 1664e67db06eSJia Liu for (i = 0; i < 32; ++i) { 166590c84c56SMarkus Armbruster qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1666e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1667e67db06eSJia Liu } 1668e67db06eSJia Liu } 1669