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 10e67db06eSJia Liu * version 2 of the License, or (at your option) any later version. 11e67db06eSJia Liu * 12e67db06eSJia Liu * This library is distributed in the hope that it will be useful, 13e67db06eSJia Liu * but WITHOUT ANY WARRANTY; without even the implied warranty of 14e67db06eSJia Liu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15e67db06eSJia Liu * Lesser General Public License for more details. 16e67db06eSJia Liu * 17e67db06eSJia Liu * You should have received a copy of the GNU Lesser General Public 18e67db06eSJia Liu * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19e67db06eSJia Liu */ 20e67db06eSJia Liu 21ed2decc6SPeter Maydell #include "qemu/osdep.h" 22e67db06eSJia Liu #include "cpu.h" 23022c62cbSPaolo Bonzini #include "exec/exec-all.h" 2476cad711SPaolo Bonzini #include "disas/disas.h" 25e67db06eSJia Liu #include "tcg-op.h" 26e67db06eSJia Liu #include "qemu-common.h" 271de7afc9SPaolo Bonzini #include "qemu/log.h" 281de7afc9SPaolo Bonzini #include "qemu/bitops.h" 29f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 3077fc6f5eSLluís Vilanova #include "exec/translator.h" 31bbe418f2SJia Liu 322ef6175aSRichard Henderson #include "exec/helper-proto.h" 332ef6175aSRichard Henderson #include "exec/helper-gen.h" 347de9729fSRichard Henderson #include "exec/gen-icount.h" 35e67db06eSJia Liu 36a7e30d84SLluís Vilanova #include "trace-tcg.h" 37508127e2SPaolo Bonzini #include "exec/log.h" 38a7e30d84SLluís Vilanova 39111ece51SRichard Henderson #define LOG_DIS(str, ...) \ 401ffa4bceSEmilio G. Cota qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->base.pc_next, \ 411ffa4bceSEmilio G. Cota ## __VA_ARGS__) 42e67db06eSJia Liu 4377fc6f5eSLluís Vilanova /* is_jmp field values */ 4477fc6f5eSLluís Vilanova #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ 4577fc6f5eSLluís Vilanova #define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */ 4677fc6f5eSLluís Vilanova #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */ 4777fc6f5eSLluís Vilanova 48bbe418f2SJia Liu typedef struct DisasContext { 491ffa4bceSEmilio G. Cota DisasContextBase base; 50bbe418f2SJia Liu uint32_t mem_idx; 51a01deb36SRichard Henderson uint32_t tb_flags; 52bbe418f2SJia Liu uint32_t delayed_branch; 53bbe418f2SJia Liu } DisasContext; 54bbe418f2SJia Liu 557de9729fSRichard Henderson /* Include the auto-generated decoder. */ 567de9729fSRichard Henderson #include "decode.inc.c" 577de9729fSRichard Henderson 58bbe418f2SJia Liu static TCGv cpu_sr; 59bbe418f2SJia Liu static TCGv cpu_R[32]; 606597c28dSRichard Henderson static TCGv cpu_R0; 61bbe418f2SJia Liu static TCGv cpu_pc; 62bbe418f2SJia Liu static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ 63bbe418f2SJia Liu static TCGv cpu_ppc; 6484775c43SRichard Henderson static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ 6597458071SRichard Henderson static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ 6697458071SRichard Henderson static TCGv cpu_sr_ov; /* signed overflow */ 67930c3d00SRichard Henderson static TCGv cpu_lock_addr; 68930c3d00SRichard Henderson static TCGv cpu_lock_value; 69bbe418f2SJia Liu static TCGv_i32 fpcsr; 706f7332baSRichard Henderson static TCGv_i64 cpu_mac; /* MACHI:MACLO */ 71a01deb36SRichard Henderson static TCGv_i32 cpu_dflag; 72bbe418f2SJia Liu 73e67db06eSJia Liu void openrisc_translate_init(void) 74e67db06eSJia Liu { 75bbe418f2SJia Liu static const char * const regnames[] = { 76bbe418f2SJia Liu "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 77bbe418f2SJia Liu "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 78bbe418f2SJia Liu "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 79bbe418f2SJia Liu "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 80bbe418f2SJia Liu }; 81bbe418f2SJia Liu int i; 82bbe418f2SJia Liu 83e1ccc054SRichard Henderson cpu_sr = tcg_global_mem_new(cpu_env, 84bbe418f2SJia Liu offsetof(CPUOpenRISCState, sr), "sr"); 85a01deb36SRichard Henderson cpu_dflag = tcg_global_mem_new_i32(cpu_env, 86a01deb36SRichard Henderson offsetof(CPUOpenRISCState, dflag), 87a01deb36SRichard Henderson "dflag"); 88e1ccc054SRichard Henderson cpu_pc = tcg_global_mem_new(cpu_env, 89bbe418f2SJia Liu offsetof(CPUOpenRISCState, pc), "pc"); 90e1ccc054SRichard Henderson cpu_ppc = tcg_global_mem_new(cpu_env, 91bbe418f2SJia Liu offsetof(CPUOpenRISCState, ppc), "ppc"); 92e1ccc054SRichard Henderson jmp_pc = tcg_global_mem_new(cpu_env, 93bbe418f2SJia Liu offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); 9484775c43SRichard Henderson cpu_sr_f = tcg_global_mem_new(cpu_env, 9584775c43SRichard Henderson offsetof(CPUOpenRISCState, sr_f), "sr_f"); 9697458071SRichard Henderson cpu_sr_cy = tcg_global_mem_new(cpu_env, 9797458071SRichard Henderson offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); 9897458071SRichard Henderson cpu_sr_ov = tcg_global_mem_new(cpu_env, 9997458071SRichard Henderson offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); 100930c3d00SRichard Henderson cpu_lock_addr = tcg_global_mem_new(cpu_env, 101930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_addr), 102930c3d00SRichard Henderson "lock_addr"); 103930c3d00SRichard Henderson cpu_lock_value = tcg_global_mem_new(cpu_env, 104930c3d00SRichard Henderson offsetof(CPUOpenRISCState, lock_value), 105930c3d00SRichard Henderson "lock_value"); 106e1ccc054SRichard Henderson fpcsr = tcg_global_mem_new_i32(cpu_env, 107bbe418f2SJia Liu offsetof(CPUOpenRISCState, fpcsr), 108bbe418f2SJia Liu "fpcsr"); 1096f7332baSRichard Henderson cpu_mac = tcg_global_mem_new_i64(cpu_env, 1106f7332baSRichard Henderson offsetof(CPUOpenRISCState, mac), 1116f7332baSRichard Henderson "mac"); 112bbe418f2SJia Liu for (i = 0; i < 32; i++) { 113e1ccc054SRichard Henderson cpu_R[i] = tcg_global_mem_new(cpu_env, 114d89e71e8SStafford Horne offsetof(CPUOpenRISCState, 115d89e71e8SStafford Horne shadow_gpr[0][i]), 116bbe418f2SJia Liu regnames[i]); 117bbe418f2SJia Liu } 1186597c28dSRichard Henderson cpu_R0 = cpu_R[0]; 119bbe418f2SJia Liu } 120bbe418f2SJia Liu 121bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp) 122bbe418f2SJia Liu { 123bbe418f2SJia Liu TCGv_i32 tmp = tcg_const_i32(excp); 124bbe418f2SJia Liu gen_helper_exception(cpu_env, tmp); 125bbe418f2SJia Liu tcg_temp_free_i32(tmp); 126bbe418f2SJia Liu } 127bbe418f2SJia Liu 128bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc) 129bbe418f2SJia Liu { 1301ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 131bbe418f2SJia Liu gen_exception(dc, EXCP_ILLEGAL); 1321ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 133bbe418f2SJia Liu } 134bbe418f2SJia Liu 135bbe418f2SJia Liu /* not used yet, open it when we need or64. */ 136bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64 137bbe418f2SJia Liu static void check_ob64s(DisasContext *dc) 138bbe418f2SJia Liu { 139bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OB64S)) { 140bbe418f2SJia Liu gen_illegal_exception(dc); 141bbe418f2SJia Liu } 142bbe418f2SJia Liu } 143bbe418f2SJia Liu 144bbe418f2SJia Liu static void check_of64s(DisasContext *dc) 145bbe418f2SJia Liu { 146bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OF64S)) { 147bbe418f2SJia Liu gen_illegal_exception(dc); 148bbe418f2SJia Liu } 149bbe418f2SJia Liu } 150bbe418f2SJia Liu 151bbe418f2SJia Liu static void check_ov64s(DisasContext *dc) 152bbe418f2SJia Liu { 153bbe418f2SJia Liu if (!(dc->flags & CPUCFGR_OV64S)) { 154bbe418f2SJia Liu gen_illegal_exception(dc); 155bbe418f2SJia Liu } 156bbe418f2SJia Liu } 157bbe418f2SJia Liu #endif*/ 158bbe418f2SJia Liu 1596597c28dSRichard Henderson /* We're about to write to REG. On the off-chance that the user is 1606597c28dSRichard Henderson writing to R0, re-instate the architectural register. */ 1616597c28dSRichard Henderson #define check_r0_write(reg) \ 1626597c28dSRichard Henderson do { \ 1636597c28dSRichard Henderson if (unlikely(reg == 0)) { \ 1646597c28dSRichard Henderson cpu_R[0] = cpu_R0; \ 1656597c28dSRichard Henderson } \ 1666597c28dSRichard Henderson } while (0) 1676597c28dSRichard Henderson 16890aa39a1SSergey Fedorov static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) 16990aa39a1SSergey Fedorov { 1701ffa4bceSEmilio G. Cota if (unlikely(dc->base.singlestep_enabled)) { 17190aa39a1SSergey Fedorov return false; 17290aa39a1SSergey Fedorov } 17390aa39a1SSergey Fedorov 17490aa39a1SSergey Fedorov #ifndef CONFIG_USER_ONLY 1751ffa4bceSEmilio G. Cota return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); 17690aa39a1SSergey Fedorov #else 17790aa39a1SSergey Fedorov return true; 17890aa39a1SSergey Fedorov #endif 17990aa39a1SSergey Fedorov } 18090aa39a1SSergey Fedorov 181bbe418f2SJia Liu static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) 182bbe418f2SJia Liu { 18390aa39a1SSergey Fedorov if (use_goto_tb(dc, dest)) { 184bbe418f2SJia Liu tcg_gen_movi_tl(cpu_pc, dest); 185bbe418f2SJia Liu tcg_gen_goto_tb(n); 1861ffa4bceSEmilio G. Cota tcg_gen_exit_tb((uintptr_t)dc->base.tb + n); 187bbe418f2SJia Liu } else { 188bbe418f2SJia Liu tcg_gen_movi_tl(cpu_pc, dest); 1891ffa4bceSEmilio G. Cota if (dc->base.singlestep_enabled) { 190bbe418f2SJia Liu gen_exception(dc, EXCP_DEBUG); 191bbe418f2SJia Liu } 192bbe418f2SJia Liu tcg_gen_exit_tb(0); 193bbe418f2SJia Liu } 194bbe418f2SJia Liu } 195bbe418f2SJia Liu 19697458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 1979ecaa27eSRichard Henderson { 1980c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 19997458071SRichard Henderson gen_helper_ove_cy(cpu_env); 2009ecaa27eSRichard Henderson } 2010c53d734SRichard Henderson } 2029ecaa27eSRichard Henderson 20397458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 2049ecaa27eSRichard Henderson { 2050c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 20697458071SRichard Henderson gen_helper_ove_ov(cpu_env); 2079ecaa27eSRichard Henderson } 2080c53d734SRichard Henderson } 2099ecaa27eSRichard Henderson 21097458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 2119ecaa27eSRichard Henderson { 2120c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 21397458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 2149ecaa27eSRichard Henderson } 2150c53d734SRichard Henderson } 2169ecaa27eSRichard Henderson 2179ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2189ecaa27eSRichard Henderson { 2199ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2209ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2219ecaa27eSRichard Henderson 22297458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 22397458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2249ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 22597458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2269ecaa27eSRichard Henderson tcg_temp_free(t0); 2279ecaa27eSRichard Henderson 2289ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2299ecaa27eSRichard Henderson tcg_temp_free(res); 2309ecaa27eSRichard Henderson 23197458071SRichard Henderson gen_ove_cyov(dc); 2329ecaa27eSRichard Henderson } 2339ecaa27eSRichard Henderson 2349ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2359ecaa27eSRichard Henderson { 2369ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2379ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2389ecaa27eSRichard Henderson 23997458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 24097458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 24197458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2429ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 24397458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2449ecaa27eSRichard Henderson tcg_temp_free(t0); 2459ecaa27eSRichard Henderson 2469ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2479ecaa27eSRichard Henderson tcg_temp_free(res); 2489ecaa27eSRichard Henderson 24997458071SRichard Henderson gen_ove_cyov(dc); 2509ecaa27eSRichard Henderson } 2519ecaa27eSRichard Henderson 2529ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2539ecaa27eSRichard Henderson { 2549ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2559ecaa27eSRichard Henderson 2569ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 25797458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 25897458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 25997458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 26097458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 2619ecaa27eSRichard Henderson 2629ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2639ecaa27eSRichard Henderson tcg_temp_free(res); 2649ecaa27eSRichard Henderson 26597458071SRichard Henderson gen_ove_cyov(dc); 2669ecaa27eSRichard Henderson } 2679ecaa27eSRichard Henderson 2689ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2699ecaa27eSRichard Henderson { 2709ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2719ecaa27eSRichard Henderson 27297458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 2739ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 27497458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 2759ecaa27eSRichard Henderson tcg_temp_free(t0); 2769ecaa27eSRichard Henderson 27797458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 27897458071SRichard Henderson gen_ove_ov(dc); 2799ecaa27eSRichard Henderson } 2809ecaa27eSRichard Henderson 2819ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2829ecaa27eSRichard Henderson { 28397458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 28497458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 2859ecaa27eSRichard Henderson 28697458071SRichard Henderson gen_ove_cy(dc); 2879ecaa27eSRichard Henderson } 2889ecaa27eSRichard Henderson 2899ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2909ecaa27eSRichard Henderson { 2919ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 2929ecaa27eSRichard Henderson 29397458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 2949ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 2959ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 29697458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 2979ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 2989ecaa27eSRichard Henderson tcg_temp_free(t0); 2999ecaa27eSRichard Henderson 30097458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 30197458071SRichard Henderson gen_ove_ov(dc); 3029ecaa27eSRichard Henderson } 3039ecaa27eSRichard Henderson 3049ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 3059ecaa27eSRichard Henderson { 3069ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 3079ecaa27eSRichard Henderson 30897458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 3099ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 3109ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 31197458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 3129ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 3139ecaa27eSRichard Henderson tcg_temp_free(t0); 3149ecaa27eSRichard Henderson 31597458071SRichard Henderson gen_ove_cy(dc); 3169ecaa27eSRichard Henderson } 317da1d7759SSebastian Macke 318cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 319cc5de49eSRichard Henderson { 320cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 321cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 322cc5de49eSRichard Henderson 323cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 324cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 325cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 326cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 327cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 328cc5de49eSRichard Henderson } else { 329cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 330cc5de49eSRichard Henderson 331cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 332cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 333cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 334cc5de49eSRichard Henderson tcg_temp_free_i64(high); 335cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 336cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 337cc5de49eSRichard Henderson 338cc5de49eSRichard Henderson gen_ove_ov(dc); 339cc5de49eSRichard Henderson } 340cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 341cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 342cc5de49eSRichard Henderson } 343cc5de49eSRichard Henderson 344cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 345cc5de49eSRichard Henderson { 346cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 347cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 348cc5de49eSRichard Henderson 349cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 350cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 351cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 352cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 353cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 354cc5de49eSRichard Henderson } else { 355cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 356cc5de49eSRichard Henderson 357cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 358cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 359cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 360cc5de49eSRichard Henderson tcg_temp_free_i64(high); 361cc5de49eSRichard Henderson 362cc5de49eSRichard Henderson gen_ove_cy(dc); 363cc5de49eSRichard Henderson } 364cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 365cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 366cc5de49eSRichard Henderson } 367cc5de49eSRichard Henderson 3686f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 3696f7332baSRichard Henderson { 3706f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 3716f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 3726f7332baSRichard Henderson 3736f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 3746f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 3756f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 3766f7332baSRichard Henderson 3776f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 3786f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 3796f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 3806f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 3816f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 3826f7332baSRichard Henderson tcg_temp_free_i64(t2); 3836f7332baSRichard Henderson 3846f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 3856f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 3866f7332baSRichard Henderson #else 3876f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 3886f7332baSRichard Henderson #endif 3896f7332baSRichard Henderson tcg_temp_free_i64(t1); 3906f7332baSRichard Henderson 3916f7332baSRichard Henderson gen_ove_ov(dc); 3926f7332baSRichard Henderson } 3936f7332baSRichard Henderson 394cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 395cc5de49eSRichard Henderson { 396cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 397cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 398cc5de49eSRichard Henderson 399cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 400cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 401cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 402cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 403cc5de49eSRichard Henderson 404cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 405cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 406cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 407cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 408cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 409cc5de49eSRichard Henderson 410cc5de49eSRichard Henderson gen_ove_cy(dc); 411cc5de49eSRichard Henderson } 412cc5de49eSRichard Henderson 4136f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 4146f7332baSRichard Henderson { 4156f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4166f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4176f7332baSRichard Henderson 4186f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4196f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4206f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4216f7332baSRichard Henderson 4226f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4236f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4246f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4256f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4266f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4276f7332baSRichard Henderson tcg_temp_free_i64(t2); 4286f7332baSRichard Henderson 4296f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4306f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4316f7332baSRichard Henderson #else 4326f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4336f7332baSRichard Henderson #endif 4346f7332baSRichard Henderson tcg_temp_free_i64(t1); 4356f7332baSRichard Henderson 4366f7332baSRichard Henderson gen_ove_ov(dc); 4376f7332baSRichard Henderson } 4386f7332baSRichard Henderson 439cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 440cc5de49eSRichard Henderson { 441cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 442cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 443cc5de49eSRichard Henderson 444cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 445cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 446cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 447cc5de49eSRichard Henderson 448cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 449cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 450cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 451cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 452cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 453cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 454cc5de49eSRichard Henderson 455cc5de49eSRichard Henderson gen_ove_cy(dc); 456cc5de49eSRichard Henderson } 457cc5de49eSRichard Henderson 4586ad216abSRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a, uint32_t insn) 459bbe418f2SJia Liu { 4606ad216abSRichard Henderson LOG_DIS("l.add r%d, r%d, r%d\n", a->d, a->a, a->b); 4616ad216abSRichard Henderson check_r0_write(a->d); 4626ad216abSRichard Henderson gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4636ad216abSRichard Henderson return true; 464bbe418f2SJia Liu } 465bbe418f2SJia Liu 4666ad216abSRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a, uint32_t insn) 467bbe418f2SJia Liu { 4686ad216abSRichard Henderson LOG_DIS("l.addc r%d, r%d, r%d\n", a->d, a->a, a->b); 4696ad216abSRichard Henderson check_r0_write(a->d); 4706ad216abSRichard Henderson gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4716ad216abSRichard Henderson return true; 4726ad216abSRichard Henderson } 4736ad216abSRichard Henderson 4746ad216abSRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a, uint32_t insn) 4756ad216abSRichard Henderson { 4766ad216abSRichard Henderson LOG_DIS("l.sub r%d, r%d, r%d\n", a->d, a->a, a->b); 4776ad216abSRichard Henderson check_r0_write(a->d); 4786ad216abSRichard Henderson gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4796ad216abSRichard Henderson return true; 4806ad216abSRichard Henderson } 4816ad216abSRichard Henderson 4826ad216abSRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a, uint32_t insn) 4836ad216abSRichard Henderson { 4846ad216abSRichard Henderson LOG_DIS("l.and r%d, r%d, r%d\n", a->d, a->a, a->b); 4856ad216abSRichard Henderson check_r0_write(a->d); 4866ad216abSRichard Henderson tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4876ad216abSRichard Henderson return true; 4886ad216abSRichard Henderson } 4896ad216abSRichard Henderson 4906ad216abSRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a, uint32_t insn) 4916ad216abSRichard Henderson { 4926ad216abSRichard Henderson LOG_DIS("l.or r%d, r%d, r%d\n", a->d, a->a, a->b); 4936ad216abSRichard Henderson check_r0_write(a->d); 4946ad216abSRichard Henderson tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 4956ad216abSRichard Henderson return true; 4966ad216abSRichard Henderson } 4976ad216abSRichard Henderson 4986ad216abSRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a, uint32_t insn) 4996ad216abSRichard Henderson { 5006ad216abSRichard Henderson LOG_DIS("l.xor r%d, r%d, r%d\n", a->d, a->a, a->b); 5016ad216abSRichard Henderson check_r0_write(a->d); 5026ad216abSRichard Henderson tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5036ad216abSRichard Henderson return true; 5046ad216abSRichard Henderson } 5056ad216abSRichard Henderson 5066ad216abSRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a, uint32_t insn) 5076ad216abSRichard Henderson { 5086ad216abSRichard Henderson LOG_DIS("l.sll r%d, r%d, r%d\n", a->d, a->a, a->b); 5096ad216abSRichard Henderson check_r0_write(a->d); 5106ad216abSRichard Henderson tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5116ad216abSRichard Henderson return true; 5126ad216abSRichard Henderson } 5136ad216abSRichard Henderson 5146ad216abSRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a, uint32_t insn) 5156ad216abSRichard Henderson { 5166ad216abSRichard Henderson LOG_DIS("l.srl r%d, r%d, r%d\n", a->d, a->a, a->b); 5176ad216abSRichard Henderson check_r0_write(a->d); 5186ad216abSRichard Henderson tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5196ad216abSRichard Henderson return true; 5206ad216abSRichard Henderson } 5216ad216abSRichard Henderson 5226ad216abSRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a, uint32_t insn) 5236ad216abSRichard Henderson { 5246ad216abSRichard Henderson LOG_DIS("l.sra r%d, r%d, r%d\n", a->d, a->a, a->b); 5256ad216abSRichard Henderson check_r0_write(a->d); 5266ad216abSRichard Henderson tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5276ad216abSRichard Henderson return true; 5286ad216abSRichard Henderson } 5296ad216abSRichard Henderson 5306ad216abSRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a, uint32_t insn) 5316ad216abSRichard Henderson { 5326ad216abSRichard Henderson LOG_DIS("l.ror r%d, r%d, r%d\n", a->d, a->a, a->b); 5336ad216abSRichard Henderson check_r0_write(a->d); 5346ad216abSRichard Henderson tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 5356ad216abSRichard Henderson return true; 5366ad216abSRichard Henderson } 5376ad216abSRichard Henderson 5386ad216abSRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a, uint32_t insn) 5396ad216abSRichard Henderson { 5406ad216abSRichard Henderson LOG_DIS("l.exths r%d, r%d\n", a->d, a->a); 5416ad216abSRichard Henderson check_r0_write(a->d); 5426ad216abSRichard Henderson tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]); 5436ad216abSRichard Henderson return true; 5446ad216abSRichard Henderson } 5456ad216abSRichard Henderson 5466ad216abSRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a, uint32_t insn) 5476ad216abSRichard Henderson { 5486ad216abSRichard Henderson LOG_DIS("l.extbs r%d, r%d\n", a->d, a->a); 5496ad216abSRichard Henderson check_r0_write(a->d); 5506ad216abSRichard Henderson tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]); 5516ad216abSRichard Henderson return true; 5526ad216abSRichard Henderson } 5536ad216abSRichard Henderson 5546ad216abSRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a, uint32_t insn) 5556ad216abSRichard Henderson { 5566ad216abSRichard Henderson LOG_DIS("l.exthz r%d, r%d\n", a->d, a->a); 5576ad216abSRichard Henderson check_r0_write(a->d); 5586ad216abSRichard Henderson tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]); 5596ad216abSRichard Henderson return true; 5606ad216abSRichard Henderson } 5616ad216abSRichard Henderson 5626ad216abSRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a, uint32_t insn) 5636ad216abSRichard Henderson { 5646ad216abSRichard Henderson LOG_DIS("l.extbz r%d, r%d\n", a->d, a->a); 5656ad216abSRichard Henderson check_r0_write(a->d); 5666ad216abSRichard Henderson tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]); 5676ad216abSRichard Henderson return true; 5686ad216abSRichard Henderson } 5696ad216abSRichard Henderson 5706ad216abSRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a, uint32_t insn) 5716ad216abSRichard Henderson { 5726ad216abSRichard Henderson TCGv zero; 5736ad216abSRichard Henderson LOG_DIS("l.cmov r%d, r%d, r%d\n", a->d, a->a, a->b); 5746ad216abSRichard Henderson 5756ad216abSRichard Henderson check_r0_write(a->d); 5766ad216abSRichard Henderson zero = tcg_const_tl(0); 5776ad216abSRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[a->d], cpu_sr_f, zero, 5786ad216abSRichard Henderson cpu_R[a->a], cpu_R[a->b]); 579784696d1SRichard Henderson tcg_temp_free(zero); 5806ad216abSRichard Henderson return true; 581bbe418f2SJia Liu } 582bbe418f2SJia Liu 5836ad216abSRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a, uint32_t insn) 5846ad216abSRichard Henderson { 5856ad216abSRichard Henderson LOG_DIS("l.ff1 r%d, r%d\n", a->d, a->a); 5866ad216abSRichard Henderson 5876ad216abSRichard Henderson check_r0_write(a->d); 5886ad216abSRichard Henderson tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1); 5896ad216abSRichard Henderson tcg_gen_addi_tl(cpu_R[a->d], cpu_R[a->d], 1); 5906ad216abSRichard Henderson return true; 591cf2ae442SRichard Henderson } 592cf2ae442SRichard Henderson 5936ad216abSRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a, uint32_t insn) 5946ad216abSRichard Henderson { 5956ad216abSRichard Henderson LOG_DIS("l.fl1 r%d, r%d\n", a->d, a->a); 5966ad216abSRichard Henderson 5976ad216abSRichard Henderson check_r0_write(a->d); 5986ad216abSRichard Henderson tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS); 5996ad216abSRichard Henderson tcg_gen_subfi_tl(cpu_R[a->d], TARGET_LONG_BITS, cpu_R[a->d]); 6006ad216abSRichard Henderson return true; 601bbe418f2SJia Liu } 602bbe418f2SJia Liu 6036ad216abSRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a, uint32_t insn) 6046ad216abSRichard Henderson { 6056ad216abSRichard Henderson LOG_DIS("l.mul r%d, r%d, r%d\n", a->d, a->a, a->b); 606bbe418f2SJia Liu 6076ad216abSRichard Henderson check_r0_write(a->d); 6086ad216abSRichard Henderson gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 6096ad216abSRichard Henderson return true; 610bbe418f2SJia Liu } 6116ad216abSRichard Henderson 6126ad216abSRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a, uint32_t insn) 6136ad216abSRichard Henderson { 6146ad216abSRichard Henderson LOG_DIS("l.mulu r%d, r%d, r%d\n", a->d, a->a, a->b); 6156ad216abSRichard Henderson 6166ad216abSRichard Henderson check_r0_write(a->d); 6176ad216abSRichard Henderson gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 6186ad216abSRichard Henderson return true; 619bbe418f2SJia Liu } 6206ad216abSRichard Henderson 6216ad216abSRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a, uint32_t insn) 6226ad216abSRichard Henderson { 6236ad216abSRichard Henderson LOG_DIS("l.div r%d, r%d, r%d\n", a->d, a->a, a->b); 6246ad216abSRichard Henderson 6256ad216abSRichard Henderson check_r0_write(a->d); 6266ad216abSRichard Henderson gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 6276ad216abSRichard Henderson return true; 6286ad216abSRichard Henderson } 6296ad216abSRichard Henderson 6306ad216abSRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a, uint32_t insn) 6316ad216abSRichard Henderson { 6326ad216abSRichard Henderson LOG_DIS("l.divu r%d, r%d, r%d\n", a->d, a->a, a->b); 6336ad216abSRichard Henderson 6346ad216abSRichard Henderson check_r0_write(a->d); 6356ad216abSRichard Henderson gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); 6366ad216abSRichard Henderson return true; 6376ad216abSRichard Henderson } 6386ad216abSRichard Henderson 6396ad216abSRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a, uint32_t insn) 6406ad216abSRichard Henderson { 6416ad216abSRichard Henderson LOG_DIS("l.muld r%d, r%d\n", a->a, a->b); 6426ad216abSRichard Henderson gen_muld(dc, cpu_R[a->a], cpu_R[a->b]); 6436ad216abSRichard Henderson return true; 6446ad216abSRichard Henderson } 6456ad216abSRichard Henderson 6466ad216abSRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a, uint32_t insn) 6476ad216abSRichard Henderson { 6486ad216abSRichard Henderson LOG_DIS("l.muldu r%d, r%d\n", a->a, a->b); 6496ad216abSRichard Henderson gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]); 6506ad216abSRichard Henderson return true; 651bbe418f2SJia Liu } 652bbe418f2SJia Liu 653136e13aeSRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) 654136e13aeSRichard Henderson { 655136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 656136e13aeSRichard Henderson 657136e13aeSRichard Henderson LOG_DIS("l.j %d\n", a->n); 658136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 659136e13aeSRichard Henderson dc->delayed_branch = 2; 660136e13aeSRichard Henderson return true; 661136e13aeSRichard Henderson } 662136e13aeSRichard Henderson 663136e13aeSRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn) 664136e13aeSRichard Henderson { 665136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 666136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 667136e13aeSRichard Henderson 668136e13aeSRichard Henderson LOG_DIS("l.jal %d\n", a->n); 669136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], ret_pc); 670136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 671136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 672136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 673136e13aeSRichard Henderson dc->delayed_branch = 2; 674136e13aeSRichard Henderson } 675136e13aeSRichard Henderson return true; 676136e13aeSRichard Henderson } 677136e13aeSRichard Henderson 678136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 679136e13aeSRichard Henderson { 680136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 681136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 682136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 683136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 684136e13aeSRichard Henderson 685136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 686136e13aeSRichard Henderson 687136e13aeSRichard Henderson tcg_temp_free(t_next); 688136e13aeSRichard Henderson tcg_temp_free(t_true); 689136e13aeSRichard Henderson tcg_temp_free(t_zero); 690136e13aeSRichard Henderson dc->delayed_branch = 2; 691136e13aeSRichard Henderson } 692136e13aeSRichard Henderson 693136e13aeSRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 694136e13aeSRichard Henderson { 695136e13aeSRichard Henderson LOG_DIS("l.bf %d\n", a->n); 696136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 697136e13aeSRichard Henderson return true; 698136e13aeSRichard Henderson } 699136e13aeSRichard Henderson 700136e13aeSRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 701136e13aeSRichard Henderson { 702136e13aeSRichard Henderson LOG_DIS("l.bnf %d\n", a->n); 703136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 704136e13aeSRichard Henderson return true; 705136e13aeSRichard Henderson } 706136e13aeSRichard Henderson 707136e13aeSRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn) 708136e13aeSRichard Henderson { 709136e13aeSRichard Henderson LOG_DIS("l.jr r%d\n", a->b); 710136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 711136e13aeSRichard Henderson dc->delayed_branch = 2; 712136e13aeSRichard Henderson return true; 713136e13aeSRichard Henderson } 714136e13aeSRichard Henderson 715136e13aeSRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) 716136e13aeSRichard Henderson { 717136e13aeSRichard Henderson LOG_DIS("l.jalr r%d\n", a->b); 718136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 719136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); 720136e13aeSRichard Henderson dc->delayed_branch = 2; 721136e13aeSRichard Henderson return true; 722136e13aeSRichard Henderson } 723136e13aeSRichard Henderson 724d80bff19SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn) 725d80bff19SRichard Henderson { 726d80bff19SRichard Henderson TCGv ea; 727d80bff19SRichard Henderson 728d80bff19SRichard Henderson LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i); 729d80bff19SRichard Henderson 730d80bff19SRichard Henderson check_r0_write(a->d); 731d80bff19SRichard Henderson ea = tcg_temp_new(); 732d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 733d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL); 734d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 735d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]); 736d80bff19SRichard Henderson tcg_temp_free(ea); 737d80bff19SRichard Henderson return true; 738d80bff19SRichard Henderson } 739d80bff19SRichard Henderson 740d80bff19SRichard Henderson static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop) 741d80bff19SRichard Henderson { 742d80bff19SRichard Henderson TCGv ea; 743d80bff19SRichard Henderson 744d80bff19SRichard Henderson check_r0_write(a->d); 745d80bff19SRichard Henderson ea = tcg_temp_new(); 746d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 747d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop); 748d80bff19SRichard Henderson tcg_temp_free(ea); 749d80bff19SRichard Henderson } 750d80bff19SRichard Henderson 751d80bff19SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn) 752d80bff19SRichard Henderson { 753d80bff19SRichard Henderson LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i); 754d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 755d80bff19SRichard Henderson return true; 756d80bff19SRichard Henderson } 757d80bff19SRichard Henderson 758d80bff19SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn) 759d80bff19SRichard Henderson { 760d80bff19SRichard Henderson LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i); 761d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 762d80bff19SRichard Henderson return true; 763d80bff19SRichard Henderson } 764d80bff19SRichard Henderson 765d80bff19SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn) 766d80bff19SRichard Henderson { 767d80bff19SRichard Henderson LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i); 768d80bff19SRichard Henderson do_load(dc, a, MO_UB); 769d80bff19SRichard Henderson return true; 770d80bff19SRichard Henderson } 771d80bff19SRichard Henderson 772d80bff19SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn) 773d80bff19SRichard Henderson { 774d80bff19SRichard Henderson LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i); 775d80bff19SRichard Henderson do_load(dc, a, MO_SB); 776d80bff19SRichard Henderson return true; 777d80bff19SRichard Henderson } 778d80bff19SRichard Henderson 779d80bff19SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn) 780d80bff19SRichard Henderson { 781d80bff19SRichard Henderson LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i); 782d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 783d80bff19SRichard Henderson return true; 784d80bff19SRichard Henderson } 785d80bff19SRichard Henderson 786d80bff19SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn) 787d80bff19SRichard Henderson { 788d80bff19SRichard Henderson LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i); 789d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 790d80bff19SRichard Henderson return true; 791d80bff19SRichard Henderson } 792d80bff19SRichard Henderson 793d80bff19SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn) 794d80bff19SRichard Henderson { 795d80bff19SRichard Henderson TCGv ea, val; 796d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 797d80bff19SRichard Henderson 798d80bff19SRichard Henderson LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i); 799d80bff19SRichard Henderson 800d80bff19SRichard Henderson ea = tcg_temp_new(); 801d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 802d80bff19SRichard Henderson 803d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 804d80bff19SRichard Henderson to cpu_R[0]. Since l.swa is quite often immediately followed by a 805d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 806d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 807d80bff19SRichard Henderson cpu_R[0] = cpu_R0; 808d80bff19SRichard Henderson 809d80bff19SRichard Henderson lab_fail = gen_new_label(); 810d80bff19SRichard Henderson lab_done = gen_new_label(); 811d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 812d80bff19SRichard Henderson tcg_temp_free(ea); 813d80bff19SRichard Henderson 814d80bff19SRichard Henderson val = tcg_temp_new(); 815d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 816d80bff19SRichard Henderson cpu_R[a->b], dc->mem_idx, MO_TEUL); 817d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 818d80bff19SRichard Henderson tcg_temp_free(val); 819d80bff19SRichard Henderson 820d80bff19SRichard Henderson tcg_gen_br(lab_done); 821d80bff19SRichard Henderson 822d80bff19SRichard Henderson gen_set_label(lab_fail); 823d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 824d80bff19SRichard Henderson 825d80bff19SRichard Henderson gen_set_label(lab_done); 826d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 827d80bff19SRichard Henderson return true; 828d80bff19SRichard Henderson } 829d80bff19SRichard Henderson 830d80bff19SRichard Henderson static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop) 831d80bff19SRichard Henderson { 832d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 833d80bff19SRichard Henderson tcg_gen_addi_tl(t0, cpu_R[a->a], a->i); 834d80bff19SRichard Henderson tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop); 835d80bff19SRichard Henderson tcg_temp_free(t0); 836d80bff19SRichard Henderson } 837d80bff19SRichard Henderson 838d80bff19SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn) 839d80bff19SRichard Henderson { 840d80bff19SRichard Henderson LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i); 841d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 842d80bff19SRichard Henderson return true; 843d80bff19SRichard Henderson } 844d80bff19SRichard Henderson 845d80bff19SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn) 846d80bff19SRichard Henderson { 847d80bff19SRichard Henderson LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i); 848d80bff19SRichard Henderson do_store(dc, a, MO_UB); 849d80bff19SRichard Henderson return true; 850d80bff19SRichard Henderson } 851d80bff19SRichard Henderson 852d80bff19SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn) 853d80bff19SRichard Henderson { 854d80bff19SRichard Henderson LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i); 855d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 856d80bff19SRichard Henderson return true; 857d80bff19SRichard Henderson } 858d80bff19SRichard Henderson 8598816f70bSRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn) 860bbe418f2SJia Liu { 8618816f70bSRichard Henderson LOG_DIS("l.nop %d\n", a->k); 8628816f70bSRichard Henderson return true; 8638816f70bSRichard Henderson } 8648816f70bSRichard Henderson 8658816f70bSRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) 8668816f70bSRichard Henderson { 8679ecaa27eSRichard Henderson TCGv t0; 8685631e69cSRichard Henderson 8698816f70bSRichard Henderson LOG_DIS("l.addi r%d, r%d, %d\n", a->d, a->a, a->i); 8708816f70bSRichard Henderson check_r0_write(a->d); 8718816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8728816f70bSRichard Henderson gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0); 8736f7332baSRichard Henderson tcg_temp_free(t0); 8748816f70bSRichard Henderson return true; 8758816f70bSRichard Henderson } 876bbe418f2SJia Liu 8778816f70bSRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) 878bbe418f2SJia Liu { 8798816f70bSRichard Henderson TCGv t0; 8808816f70bSRichard Henderson 8818816f70bSRichard Henderson LOG_DIS("l.addic r%d, r%d, %d\n", a->d, a->a, a->i); 8828816f70bSRichard Henderson check_r0_write(a->d); 8838816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8848816f70bSRichard Henderson gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0); 8858816f70bSRichard Henderson tcg_temp_free(t0); 8868816f70bSRichard Henderson return true; 8878816f70bSRichard Henderson } 8888816f70bSRichard Henderson 8898816f70bSRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) 8908816f70bSRichard Henderson { 8918816f70bSRichard Henderson TCGv t0; 8928816f70bSRichard Henderson 8938816f70bSRichard Henderson LOG_DIS("l.muli r%d, r%d, %d\n", a->d, a->a, a->i); 8948816f70bSRichard Henderson check_r0_write(a->d); 8958816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 8968816f70bSRichard Henderson gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0); 8978816f70bSRichard Henderson tcg_temp_free(t0); 8988816f70bSRichard Henderson return true; 8998816f70bSRichard Henderson } 9008816f70bSRichard Henderson 9018816f70bSRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) 9028816f70bSRichard Henderson { 9038816f70bSRichard Henderson TCGv t0; 9048816f70bSRichard Henderson 9058816f70bSRichard Henderson LOG_DIS("l.maci r%d, %d\n", a->a, a->i); 9068816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 9078816f70bSRichard Henderson gen_mac(dc, cpu_R[a->a], t0); 9088816f70bSRichard Henderson tcg_temp_free(t0); 9098816f70bSRichard Henderson return true; 9108816f70bSRichard Henderson } 9118816f70bSRichard Henderson 9128816f70bSRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn) 9138816f70bSRichard Henderson { 9148816f70bSRichard Henderson LOG_DIS("l.andi r%d, r%d, %d\n", a->d, a->a, a->k); 9158816f70bSRichard Henderson check_r0_write(a->d); 9168816f70bSRichard Henderson tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k); 9178816f70bSRichard Henderson return true; 9188816f70bSRichard Henderson } 9198816f70bSRichard Henderson 9208816f70bSRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn) 9218816f70bSRichard Henderson { 9228816f70bSRichard Henderson LOG_DIS("l.ori r%d, r%d, %d\n", a->d, a->a, a->k); 9238816f70bSRichard Henderson check_r0_write(a->d); 9248816f70bSRichard Henderson tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k); 9258816f70bSRichard Henderson return true; 9268816f70bSRichard Henderson } 9278816f70bSRichard Henderson 9288816f70bSRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn) 9298816f70bSRichard Henderson { 9308816f70bSRichard Henderson LOG_DIS("l.xori r%d, r%d, %d\n", a->d, a->a, a->i); 9318816f70bSRichard Henderson check_r0_write(a->d); 9328816f70bSRichard Henderson tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i); 9338816f70bSRichard Henderson return true; 9348816f70bSRichard Henderson } 9358816f70bSRichard Henderson 9368816f70bSRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) 9378816f70bSRichard Henderson { 9388816f70bSRichard Henderson LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k); 9398816f70bSRichard Henderson check_r0_write(a->d); 9408816f70bSRichard Henderson 9418816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 9428816f70bSRichard Henderson gen_illegal_exception(dc); 943bbe418f2SJia Liu #else 944bbe418f2SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 945bbe418f2SJia Liu gen_illegal_exception(dc); 9468816f70bSRichard Henderson } else { 9478816f70bSRichard Henderson TCGv_i32 ti = tcg_const_i32(a->k); 9488816f70bSRichard Henderson gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti); 9494dd044c6SJia Liu tcg_temp_free_i32(ti); 9504dd044c6SJia Liu } 9518816f70bSRichard Henderson #endif 9528816f70bSRichard Henderson return true; 9538816f70bSRichard Henderson } 954bbe418f2SJia Liu 9558816f70bSRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) 9564dd044c6SJia Liu { 9578816f70bSRichard Henderson LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k); 9588816f70bSRichard Henderson 9598816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 9608816f70bSRichard Henderson gen_illegal_exception(dc); 9614dd044c6SJia Liu #else 9624dd044c6SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 9634dd044c6SJia Liu gen_illegal_exception(dc); 9648816f70bSRichard Henderson } else { 9658816f70bSRichard Henderson TCGv_i32 ti = tcg_const_i32(a->k); 9668816f70bSRichard Henderson gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti); 9678816f70bSRichard Henderson tcg_temp_free_i32(ti); 9684dd044c6SJia Liu } 9694dd044c6SJia Liu #endif 9708816f70bSRichard Henderson return true; 971bbe418f2SJia Liu } 972bbe418f2SJia Liu 97399d863d6SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a, uint32_t insn) 974bbe418f2SJia Liu { 97599d863d6SRichard Henderson LOG_DIS("l.mac r%d, r%d\n", a->a, a->b); 97699d863d6SRichard Henderson gen_mac(dc, cpu_R[a->a], cpu_R[a->b]); 97799d863d6SRichard Henderson return true; 978bbe418f2SJia Liu } 97999d863d6SRichard Henderson 98099d863d6SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a, uint32_t insn) 98199d863d6SRichard Henderson { 98299d863d6SRichard Henderson LOG_DIS("l.msb r%d, r%d\n", a->a, a->b); 98399d863d6SRichard Henderson gen_msb(dc, cpu_R[a->a], cpu_R[a->b]); 98499d863d6SRichard Henderson return true; 98599d863d6SRichard Henderson } 98699d863d6SRichard Henderson 98799d863d6SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a, uint32_t insn) 98899d863d6SRichard Henderson { 98999d863d6SRichard Henderson LOG_DIS("l.mac r%d, r%d\n", a->a, a->b); 99099d863d6SRichard Henderson gen_macu(dc, cpu_R[a->a], cpu_R[a->b]); 99199d863d6SRichard Henderson return true; 99299d863d6SRichard Henderson } 99399d863d6SRichard Henderson 99499d863d6SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a, uint32_t insn) 99599d863d6SRichard Henderson { 99699d863d6SRichard Henderson LOG_DIS("l.msb r%d, r%d\n", a->a, a->b); 99799d863d6SRichard Henderson gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]); 99899d863d6SRichard Henderson return true; 999bbe418f2SJia Liu } 1000bbe418f2SJia Liu 1001e20c2592SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a, uint32_t insn) 1002bbe418f2SJia Liu { 1003e20c2592SRichard Henderson LOG_DIS("l.slli r%d, r%d, %d\n", a->d, a->a, a->l); 1004e20c2592SRichard Henderson check_r0_write(a->d); 1005e20c2592SRichard Henderson tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 1006e20c2592SRichard Henderson return true; 1007bbe418f2SJia Liu } 1008e20c2592SRichard Henderson 1009e20c2592SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a, uint32_t insn) 1010e20c2592SRichard Henderson { 1011e20c2592SRichard Henderson LOG_DIS("l.srli r%d, r%d, %d\n", a->d, a->a, a->l); 1012e20c2592SRichard Henderson check_r0_write(a->d); 1013e20c2592SRichard Henderson tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 1014e20c2592SRichard Henderson return true; 1015e20c2592SRichard Henderson } 1016e20c2592SRichard Henderson 1017e20c2592SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a, uint32_t insn) 1018e20c2592SRichard Henderson { 1019e20c2592SRichard Henderson LOG_DIS("l.srai r%d, r%d, %d\n", a->d, a->a, a->l); 1020e20c2592SRichard Henderson check_r0_write(a->d); 1021e20c2592SRichard Henderson tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 1022e20c2592SRichard Henderson return true; 1023e20c2592SRichard Henderson } 1024e20c2592SRichard Henderson 1025e20c2592SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a, uint32_t insn) 1026e20c2592SRichard Henderson { 1027e20c2592SRichard Henderson LOG_DIS("l.rori r%d, r%d, %d\n", a->d, a->a, a->l); 1028e20c2592SRichard Henderson check_r0_write(a->d); 1029e20c2592SRichard Henderson tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); 1030e20c2592SRichard Henderson return true; 1031bbe418f2SJia Liu } 1032bbe418f2SJia Liu 1033e720a571SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a, uint32_t insn) 1034bbe418f2SJia Liu { 1035e720a571SRichard Henderson LOG_DIS("l.movhi r%d, %d\n", a->d, a->k); 1036e720a571SRichard Henderson check_r0_write(a->d); 1037e720a571SRichard Henderson tcg_gen_movi_tl(cpu_R[a->d], a->k << 16); 1038e720a571SRichard Henderson return true; 1039bbe418f2SJia Liu } 1040e720a571SRichard Henderson 1041e720a571SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a, uint32_t insn) 1042e720a571SRichard Henderson { 1043e720a571SRichard Henderson LOG_DIS("l.macrc r%d\n", a->d); 1044e720a571SRichard Henderson check_r0_write(a->d); 1045e720a571SRichard Henderson tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac); 1046e720a571SRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 1047e720a571SRichard Henderson return true; 1048bbe418f2SJia Liu } 1049bbe418f2SJia Liu 1050fbb3e29aSRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a, TCGCond cond) 1051bbe418f2SJia Liu { 1052fbb3e29aSRichard Henderson LOG_DIS("l.sfeq r%d, r%d\n", a->a, a->b); 1053fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1054fbb3e29aSRichard Henderson return true; 1055bbe418f2SJia Liu } 1056fbb3e29aSRichard Henderson 1057fbb3e29aSRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a, TCGCond cond) 1058fbb3e29aSRichard Henderson { 1059fbb3e29aSRichard Henderson LOG_DIS("l.sfne r%d, r%d\n", a->a, a->b); 1060fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1061fbb3e29aSRichard Henderson return true; 1062fbb3e29aSRichard Henderson } 1063fbb3e29aSRichard Henderson 1064fbb3e29aSRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a, TCGCond cond) 1065fbb3e29aSRichard Henderson { 1066fbb3e29aSRichard Henderson LOG_DIS("l.sfgtu r%d, r%d\n", a->a, a->b); 1067fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1068fbb3e29aSRichard Henderson return true; 1069fbb3e29aSRichard Henderson } 1070fbb3e29aSRichard Henderson 1071fbb3e29aSRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a, TCGCond cond) 1072fbb3e29aSRichard Henderson { 1073fbb3e29aSRichard Henderson LOG_DIS("l.sfgeu r%d, r%d\n", a->a, a->b); 1074fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1075fbb3e29aSRichard Henderson return true; 1076fbb3e29aSRichard Henderson } 1077fbb3e29aSRichard Henderson 1078fbb3e29aSRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a, TCGCond cond) 1079fbb3e29aSRichard Henderson { 1080fbb3e29aSRichard Henderson LOG_DIS("l.sfltu r%d, r%d\n", a->a, a->b); 1081fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1082fbb3e29aSRichard Henderson return true; 1083fbb3e29aSRichard Henderson } 1084fbb3e29aSRichard Henderson 1085fbb3e29aSRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a, TCGCond cond) 1086fbb3e29aSRichard Henderson { 1087fbb3e29aSRichard Henderson LOG_DIS("l.sfleu r%d, r%d\n", a->a, a->b); 1088fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1089fbb3e29aSRichard Henderson return true; 1090fbb3e29aSRichard Henderson } 1091fbb3e29aSRichard Henderson 1092fbb3e29aSRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a, TCGCond cond) 1093fbb3e29aSRichard Henderson { 1094fbb3e29aSRichard Henderson LOG_DIS("l.sfgts r%d, r%d\n", a->a, a->b); 1095fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1096fbb3e29aSRichard Henderson return true; 1097fbb3e29aSRichard Henderson } 1098fbb3e29aSRichard Henderson 1099fbb3e29aSRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a, TCGCond cond) 1100fbb3e29aSRichard Henderson { 1101fbb3e29aSRichard Henderson LOG_DIS("l.sfges r%d, r%d\n", a->a, a->b); 1102fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1103fbb3e29aSRichard Henderson return true; 1104fbb3e29aSRichard Henderson } 1105fbb3e29aSRichard Henderson 1106fbb3e29aSRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a, TCGCond cond) 1107fbb3e29aSRichard Henderson { 1108fbb3e29aSRichard Henderson LOG_DIS("l.sflts r%d, r%d\n", a->a, a->b); 1109fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1110fbb3e29aSRichard Henderson return true; 1111fbb3e29aSRichard Henderson } 1112fbb3e29aSRichard Henderson 1113fbb3e29aSRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a, TCGCond cond) 1114fbb3e29aSRichard Henderson { 1115fbb3e29aSRichard Henderson LOG_DIS("l.sfles r%d, r%d\n", a->a, a->b); 1116fbb3e29aSRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); 1117fbb3e29aSRichard Henderson return true; 1118bbe418f2SJia Liu } 1119bbe418f2SJia Liu 1120*032de4fcSRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a, TCGCond cond) 1121bbe418f2SJia Liu { 1122*032de4fcSRichard Henderson LOG_DIS("l.sfeqi r%d, %d\n", a->a, a->i); 1123*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i); 1124*032de4fcSRichard Henderson return true; 1125bbe418f2SJia Liu } 1126*032de4fcSRichard Henderson 1127*032de4fcSRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a, TCGCond cond) 1128*032de4fcSRichard Henderson { 1129*032de4fcSRichard Henderson LOG_DIS("l.sfnei r%d, %d\n", a->a, a->i); 1130*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i); 1131*032de4fcSRichard Henderson return true; 1132*032de4fcSRichard Henderson } 1133*032de4fcSRichard Henderson 1134*032de4fcSRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a, TCGCond cond) 1135*032de4fcSRichard Henderson { 1136*032de4fcSRichard Henderson LOG_DIS("l.sfgtui r%d, %d\n", a->a, a->i); 1137*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i); 1138*032de4fcSRichard Henderson return true; 1139*032de4fcSRichard Henderson } 1140*032de4fcSRichard Henderson 1141*032de4fcSRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a, TCGCond cond) 1142*032de4fcSRichard Henderson { 1143*032de4fcSRichard Henderson LOG_DIS("l.sfgeui r%d, %d\n", a->a, a->i); 1144*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i); 1145*032de4fcSRichard Henderson return true; 1146*032de4fcSRichard Henderson } 1147*032de4fcSRichard Henderson 1148*032de4fcSRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a, TCGCond cond) 1149*032de4fcSRichard Henderson { 1150*032de4fcSRichard Henderson LOG_DIS("l.sfltui r%d, %d\n", a->a, a->i); 1151*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i); 1152*032de4fcSRichard Henderson return true; 1153*032de4fcSRichard Henderson } 1154*032de4fcSRichard Henderson 1155*032de4fcSRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a, TCGCond cond) 1156*032de4fcSRichard Henderson { 1157*032de4fcSRichard Henderson LOG_DIS("l.sfleui r%d, %d\n", a->a, a->i); 1158*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i); 1159*032de4fcSRichard Henderson return true; 1160*032de4fcSRichard Henderson } 1161*032de4fcSRichard Henderson 1162*032de4fcSRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a, TCGCond cond) 1163*032de4fcSRichard Henderson { 1164*032de4fcSRichard Henderson LOG_DIS("l.sfgtsi r%d, %d\n", a->a, a->i); 1165*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i); 1166*032de4fcSRichard Henderson return true; 1167*032de4fcSRichard Henderson } 1168*032de4fcSRichard Henderson 1169*032de4fcSRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a, TCGCond cond) 1170*032de4fcSRichard Henderson { 1171*032de4fcSRichard Henderson LOG_DIS("l.sfgesi r%d, %d\n", a->a, a->i); 1172*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i); 1173*032de4fcSRichard Henderson return true; 1174*032de4fcSRichard Henderson } 1175*032de4fcSRichard Henderson 1176*032de4fcSRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a, TCGCond cond) 1177*032de4fcSRichard Henderson { 1178*032de4fcSRichard Henderson LOG_DIS("l.sfltsi r%d, %d\n", a->a, a->i); 1179*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i); 1180*032de4fcSRichard Henderson return true; 1181*032de4fcSRichard Henderson } 1182*032de4fcSRichard Henderson 1183*032de4fcSRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a, TCGCond cond) 1184*032de4fcSRichard Henderson { 1185*032de4fcSRichard Henderson LOG_DIS("l.sflesi r%d, %d\n", a->a, a->i); 1186*032de4fcSRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i); 1187*032de4fcSRichard Henderson return true; 1188bbe418f2SJia Liu } 1189bbe418f2SJia Liu 11907de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) 1191bbe418f2SJia Liu { 11927de9729fSRichard Henderson LOG_DIS("l.sys %d\n", a->k); 11931ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1194bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11951ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11967de9729fSRichard Henderson return true; 11977de9729fSRichard Henderson } 1198bbe418f2SJia Liu 11997de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) 12007de9729fSRichard Henderson { 12017de9729fSRichard Henderson LOG_DIS("l.trap %d\n", a->k); 12021ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1203bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 12041ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 12057de9729fSRichard Henderson return true; 12067de9729fSRichard Henderson } 1207bbe418f2SJia Liu 12087de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) 12097de9729fSRichard Henderson { 1210bbe418f2SJia Liu LOG_DIS("l.msync\n"); 121124fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 12127de9729fSRichard Henderson return true; 1213bbe418f2SJia Liu } 12147de9729fSRichard Henderson 12157de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) 12167de9729fSRichard Henderson { 12177de9729fSRichard Henderson LOG_DIS("l.psync\n"); 12187de9729fSRichard Henderson return true; 12197de9729fSRichard Henderson } 12207de9729fSRichard Henderson 12217de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) 12227de9729fSRichard Henderson { 12237de9729fSRichard Henderson LOG_DIS("l.csync\n"); 12247de9729fSRichard Henderson return true; 1225bbe418f2SJia Liu } 1226bbe418f2SJia Liu 12278816f70bSRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn) 12288816f70bSRichard Henderson { 12298816f70bSRichard Henderson LOG_DIS("l.rfe\n"); 12308816f70bSRichard Henderson 12318816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 12328816f70bSRichard Henderson gen_illegal_exception(dc); 12338816f70bSRichard Henderson #else 12348816f70bSRichard Henderson if (dc->mem_idx == MMU_USER_IDX) { 12358816f70bSRichard Henderson gen_illegal_exception(dc); 12368816f70bSRichard Henderson } else { 12378816f70bSRichard Henderson gen_helper_rfe(cpu_env); 12388816f70bSRichard Henderson dc->base.is_jmp = DISAS_UPDATE; 12398816f70bSRichard Henderson } 12408816f70bSRichard Henderson #endif 12418816f70bSRichard Henderson return true; 12428816f70bSRichard Henderson } 12438816f70bSRichard Henderson 1244bbe418f2SJia Liu static void dec_float(DisasContext *dc, uint32_t insn) 1245bbe418f2SJia Liu { 1246bbe418f2SJia Liu uint32_t op0; 1247bbe418f2SJia Liu uint32_t ra, rb, rd; 1248bbe418f2SJia Liu op0 = extract32(insn, 0, 8); 1249bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1250bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1251bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1252bbe418f2SJia Liu 1253bbe418f2SJia Liu switch (op0) { 1254bbe418f2SJia Liu case 0x00: /* lf.add.s */ 1255bbe418f2SJia Liu LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); 12566597c28dSRichard Henderson check_r0_write(rd); 1257bbe418f2SJia Liu gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12584e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1259bbe418f2SJia Liu break; 1260bbe418f2SJia Liu 1261bbe418f2SJia Liu case 0x01: /* lf.sub.s */ 1262bbe418f2SJia Liu LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); 12636597c28dSRichard Henderson check_r0_write(rd); 1264bbe418f2SJia Liu gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12654e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1266bbe418f2SJia Liu break; 1267bbe418f2SJia Liu 1268bbe418f2SJia Liu case 0x02: /* lf.mul.s */ 1269bbe418f2SJia Liu LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); 12706597c28dSRichard Henderson check_r0_write(rd); 1271bbe418f2SJia Liu gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12724e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1273bbe418f2SJia Liu break; 1274bbe418f2SJia Liu 1275bbe418f2SJia Liu case 0x03: /* lf.div.s */ 1276bbe418f2SJia Liu LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); 12776597c28dSRichard Henderson check_r0_write(rd); 1278bbe418f2SJia Liu gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12794e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1280bbe418f2SJia Liu break; 1281bbe418f2SJia Liu 1282bbe418f2SJia Liu case 0x04: /* lf.itof.s */ 1283bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 12846597c28dSRichard Henderson check_r0_write(rd); 1285bbe418f2SJia Liu gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); 12864e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1287bbe418f2SJia Liu break; 1288bbe418f2SJia Liu 1289bbe418f2SJia Liu case 0x05: /* lf.ftoi.s */ 1290bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 12916597c28dSRichard Henderson check_r0_write(rd); 1292bbe418f2SJia Liu gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); 12934e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1294bbe418f2SJia Liu break; 1295bbe418f2SJia Liu 1296bbe418f2SJia Liu case 0x06: /* lf.rem.s */ 1297bbe418f2SJia Liu LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); 12986597c28dSRichard Henderson check_r0_write(rd); 1299bbe418f2SJia Liu gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13004e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1301bbe418f2SJia Liu break; 1302bbe418f2SJia Liu 1303bbe418f2SJia Liu case 0x07: /* lf.madd.s */ 1304bbe418f2SJia Liu LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); 13056597c28dSRichard Henderson check_r0_write(rd); 1306762e22edSRichard Henderson gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], 1307762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 13084e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1309bbe418f2SJia Liu break; 1310bbe418f2SJia Liu 1311bbe418f2SJia Liu case 0x08: /* lf.sfeq.s */ 1312bbe418f2SJia Liu LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); 131384775c43SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13144e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1315bbe418f2SJia Liu break; 1316bbe418f2SJia Liu 1317bbe418f2SJia Liu case 0x09: /* lf.sfne.s */ 1318bbe418f2SJia Liu LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); 13194e2d3007SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13204e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 13214e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1322bbe418f2SJia Liu break; 1323bbe418f2SJia Liu 1324bbe418f2SJia Liu case 0x0a: /* lf.sfgt.s */ 1325bbe418f2SJia Liu LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); 13264e2d3007SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13274e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1328bbe418f2SJia Liu break; 1329bbe418f2SJia Liu 1330bbe418f2SJia Liu case 0x0b: /* lf.sfge.s */ 1331bbe418f2SJia Liu LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); 13324e2d3007SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13334e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1334bbe418f2SJia Liu break; 1335bbe418f2SJia Liu 1336bbe418f2SJia Liu case 0x0c: /* lf.sflt.s */ 1337bbe418f2SJia Liu LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); 133884775c43SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13394e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1340bbe418f2SJia Liu break; 1341bbe418f2SJia Liu 1342bbe418f2SJia Liu case 0x0d: /* lf.sfle.s */ 1343bbe418f2SJia Liu LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); 134484775c43SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13454e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1346bbe418f2SJia Liu break; 1347bbe418f2SJia Liu 13484e2d3007SRichard Henderson #ifdef TARGET_OPENRISC64 13494e2d3007SRichard Henderson case 0x10: /* lf.add.d */ 1350bbe418f2SJia Liu LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); 1351bbe418f2SJia Liu check_of64s(dc); 13526597c28dSRichard Henderson check_r0_write(rd); 1353bbe418f2SJia Liu gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13544e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1355bbe418f2SJia Liu break; 1356bbe418f2SJia Liu 13574e2d3007SRichard Henderson case 0x11: /* lf.sub.d */ 1358bbe418f2SJia Liu LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb); 1359bbe418f2SJia Liu check_of64s(dc); 13606597c28dSRichard Henderson check_r0_write(rd); 1361bbe418f2SJia Liu gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13624e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1363bbe418f2SJia Liu break; 1364bbe418f2SJia Liu 13654e2d3007SRichard Henderson case 0x12: /* lf.mul.d */ 1366bbe418f2SJia Liu LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb); 1367bbe418f2SJia Liu check_of64s(dc); 13686597c28dSRichard Henderson check_r0_write(rd); 1369bbe418f2SJia Liu gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13704e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1371bbe418f2SJia Liu break; 1372bbe418f2SJia Liu 13734e2d3007SRichard Henderson case 0x13: /* lf.div.d */ 1374bbe418f2SJia Liu LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); 1375bbe418f2SJia Liu check_of64s(dc); 13766597c28dSRichard Henderson check_r0_write(rd); 1377bbe418f2SJia Liu gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13784e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1379bbe418f2SJia Liu break; 1380bbe418f2SJia Liu 13814e2d3007SRichard Henderson case 0x14: /* lf.itof.d */ 1382bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 1383bbe418f2SJia Liu check_of64s(dc); 13846597c28dSRichard Henderson check_r0_write(rd); 1385bbe418f2SJia Liu gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); 13864e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1387bbe418f2SJia Liu break; 1388bbe418f2SJia Liu 13894e2d3007SRichard Henderson case 0x15: /* lf.ftoi.d */ 1390bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 1391bbe418f2SJia Liu check_of64s(dc); 13926597c28dSRichard Henderson check_r0_write(rd); 1393bbe418f2SJia Liu gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); 13944e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1395bbe418f2SJia Liu break; 1396bbe418f2SJia Liu 13974e2d3007SRichard Henderson case 0x16: /* lf.rem.d */ 1398bbe418f2SJia Liu LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); 1399bbe418f2SJia Liu check_of64s(dc); 14006597c28dSRichard Henderson check_r0_write(rd); 1401bbe418f2SJia Liu gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 14024e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1403bbe418f2SJia Liu break; 1404bbe418f2SJia Liu 14054e2d3007SRichard Henderson case 0x17: /* lf.madd.d */ 1406bbe418f2SJia Liu LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); 1407bbe418f2SJia Liu check_of64s(dc); 14086597c28dSRichard Henderson check_r0_write(rd); 1409762e22edSRichard Henderson gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], 1410762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 14114e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1412bbe418f2SJia Liu break; 1413bbe418f2SJia Liu 14144e2d3007SRichard Henderson case 0x18: /* lf.sfeq.d */ 1415bbe418f2SJia Liu LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); 1416bbe418f2SJia Liu check_of64s(dc); 141784775c43SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14184e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1419bbe418f2SJia Liu break; 1420bbe418f2SJia Liu 14214e2d3007SRichard Henderson case 0x1a: /* lf.sfgt.d */ 1422bbe418f2SJia Liu LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); 1423bbe418f2SJia Liu check_of64s(dc); 14244e2d3007SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14254e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1426bbe418f2SJia Liu break; 1427bbe418f2SJia Liu 14284e2d3007SRichard Henderson case 0x1b: /* lf.sfge.d */ 1429bbe418f2SJia Liu LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); 1430bbe418f2SJia Liu check_of64s(dc); 14314e2d3007SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14324e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1433bbe418f2SJia Liu break; 1434bbe418f2SJia Liu 14354e2d3007SRichard Henderson case 0x19: /* lf.sfne.d */ 1436bbe418f2SJia Liu LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); 1437bbe418f2SJia Liu check_of64s(dc); 14384e2d3007SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14394e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 14404e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1441bbe418f2SJia Liu break; 1442bbe418f2SJia Liu 14434e2d3007SRichard Henderson case 0x1c: /* lf.sflt.d */ 1444bbe418f2SJia Liu LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); 1445bbe418f2SJia Liu check_of64s(dc); 144684775c43SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14474e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1448bbe418f2SJia Liu break; 1449bbe418f2SJia Liu 14504e2d3007SRichard Henderson case 0x1d: /* lf.sfle.d */ 1451bbe418f2SJia Liu LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); 1452bbe418f2SJia Liu check_of64s(dc); 145384775c43SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14544e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1455bbe418f2SJia Liu break; 14564e2d3007SRichard Henderson #endif 1457bbe418f2SJia Liu 1458bbe418f2SJia Liu default: 1459bbe418f2SJia Liu gen_illegal_exception(dc); 1460bbe418f2SJia Liu break; 1461bbe418f2SJia Liu } 1462bbe418f2SJia Liu } 1463bbe418f2SJia Liu 1464bbe418f2SJia Liu static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) 1465bbe418f2SJia Liu { 1466bbe418f2SJia Liu uint32_t op0; 14677de9729fSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1468bbe418f2SJia Liu 14697de9729fSRichard Henderson /* Transition to the auto-generated decoder. */ 14707de9729fSRichard Henderson if (decode(dc, insn)) { 14717de9729fSRichard Henderson return; 14727de9729fSRichard Henderson } 14737de9729fSRichard Henderson 14747de9729fSRichard Henderson op0 = extract32(insn, 26, 6); 1475bbe418f2SJia Liu switch (op0) { 1476bbe418f2SJia Liu case 0x32: 1477bbe418f2SJia Liu dec_float(dc, insn); 1478bbe418f2SJia Liu break; 1479bbe418f2SJia Liu 1480bbe418f2SJia Liu default: 14818816f70bSRichard Henderson gen_illegal_exception(dc); 1482bbe418f2SJia Liu break; 1483bbe418f2SJia Liu } 1484bbe418f2SJia Liu } 1485bbe418f2SJia Liu 1486a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1487e67db06eSJia Liu { 1488a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 14899c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1490a4fd3ec3SEmilio G. Cota int bound; 1491bbe418f2SJia Liu 1492a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 14931ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1494a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1495a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1496a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1497190ce7fbSRichard Henderson } 1498bbe418f2SJia Liu 1499a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1500a4fd3ec3SEmilio G. Cota { 1501a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1502bbe418f2SJia Liu 15036597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15046597c28dSRichard Henderson when it's true, which is the common case. */ 15056597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 15066597c28dSRichard Henderson cpu_R[0] = tcg_const_tl(0); 15076597c28dSRichard Henderson } else { 15086597c28dSRichard Henderson cpu_R[0] = cpu_R0; 15096597c28dSRichard Henderson } 1510a4fd3ec3SEmilio G. Cota } 15116597c28dSRichard Henderson 1512a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1513a4fd3ec3SEmilio G. Cota { 1514a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1515a4fd3ec3SEmilio G. Cota 15161ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1517a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1518a4fd3ec3SEmilio G. Cota } 1519bbe418f2SJia Liu 1520a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1521a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1522a4fd3ec3SEmilio G. Cota { 1523a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1524a4fd3ec3SEmilio G. Cota 15251ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1526b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 15271ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1528522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1529522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1530522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1531522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 15321ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1533a4fd3ec3SEmilio G. Cota return true; 1534b933066aSRichard Henderson } 1535b933066aSRichard Henderson 1536a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1537a4fd3ec3SEmilio G. Cota { 1538a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1539a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1540a4fd3ec3SEmilio G. Cota 1541bbe418f2SJia Liu disas_openrisc_insn(dc, cpu); 15421ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 154324c32852SRichard Henderson 1544bbe418f2SJia Liu /* delay slot */ 1545bbe418f2SJia Liu if (dc->delayed_branch) { 1546bbe418f2SJia Liu dc->delayed_branch--; 1547bbe418f2SJia Liu if (!dc->delayed_branch) { 1548bbe418f2SJia Liu tcg_gen_mov_tl(cpu_pc, jmp_pc); 154924c32852SRichard Henderson tcg_gen_discard_tl(jmp_pc); 15501ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 1551a4fd3ec3SEmilio G. Cota return; 1552bbe418f2SJia Liu } 1553bbe418f2SJia Liu } 1554a4fd3ec3SEmilio G. Cota } 1555bbe418f2SJia Liu 1556a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1557a4fd3ec3SEmilio G. Cota { 1558a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 155924c32852SRichard Henderson 1560a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1561a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1562a01deb36SRichard Henderson } 1563a01deb36SRichard Henderson 15641ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4); 15651ffa4bceSEmilio G. Cota if (dc->base.is_jmp == DISAS_NEXT) { 15661ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 15671ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1568bbe418f2SJia Liu } 15691ffa4bceSEmilio G. Cota if (unlikely(dc->base.singlestep_enabled)) { 1570bbe418f2SJia Liu gen_exception(dc, EXCP_DEBUG); 1571bbe418f2SJia Liu } else { 15721ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 1573a4fd3ec3SEmilio G. Cota case DISAS_TOO_MANY: 15741ffa4bceSEmilio G. Cota gen_goto_tb(dc, 0, dc->base.pc_next); 1575bbe418f2SJia Liu break; 15761ffa4bceSEmilio G. Cota case DISAS_NORETURN: 1577bbe418f2SJia Liu case DISAS_JUMP: 15781ffa4bceSEmilio G. Cota case DISAS_TB_JUMP: 1579bbe418f2SJia Liu break; 1580bbe418f2SJia Liu case DISAS_UPDATE: 1581bbe418f2SJia Liu /* indicate that the hash table must be used 1582bbe418f2SJia Liu to find the next TB */ 1583bbe418f2SJia Liu tcg_gen_exit_tb(0); 1584bbe418f2SJia Liu break; 1585a4fd3ec3SEmilio G. Cota default: 1586a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1587a4fd3ec3SEmilio G. Cota } 1588bbe418f2SJia Liu } 1589bbe418f2SJia Liu } 1590bbe418f2SJia Liu 1591a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1592a4fd3ec3SEmilio G. Cota { 1593a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 15940a7df5daSRichard Henderson 1595a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1596a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1597bbe418f2SJia Liu } 1598a4fd3ec3SEmilio G. Cota 1599a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1600a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1601a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1602a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1603a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1604a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1605a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1606a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1607a4fd3ec3SEmilio G. Cota }; 1608a4fd3ec3SEmilio G. Cota 1609a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) 1610a4fd3ec3SEmilio G. Cota { 1611a4fd3ec3SEmilio G. Cota DisasContext ctx; 1612a4fd3ec3SEmilio G. Cota 1613a4fd3ec3SEmilio G. Cota translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb); 1614e67db06eSJia Liu } 1615e67db06eSJia Liu 1616878096eeSAndreas Färber void openrisc_cpu_dump_state(CPUState *cs, FILE *f, 1617e67db06eSJia Liu fprintf_function cpu_fprintf, 1618e67db06eSJia Liu int flags) 1619e67db06eSJia Liu { 1620878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1621878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1622e67db06eSJia Liu int i; 1623878096eeSAndreas Färber 1624e67db06eSJia Liu cpu_fprintf(f, "PC=%08x\n", env->pc); 1625e67db06eSJia Liu for (i = 0; i < 32; ++i) { 1626d89e71e8SStafford Horne cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1627e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1628e67db06eSJia Liu } 1629e67db06eSJia Liu } 1630e67db06eSJia Liu 1631e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1632bad729e2SRichard Henderson target_ulong *data) 1633e67db06eSJia Liu { 1634bad729e2SRichard Henderson env->pc = data[0]; 1635a01deb36SRichard Henderson env->dflag = data[1] & 1; 1636a01deb36SRichard Henderson if (data[1] & 2) { 163724c32852SRichard Henderson env->ppc = env->pc - 4; 163824c32852SRichard Henderson } 1639e67db06eSJia Liu } 1640