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 458bbe418f2SJia Liu static void dec_calc(DisasContext *dc, uint32_t insn) 459bbe418f2SJia Liu { 460bbe418f2SJia Liu uint32_t op0, op1, op2; 461bbe418f2SJia Liu uint32_t ra, rb, rd; 462bbe418f2SJia Liu op0 = extract32(insn, 0, 4); 463bbe418f2SJia Liu op1 = extract32(insn, 8, 2); 464bbe418f2SJia Liu op2 = extract32(insn, 6, 2); 465bbe418f2SJia Liu ra = extract32(insn, 16, 5); 466bbe418f2SJia Liu rb = extract32(insn, 11, 5); 467bbe418f2SJia Liu rd = extract32(insn, 21, 5); 468bbe418f2SJia Liu 469bbe418f2SJia Liu switch (op1) { 470cf2ae442SRichard Henderson case 0: 471cf2ae442SRichard Henderson switch (op0) { 472cf2ae442SRichard Henderson case 0x0: /* l.add */ 473bbe418f2SJia Liu LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); 4749ecaa27eSRichard Henderson gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 475cf2ae442SRichard Henderson return; 476bbe418f2SJia Liu 477cf2ae442SRichard Henderson case 0x1: /* l.addc */ 478bbe418f2SJia Liu LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); 4799ecaa27eSRichard Henderson gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 480cf2ae442SRichard Henderson return; 481bbe418f2SJia Liu 482cf2ae442SRichard Henderson case 0x2: /* l.sub */ 483bbe418f2SJia Liu LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); 4849ecaa27eSRichard Henderson gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 485cf2ae442SRichard Henderson return; 486bbe418f2SJia Liu 487cf2ae442SRichard Henderson case 0x3: /* l.and */ 488bbe418f2SJia Liu LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb); 489bbe418f2SJia Liu tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 490cf2ae442SRichard Henderson return; 491bbe418f2SJia Liu 492cf2ae442SRichard Henderson case 0x4: /* l.or */ 493bbe418f2SJia Liu LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb); 494bbe418f2SJia Liu tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 495cf2ae442SRichard Henderson return; 496bbe418f2SJia Liu 497cf2ae442SRichard Henderson case 0x5: /* l.xor */ 498bbe418f2SJia Liu LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb); 499bbe418f2SJia Liu tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 500cf2ae442SRichard Henderson return; 501cf2ae442SRichard Henderson 502cf2ae442SRichard Henderson case 0x8: 503cf2ae442SRichard Henderson switch (op2) { 504cf2ae442SRichard Henderson case 0: /* l.sll */ 505cf2ae442SRichard Henderson LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); 506cf2ae442SRichard Henderson tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 507cf2ae442SRichard Henderson return; 508cf2ae442SRichard Henderson case 1: /* l.srl */ 509cf2ae442SRichard Henderson LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); 510cf2ae442SRichard Henderson tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 511cf2ae442SRichard Henderson return; 512cf2ae442SRichard Henderson case 2: /* l.sra */ 513cf2ae442SRichard Henderson LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); 514cf2ae442SRichard Henderson tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 515cf2ae442SRichard Henderson return; 516cf2ae442SRichard Henderson case 3: /* l.ror */ 517cf2ae442SRichard Henderson LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); 518cf2ae442SRichard Henderson tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 519cf2ae442SRichard Henderson return; 520bbe418f2SJia Liu } 521bbe418f2SJia Liu break; 522bbe418f2SJia Liu 523cf2ae442SRichard Henderson case 0xc: 524cf2ae442SRichard Henderson switch (op2) { 525cf2ae442SRichard Henderson case 0: /* l.exths */ 526cf2ae442SRichard Henderson LOG_DIS("l.exths r%d, r%d\n", rd, ra); 527cf2ae442SRichard Henderson tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); 528cf2ae442SRichard Henderson return; 529cf2ae442SRichard Henderson case 1: /* l.extbs */ 530cf2ae442SRichard Henderson LOG_DIS("l.extbs r%d, r%d\n", rd, ra); 531cf2ae442SRichard Henderson tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); 532cf2ae442SRichard Henderson return; 533cf2ae442SRichard Henderson case 2: /* l.exthz */ 534cf2ae442SRichard Henderson LOG_DIS("l.exthz r%d, r%d\n", rd, ra); 535cf2ae442SRichard Henderson tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); 536cf2ae442SRichard Henderson return; 537cf2ae442SRichard Henderson case 3: /* l.extbz */ 538cf2ae442SRichard Henderson LOG_DIS("l.extbz r%d, r%d\n", rd, ra); 539cf2ae442SRichard Henderson tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); 540cf2ae442SRichard Henderson return; 541bbe418f2SJia Liu } 542bbe418f2SJia Liu break; 543bbe418f2SJia Liu 544cf2ae442SRichard Henderson case 0xd: 545cf2ae442SRichard Henderson switch (op2) { 546cf2ae442SRichard Henderson case 0: /* l.extws */ 547cf2ae442SRichard Henderson LOG_DIS("l.extws r%d, r%d\n", rd, ra); 548cf2ae442SRichard Henderson tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); 549cf2ae442SRichard Henderson return; 550cf2ae442SRichard Henderson case 1: /* l.extwz */ 551cf2ae442SRichard Henderson LOG_DIS("l.extwz r%d, r%d\n", rd, ra); 552cf2ae442SRichard Henderson tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); 553cf2ae442SRichard Henderson return; 554bbe418f2SJia Liu } 555bbe418f2SJia Liu break; 556bbe418f2SJia Liu 557cf2ae442SRichard Henderson case 0xe: /* l.cmov */ 558bbe418f2SJia Liu LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); 559bbe418f2SJia Liu { 560784696d1SRichard Henderson TCGv zero = tcg_const_tl(0); 561784696d1SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero, 562784696d1SRichard Henderson cpu_R[ra], cpu_R[rb]); 563784696d1SRichard Henderson tcg_temp_free(zero); 564bbe418f2SJia Liu } 565cf2ae442SRichard Henderson return; 566bbe418f2SJia Liu 567cf2ae442SRichard Henderson case 0xf: /* l.ff1 */ 568bbe418f2SJia Liu LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); 569555baef8SRichard Henderson tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1); 570555baef8SRichard Henderson tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1); 571cf2ae442SRichard Henderson return; 572cf2ae442SRichard Henderson } 573bbe418f2SJia Liu break; 574cf2ae442SRichard Henderson 575cf2ae442SRichard Henderson case 1: 576cf2ae442SRichard Henderson switch (op0) { 577cf2ae442SRichard Henderson case 0xf: /* l.fl1 */ 578bbe418f2SJia Liu LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); 579555baef8SRichard Henderson tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS); 580555baef8SRichard Henderson tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]); 581cf2ae442SRichard Henderson return; 582bbe418f2SJia Liu } 583bbe418f2SJia Liu break; 584bbe418f2SJia Liu 585cf2ae442SRichard Henderson case 2: 586bbe418f2SJia Liu break; 587bbe418f2SJia Liu 588cf2ae442SRichard Henderson case 3: 589cf2ae442SRichard Henderson switch (op0) { 590cf2ae442SRichard Henderson case 0x6: /* l.mul */ 591cf2ae442SRichard Henderson LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); 592cf2ae442SRichard Henderson gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 593cf2ae442SRichard Henderson return; 594cf2ae442SRichard Henderson 595cc5de49eSRichard Henderson case 0x7: /* l.muld */ 596cc5de49eSRichard Henderson LOG_DIS("l.muld r%d, r%d\n", ra, rb); 597cc5de49eSRichard Henderson gen_muld(dc, cpu_R[ra], cpu_R[rb]); 598cc5de49eSRichard Henderson break; 599cc5de49eSRichard Henderson 600cf2ae442SRichard Henderson case 0x9: /* l.div */ 601cf2ae442SRichard Henderson LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); 602cf2ae442SRichard Henderson gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 603cf2ae442SRichard Henderson return; 604cf2ae442SRichard Henderson 605cf2ae442SRichard Henderson case 0xa: /* l.divu */ 606cf2ae442SRichard Henderson LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); 607cf2ae442SRichard Henderson gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 608cf2ae442SRichard Henderson return; 609cf2ae442SRichard Henderson 610cf2ae442SRichard Henderson case 0xb: /* l.mulu */ 611cf2ae442SRichard Henderson LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); 612cf2ae442SRichard Henderson gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 613cf2ae442SRichard Henderson return; 614cc5de49eSRichard Henderson 615cc5de49eSRichard Henderson case 0xc: /* l.muldu */ 616cc5de49eSRichard Henderson LOG_DIS("l.muldu r%d, r%d\n", ra, rb); 617cc5de49eSRichard Henderson gen_muldu(dc, cpu_R[ra], cpu_R[rb]); 618cc5de49eSRichard Henderson return; 619bbe418f2SJia Liu } 620bbe418f2SJia Liu break; 621bbe418f2SJia Liu } 622bbe418f2SJia Liu gen_illegal_exception(dc); 623bbe418f2SJia Liu } 624bbe418f2SJia Liu 625136e13aeSRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) 626136e13aeSRichard Henderson { 627136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 628136e13aeSRichard Henderson 629136e13aeSRichard Henderson LOG_DIS("l.j %d\n", a->n); 630136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 631136e13aeSRichard Henderson dc->delayed_branch = 2; 632136e13aeSRichard Henderson return true; 633136e13aeSRichard Henderson } 634136e13aeSRichard Henderson 635136e13aeSRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn) 636136e13aeSRichard Henderson { 637136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 638136e13aeSRichard Henderson target_ulong ret_pc = dc->base.pc_next + 8; 639136e13aeSRichard Henderson 640136e13aeSRichard Henderson LOG_DIS("l.jal %d\n", a->n); 641136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], ret_pc); 642136e13aeSRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 643136e13aeSRichard Henderson if (tmp_pc != ret_pc) { 644136e13aeSRichard Henderson tcg_gen_movi_tl(jmp_pc, tmp_pc); 645136e13aeSRichard Henderson dc->delayed_branch = 2; 646136e13aeSRichard Henderson } 647136e13aeSRichard Henderson return true; 648136e13aeSRichard Henderson } 649136e13aeSRichard Henderson 650136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) 651136e13aeSRichard Henderson { 652136e13aeSRichard Henderson target_ulong tmp_pc = dc->base.pc_next + a->n * 4; 653136e13aeSRichard Henderson TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 654136e13aeSRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 655136e13aeSRichard Henderson TCGv t_zero = tcg_const_tl(0); 656136e13aeSRichard Henderson 657136e13aeSRichard Henderson tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 658136e13aeSRichard Henderson 659136e13aeSRichard Henderson tcg_temp_free(t_next); 660136e13aeSRichard Henderson tcg_temp_free(t_true); 661136e13aeSRichard Henderson tcg_temp_free(t_zero); 662136e13aeSRichard Henderson dc->delayed_branch = 2; 663136e13aeSRichard Henderson } 664136e13aeSRichard Henderson 665136e13aeSRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 666136e13aeSRichard Henderson { 667136e13aeSRichard Henderson LOG_DIS("l.bf %d\n", a->n); 668136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_NE); 669136e13aeSRichard Henderson return true; 670136e13aeSRichard Henderson } 671136e13aeSRichard Henderson 672136e13aeSRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn) 673136e13aeSRichard Henderson { 674136e13aeSRichard Henderson LOG_DIS("l.bnf %d\n", a->n); 675136e13aeSRichard Henderson do_bf(dc, a, TCG_COND_EQ); 676136e13aeSRichard Henderson return true; 677136e13aeSRichard Henderson } 678136e13aeSRichard Henderson 679136e13aeSRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn) 680136e13aeSRichard Henderson { 681136e13aeSRichard Henderson LOG_DIS("l.jr r%d\n", a->b); 682136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 683136e13aeSRichard Henderson dc->delayed_branch = 2; 684136e13aeSRichard Henderson return true; 685136e13aeSRichard Henderson } 686136e13aeSRichard Henderson 687136e13aeSRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) 688136e13aeSRichard Henderson { 689136e13aeSRichard Henderson LOG_DIS("l.jalr r%d\n", a->b); 690136e13aeSRichard Henderson tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); 691136e13aeSRichard Henderson tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); 692136e13aeSRichard Henderson dc->delayed_branch = 2; 693136e13aeSRichard Henderson return true; 694136e13aeSRichard Henderson } 695136e13aeSRichard Henderson 696d80bff19SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn) 697d80bff19SRichard Henderson { 698d80bff19SRichard Henderson TCGv ea; 699d80bff19SRichard Henderson 700d80bff19SRichard Henderson LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i); 701d80bff19SRichard Henderson 702d80bff19SRichard Henderson check_r0_write(a->d); 703d80bff19SRichard Henderson ea = tcg_temp_new(); 704d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 705d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL); 706d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 707d80bff19SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]); 708d80bff19SRichard Henderson tcg_temp_free(ea); 709d80bff19SRichard Henderson return true; 710d80bff19SRichard Henderson } 711d80bff19SRichard Henderson 712d80bff19SRichard Henderson static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop) 713d80bff19SRichard Henderson { 714d80bff19SRichard Henderson TCGv ea; 715d80bff19SRichard Henderson 716d80bff19SRichard Henderson check_r0_write(a->d); 717d80bff19SRichard Henderson ea = tcg_temp_new(); 718d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 719d80bff19SRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop); 720d80bff19SRichard Henderson tcg_temp_free(ea); 721d80bff19SRichard Henderson } 722d80bff19SRichard Henderson 723d80bff19SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn) 724d80bff19SRichard Henderson { 725d80bff19SRichard Henderson LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i); 726d80bff19SRichard Henderson do_load(dc, a, MO_TEUL); 727d80bff19SRichard Henderson return true; 728d80bff19SRichard Henderson } 729d80bff19SRichard Henderson 730d80bff19SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn) 731d80bff19SRichard Henderson { 732d80bff19SRichard Henderson LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i); 733d80bff19SRichard Henderson do_load(dc, a, MO_TESL); 734d80bff19SRichard Henderson return true; 735d80bff19SRichard Henderson } 736d80bff19SRichard Henderson 737d80bff19SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn) 738d80bff19SRichard Henderson { 739d80bff19SRichard Henderson LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i); 740d80bff19SRichard Henderson do_load(dc, a, MO_UB); 741d80bff19SRichard Henderson return true; 742d80bff19SRichard Henderson } 743d80bff19SRichard Henderson 744d80bff19SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn) 745d80bff19SRichard Henderson { 746d80bff19SRichard Henderson LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i); 747d80bff19SRichard Henderson do_load(dc, a, MO_SB); 748d80bff19SRichard Henderson return true; 749d80bff19SRichard Henderson } 750d80bff19SRichard Henderson 751d80bff19SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn) 752d80bff19SRichard Henderson { 753d80bff19SRichard Henderson LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i); 754d80bff19SRichard Henderson do_load(dc, a, MO_TEUW); 755d80bff19SRichard Henderson return true; 756d80bff19SRichard Henderson } 757d80bff19SRichard Henderson 758d80bff19SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn) 759d80bff19SRichard Henderson { 760d80bff19SRichard Henderson LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i); 761d80bff19SRichard Henderson do_load(dc, a, MO_TESW); 762d80bff19SRichard Henderson return true; 763d80bff19SRichard Henderson } 764d80bff19SRichard Henderson 765d80bff19SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn) 766d80bff19SRichard Henderson { 767d80bff19SRichard Henderson TCGv ea, val; 768d80bff19SRichard Henderson TCGLabel *lab_fail, *lab_done; 769d80bff19SRichard Henderson 770d80bff19SRichard Henderson LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i); 771d80bff19SRichard Henderson 772d80bff19SRichard Henderson ea = tcg_temp_new(); 773d80bff19SRichard Henderson tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); 774d80bff19SRichard Henderson 775d80bff19SRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 776d80bff19SRichard Henderson to cpu_R[0]. Since l.swa is quite often immediately followed by a 777d80bff19SRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 778d80bff19SRichard Henderson This also takes care of RB input across the branch. */ 779d80bff19SRichard Henderson cpu_R[0] = cpu_R0; 780d80bff19SRichard Henderson 781d80bff19SRichard Henderson lab_fail = gen_new_label(); 782d80bff19SRichard Henderson lab_done = gen_new_label(); 783d80bff19SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 784d80bff19SRichard Henderson tcg_temp_free(ea); 785d80bff19SRichard Henderson 786d80bff19SRichard Henderson val = tcg_temp_new(); 787d80bff19SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 788d80bff19SRichard Henderson cpu_R[a->b], dc->mem_idx, MO_TEUL); 789d80bff19SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 790d80bff19SRichard Henderson tcg_temp_free(val); 791d80bff19SRichard Henderson 792d80bff19SRichard Henderson tcg_gen_br(lab_done); 793d80bff19SRichard Henderson 794d80bff19SRichard Henderson gen_set_label(lab_fail); 795d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 796d80bff19SRichard Henderson 797d80bff19SRichard Henderson gen_set_label(lab_done); 798d80bff19SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 799d80bff19SRichard Henderson return true; 800d80bff19SRichard Henderson } 801d80bff19SRichard Henderson 802d80bff19SRichard Henderson static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop) 803d80bff19SRichard Henderson { 804d80bff19SRichard Henderson TCGv t0 = tcg_temp_new(); 805d80bff19SRichard Henderson tcg_gen_addi_tl(t0, cpu_R[a->a], a->i); 806d80bff19SRichard Henderson tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop); 807d80bff19SRichard Henderson tcg_temp_free(t0); 808d80bff19SRichard Henderson } 809d80bff19SRichard Henderson 810d80bff19SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn) 811d80bff19SRichard Henderson { 812d80bff19SRichard Henderson LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i); 813d80bff19SRichard Henderson do_store(dc, a, MO_TEUL); 814d80bff19SRichard Henderson return true; 815d80bff19SRichard Henderson } 816d80bff19SRichard Henderson 817d80bff19SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn) 818d80bff19SRichard Henderson { 819d80bff19SRichard Henderson LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i); 820d80bff19SRichard Henderson do_store(dc, a, MO_UB); 821d80bff19SRichard Henderson return true; 822d80bff19SRichard Henderson } 823d80bff19SRichard Henderson 824d80bff19SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn) 825d80bff19SRichard Henderson { 826d80bff19SRichard Henderson LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i); 827d80bff19SRichard Henderson do_store(dc, a, MO_TEUW); 828d80bff19SRichard Henderson return true; 829d80bff19SRichard Henderson } 830d80bff19SRichard Henderson 831*8816f70bSRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn) 832bbe418f2SJia Liu { 833*8816f70bSRichard Henderson LOG_DIS("l.nop %d\n", a->k); 834*8816f70bSRichard Henderson return true; 835*8816f70bSRichard Henderson } 836*8816f70bSRichard Henderson 837*8816f70bSRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) 838*8816f70bSRichard Henderson { 8399ecaa27eSRichard Henderson TCGv t0; 8405631e69cSRichard Henderson 841*8816f70bSRichard Henderson LOG_DIS("l.addi r%d, r%d, %d\n", a->d, a->a, a->i); 842*8816f70bSRichard Henderson check_r0_write(a->d); 843*8816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 844*8816f70bSRichard Henderson gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0); 8456f7332baSRichard Henderson tcg_temp_free(t0); 846*8816f70bSRichard Henderson return true; 847*8816f70bSRichard Henderson } 848bbe418f2SJia Liu 849*8816f70bSRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) 850bbe418f2SJia Liu { 851*8816f70bSRichard Henderson TCGv t0; 852*8816f70bSRichard Henderson 853*8816f70bSRichard Henderson LOG_DIS("l.addic r%d, r%d, %d\n", a->d, a->a, a->i); 854*8816f70bSRichard Henderson check_r0_write(a->d); 855*8816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 856*8816f70bSRichard Henderson gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0); 857*8816f70bSRichard Henderson tcg_temp_free(t0); 858*8816f70bSRichard Henderson return true; 859*8816f70bSRichard Henderson } 860*8816f70bSRichard Henderson 861*8816f70bSRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) 862*8816f70bSRichard Henderson { 863*8816f70bSRichard Henderson TCGv t0; 864*8816f70bSRichard Henderson 865*8816f70bSRichard Henderson LOG_DIS("l.muli r%d, r%d, %d\n", a->d, a->a, a->i); 866*8816f70bSRichard Henderson check_r0_write(a->d); 867*8816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 868*8816f70bSRichard Henderson gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0); 869*8816f70bSRichard Henderson tcg_temp_free(t0); 870*8816f70bSRichard Henderson return true; 871*8816f70bSRichard Henderson } 872*8816f70bSRichard Henderson 873*8816f70bSRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) 874*8816f70bSRichard Henderson { 875*8816f70bSRichard Henderson TCGv t0; 876*8816f70bSRichard Henderson 877*8816f70bSRichard Henderson LOG_DIS("l.maci r%d, %d\n", a->a, a->i); 878*8816f70bSRichard Henderson t0 = tcg_const_tl(a->i); 879*8816f70bSRichard Henderson gen_mac(dc, cpu_R[a->a], t0); 880*8816f70bSRichard Henderson tcg_temp_free(t0); 881*8816f70bSRichard Henderson return true; 882*8816f70bSRichard Henderson } 883*8816f70bSRichard Henderson 884*8816f70bSRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn) 885*8816f70bSRichard Henderson { 886*8816f70bSRichard Henderson LOG_DIS("l.andi r%d, r%d, %d\n", a->d, a->a, a->k); 887*8816f70bSRichard Henderson check_r0_write(a->d); 888*8816f70bSRichard Henderson tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k); 889*8816f70bSRichard Henderson return true; 890*8816f70bSRichard Henderson } 891*8816f70bSRichard Henderson 892*8816f70bSRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn) 893*8816f70bSRichard Henderson { 894*8816f70bSRichard Henderson LOG_DIS("l.ori r%d, r%d, %d\n", a->d, a->a, a->k); 895*8816f70bSRichard Henderson check_r0_write(a->d); 896*8816f70bSRichard Henderson tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k); 897*8816f70bSRichard Henderson return true; 898*8816f70bSRichard Henderson } 899*8816f70bSRichard Henderson 900*8816f70bSRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn) 901*8816f70bSRichard Henderson { 902*8816f70bSRichard Henderson LOG_DIS("l.xori r%d, r%d, %d\n", a->d, a->a, a->i); 903*8816f70bSRichard Henderson check_r0_write(a->d); 904*8816f70bSRichard Henderson tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i); 905*8816f70bSRichard Henderson return true; 906*8816f70bSRichard Henderson } 907*8816f70bSRichard Henderson 908*8816f70bSRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) 909*8816f70bSRichard Henderson { 910*8816f70bSRichard Henderson LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k); 911*8816f70bSRichard Henderson check_r0_write(a->d); 912*8816f70bSRichard Henderson 913*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 914*8816f70bSRichard Henderson gen_illegal_exception(dc); 915bbe418f2SJia Liu #else 916bbe418f2SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 917bbe418f2SJia Liu gen_illegal_exception(dc); 918*8816f70bSRichard Henderson } else { 919*8816f70bSRichard Henderson TCGv_i32 ti = tcg_const_i32(a->k); 920*8816f70bSRichard Henderson gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti); 9214dd044c6SJia Liu tcg_temp_free_i32(ti); 9224dd044c6SJia Liu } 923*8816f70bSRichard Henderson #endif 924*8816f70bSRichard Henderson return true; 925*8816f70bSRichard Henderson } 926bbe418f2SJia Liu 927*8816f70bSRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) 9284dd044c6SJia Liu { 929*8816f70bSRichard Henderson LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k); 930*8816f70bSRichard Henderson 931*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 932*8816f70bSRichard Henderson gen_illegal_exception(dc); 9334dd044c6SJia Liu #else 9344dd044c6SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 9354dd044c6SJia Liu gen_illegal_exception(dc); 936*8816f70bSRichard Henderson } else { 937*8816f70bSRichard Henderson TCGv_i32 ti = tcg_const_i32(a->k); 938*8816f70bSRichard Henderson gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti); 939*8816f70bSRichard Henderson tcg_temp_free_i32(ti); 9404dd044c6SJia Liu } 9414dd044c6SJia Liu #endif 942*8816f70bSRichard Henderson return true; 943bbe418f2SJia Liu } 944bbe418f2SJia Liu 945bbe418f2SJia Liu static void dec_mac(DisasContext *dc, uint32_t insn) 946bbe418f2SJia Liu { 947bbe418f2SJia Liu uint32_t op0; 948bbe418f2SJia Liu uint32_t ra, rb; 949bbe418f2SJia Liu op0 = extract32(insn, 0, 4); 950bbe418f2SJia Liu ra = extract32(insn, 16, 5); 951bbe418f2SJia Liu rb = extract32(insn, 11, 5); 952bbe418f2SJia Liu 953bbe418f2SJia Liu switch (op0) { 954bbe418f2SJia Liu case 0x0001: /* l.mac */ 955bbe418f2SJia Liu LOG_DIS("l.mac r%d, r%d\n", ra, rb); 9566f7332baSRichard Henderson gen_mac(dc, cpu_R[ra], cpu_R[rb]); 957bbe418f2SJia Liu break; 958bbe418f2SJia Liu 959bbe418f2SJia Liu case 0x0002: /* l.msb */ 960bbe418f2SJia Liu LOG_DIS("l.msb r%d, r%d\n", ra, rb); 9616f7332baSRichard Henderson gen_msb(dc, cpu_R[ra], cpu_R[rb]); 962bbe418f2SJia Liu break; 963bbe418f2SJia Liu 964cc5de49eSRichard Henderson case 0x0003: /* l.macu */ 965cc5de49eSRichard Henderson LOG_DIS("l.macu r%d, r%d\n", ra, rb); 966cc5de49eSRichard Henderson gen_macu(dc, cpu_R[ra], cpu_R[rb]); 967cc5de49eSRichard Henderson break; 968cc5de49eSRichard Henderson 969cc5de49eSRichard Henderson case 0x0004: /* l.msbu */ 970cc5de49eSRichard Henderson LOG_DIS("l.msbu r%d, r%d\n", ra, rb); 971cc5de49eSRichard Henderson gen_msbu(dc, cpu_R[ra], cpu_R[rb]); 972cc5de49eSRichard Henderson break; 973cc5de49eSRichard Henderson 974bbe418f2SJia Liu default: 975bbe418f2SJia Liu gen_illegal_exception(dc); 976bbe418f2SJia Liu break; 977bbe418f2SJia Liu } 978bbe418f2SJia Liu } 979bbe418f2SJia Liu 980bbe418f2SJia Liu static void dec_logic(DisasContext *dc, uint32_t insn) 981bbe418f2SJia Liu { 982bbe418f2SJia Liu uint32_t op0; 9836da544a6SRichard Henderson uint32_t rd, ra, L6, S6; 984bbe418f2SJia Liu op0 = extract32(insn, 6, 2); 985bbe418f2SJia Liu rd = extract32(insn, 21, 5); 986bbe418f2SJia Liu ra = extract32(insn, 16, 5); 987bbe418f2SJia Liu L6 = extract32(insn, 0, 6); 9886da544a6SRichard Henderson S6 = L6 & (TARGET_LONG_BITS - 1); 989bbe418f2SJia Liu 9906597c28dSRichard Henderson check_r0_write(rd); 991bbe418f2SJia Liu switch (op0) { 992bbe418f2SJia Liu case 0x00: /* l.slli */ 993bbe418f2SJia Liu LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); 9946da544a6SRichard Henderson tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6); 995bbe418f2SJia Liu break; 996bbe418f2SJia Liu 997bbe418f2SJia Liu case 0x01: /* l.srli */ 998bbe418f2SJia Liu LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6); 9996da544a6SRichard Henderson tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6); 1000bbe418f2SJia Liu break; 1001bbe418f2SJia Liu 1002bbe418f2SJia Liu case 0x02: /* l.srai */ 1003bbe418f2SJia Liu LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6); 10046da544a6SRichard Henderson tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6); 10056da544a6SRichard Henderson break; 1006bbe418f2SJia Liu 1007bbe418f2SJia Liu case 0x03: /* l.rori */ 1008bbe418f2SJia Liu LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6); 10096da544a6SRichard Henderson tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6); 1010bbe418f2SJia Liu break; 1011bbe418f2SJia Liu 1012bbe418f2SJia Liu default: 1013bbe418f2SJia Liu gen_illegal_exception(dc); 1014bbe418f2SJia Liu break; 1015bbe418f2SJia Liu } 1016bbe418f2SJia Liu } 1017bbe418f2SJia Liu 1018bbe418f2SJia Liu static void dec_M(DisasContext *dc, uint32_t insn) 1019bbe418f2SJia Liu { 1020bbe418f2SJia Liu uint32_t op0; 1021bbe418f2SJia Liu uint32_t rd; 1022bbe418f2SJia Liu uint32_t K16; 1023bbe418f2SJia Liu op0 = extract32(insn, 16, 1); 1024bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1025bbe418f2SJia Liu K16 = extract32(insn, 0, 16); 1026bbe418f2SJia Liu 10276597c28dSRichard Henderson check_r0_write(rd); 1028bbe418f2SJia Liu switch (op0) { 1029bbe418f2SJia Liu case 0x0: /* l.movhi */ 1030bbe418f2SJia Liu LOG_DIS("l.movhi r%d, %d\n", rd, K16); 1031bbe418f2SJia Liu tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); 1032bbe418f2SJia Liu break; 1033bbe418f2SJia Liu 1034bbe418f2SJia Liu case 0x1: /* l.macrc */ 1035bbe418f2SJia Liu LOG_DIS("l.macrc r%d\n", rd); 10366f7332baSRichard Henderson tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac); 10376f7332baSRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 1038bbe418f2SJia Liu break; 1039bbe418f2SJia Liu 1040bbe418f2SJia Liu default: 1041bbe418f2SJia Liu gen_illegal_exception(dc); 1042bbe418f2SJia Liu break; 1043bbe418f2SJia Liu } 1044bbe418f2SJia Liu } 1045bbe418f2SJia Liu 1046bbe418f2SJia Liu static void dec_comp(DisasContext *dc, uint32_t insn) 1047bbe418f2SJia Liu { 1048bbe418f2SJia Liu uint32_t op0; 1049bbe418f2SJia Liu uint32_t ra, rb; 1050bbe418f2SJia Liu 1051bbe418f2SJia Liu op0 = extract32(insn, 21, 5); 1052bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1053bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1054bbe418f2SJia Liu 1055bbe418f2SJia Liu /* unsigned integers */ 1056bbe418f2SJia Liu tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]); 1057bbe418f2SJia Liu tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]); 1058bbe418f2SJia Liu 1059bbe418f2SJia Liu switch (op0) { 1060bbe418f2SJia Liu case 0x0: /* l.sfeq */ 1061bbe418f2SJia Liu LOG_DIS("l.sfeq r%d, r%d\n", ra, rb); 106284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1063bbe418f2SJia Liu break; 1064bbe418f2SJia Liu 1065bbe418f2SJia Liu case 0x1: /* l.sfne */ 1066bbe418f2SJia Liu LOG_DIS("l.sfne r%d, r%d\n", ra, rb); 106784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1068bbe418f2SJia Liu break; 1069bbe418f2SJia Liu 1070bbe418f2SJia Liu case 0x2: /* l.sfgtu */ 1071bbe418f2SJia Liu LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb); 107284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1073bbe418f2SJia Liu break; 1074bbe418f2SJia Liu 1075bbe418f2SJia Liu case 0x3: /* l.sfgeu */ 1076bbe418f2SJia Liu LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb); 107784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1078bbe418f2SJia Liu break; 1079bbe418f2SJia Liu 1080bbe418f2SJia Liu case 0x4: /* l.sfltu */ 1081bbe418f2SJia Liu LOG_DIS("l.sfltu r%d, r%d\n", ra, rb); 108284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1083bbe418f2SJia Liu break; 1084bbe418f2SJia Liu 1085bbe418f2SJia Liu case 0x5: /* l.sfleu */ 1086bbe418f2SJia Liu LOG_DIS("l.sfleu r%d, r%d\n", ra, rb); 108784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1088bbe418f2SJia Liu break; 1089bbe418f2SJia Liu 1090bbe418f2SJia Liu case 0xa: /* l.sfgts */ 1091bbe418f2SJia Liu LOG_DIS("l.sfgts r%d, r%d\n", ra, rb); 109284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1093bbe418f2SJia Liu break; 1094bbe418f2SJia Liu 1095bbe418f2SJia Liu case 0xb: /* l.sfges */ 1096bbe418f2SJia Liu LOG_DIS("l.sfges r%d, r%d\n", ra, rb); 109784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1098bbe418f2SJia Liu break; 1099bbe418f2SJia Liu 1100bbe418f2SJia Liu case 0xc: /* l.sflts */ 1101bbe418f2SJia Liu LOG_DIS("l.sflts r%d, r%d\n", ra, rb); 110284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1103bbe418f2SJia Liu break; 1104bbe418f2SJia Liu 1105bbe418f2SJia Liu case 0xd: /* l.sfles */ 1106bbe418f2SJia Liu LOG_DIS("l.sfles r%d, r%d\n", ra, rb); 110784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1108bbe418f2SJia Liu break; 1109bbe418f2SJia Liu 1110bbe418f2SJia Liu default: 1111bbe418f2SJia Liu gen_illegal_exception(dc); 1112bbe418f2SJia Liu break; 1113bbe418f2SJia Liu } 1114bbe418f2SJia Liu } 1115bbe418f2SJia Liu 1116bbe418f2SJia Liu static void dec_compi(DisasContext *dc, uint32_t insn) 1117bbe418f2SJia Liu { 11186da544a6SRichard Henderson uint32_t op0, ra; 11196da544a6SRichard Henderson int32_t I16; 1120bbe418f2SJia Liu 1121bbe418f2SJia Liu op0 = extract32(insn, 21, 5); 1122bbe418f2SJia Liu ra = extract32(insn, 16, 5); 11236da544a6SRichard Henderson I16 = sextract32(insn, 0, 16); 1124bbe418f2SJia Liu 1125bbe418f2SJia Liu switch (op0) { 1126bbe418f2SJia Liu case 0x0: /* l.sfeqi */ 1127bbe418f2SJia Liu LOG_DIS("l.sfeqi r%d, %d\n", ra, I16); 112884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16); 1129bbe418f2SJia Liu break; 1130bbe418f2SJia Liu 1131bbe418f2SJia Liu case 0x1: /* l.sfnei */ 1132bbe418f2SJia Liu LOG_DIS("l.sfnei r%d, %d\n", ra, I16); 113384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16); 1134bbe418f2SJia Liu break; 1135bbe418f2SJia Liu 1136bbe418f2SJia Liu case 0x2: /* l.sfgtui */ 1137bbe418f2SJia Liu LOG_DIS("l.sfgtui r%d, %d\n", ra, I16); 113884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16); 1139bbe418f2SJia Liu break; 1140bbe418f2SJia Liu 1141bbe418f2SJia Liu case 0x3: /* l.sfgeui */ 1142bbe418f2SJia Liu LOG_DIS("l.sfgeui r%d, %d\n", ra, I16); 114384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16); 1144bbe418f2SJia Liu break; 1145bbe418f2SJia Liu 1146bbe418f2SJia Liu case 0x4: /* l.sfltui */ 1147bbe418f2SJia Liu LOG_DIS("l.sfltui r%d, %d\n", ra, I16); 114884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16); 1149bbe418f2SJia Liu break; 1150bbe418f2SJia Liu 1151bbe418f2SJia Liu case 0x5: /* l.sfleui */ 1152bbe418f2SJia Liu LOG_DIS("l.sfleui r%d, %d\n", ra, I16); 115384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16); 1154bbe418f2SJia Liu break; 1155bbe418f2SJia Liu 1156bbe418f2SJia Liu case 0xa: /* l.sfgtsi */ 1157bbe418f2SJia Liu LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16); 115884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16); 1159bbe418f2SJia Liu break; 1160bbe418f2SJia Liu 1161bbe418f2SJia Liu case 0xb: /* l.sfgesi */ 1162bbe418f2SJia Liu LOG_DIS("l.sfgesi r%d, %d\n", ra, I16); 116384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16); 1164bbe418f2SJia Liu break; 1165bbe418f2SJia Liu 1166bbe418f2SJia Liu case 0xc: /* l.sfltsi */ 1167bbe418f2SJia Liu LOG_DIS("l.sfltsi r%d, %d\n", ra, I16); 116884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16); 1169bbe418f2SJia Liu break; 1170bbe418f2SJia Liu 1171bbe418f2SJia Liu case 0xd: /* l.sflesi */ 1172bbe418f2SJia Liu LOG_DIS("l.sflesi r%d, %d\n", ra, I16); 117384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16); 1174bbe418f2SJia Liu break; 1175bbe418f2SJia Liu 1176bbe418f2SJia Liu default: 1177bbe418f2SJia Liu gen_illegal_exception(dc); 1178bbe418f2SJia Liu break; 1179bbe418f2SJia Liu } 1180bbe418f2SJia Liu } 1181bbe418f2SJia Liu 11827de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) 1183bbe418f2SJia Liu { 11847de9729fSRichard Henderson LOG_DIS("l.sys %d\n", a->k); 11851ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1186bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 11871ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11887de9729fSRichard Henderson return true; 11897de9729fSRichard Henderson } 1190bbe418f2SJia Liu 11917de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) 11927de9729fSRichard Henderson { 11937de9729fSRichard Henderson LOG_DIS("l.trap %d\n", a->k); 11941ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1195bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 11961ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 11977de9729fSRichard Henderson return true; 11987de9729fSRichard Henderson } 1199bbe418f2SJia Liu 12007de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) 12017de9729fSRichard Henderson { 1202bbe418f2SJia Liu LOG_DIS("l.msync\n"); 120324fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 12047de9729fSRichard Henderson return true; 1205bbe418f2SJia Liu } 12067de9729fSRichard Henderson 12077de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) 12087de9729fSRichard Henderson { 12097de9729fSRichard Henderson LOG_DIS("l.psync\n"); 12107de9729fSRichard Henderson return true; 12117de9729fSRichard Henderson } 12127de9729fSRichard Henderson 12137de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) 12147de9729fSRichard Henderson { 12157de9729fSRichard Henderson LOG_DIS("l.csync\n"); 12167de9729fSRichard Henderson return true; 1217bbe418f2SJia Liu } 1218bbe418f2SJia Liu 1219*8816f70bSRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn) 1220*8816f70bSRichard Henderson { 1221*8816f70bSRichard Henderson LOG_DIS("l.rfe\n"); 1222*8816f70bSRichard Henderson 1223*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY 1224*8816f70bSRichard Henderson gen_illegal_exception(dc); 1225*8816f70bSRichard Henderson #else 1226*8816f70bSRichard Henderson if (dc->mem_idx == MMU_USER_IDX) { 1227*8816f70bSRichard Henderson gen_illegal_exception(dc); 1228*8816f70bSRichard Henderson } else { 1229*8816f70bSRichard Henderson gen_helper_rfe(cpu_env); 1230*8816f70bSRichard Henderson dc->base.is_jmp = DISAS_UPDATE; 1231*8816f70bSRichard Henderson } 1232*8816f70bSRichard Henderson #endif 1233*8816f70bSRichard Henderson return true; 1234*8816f70bSRichard Henderson } 1235*8816f70bSRichard Henderson 1236bbe418f2SJia Liu static void dec_float(DisasContext *dc, uint32_t insn) 1237bbe418f2SJia Liu { 1238bbe418f2SJia Liu uint32_t op0; 1239bbe418f2SJia Liu uint32_t ra, rb, rd; 1240bbe418f2SJia Liu op0 = extract32(insn, 0, 8); 1241bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1242bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1243bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1244bbe418f2SJia Liu 1245bbe418f2SJia Liu switch (op0) { 1246bbe418f2SJia Liu case 0x00: /* lf.add.s */ 1247bbe418f2SJia Liu LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); 12486597c28dSRichard Henderson check_r0_write(rd); 1249bbe418f2SJia Liu gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12504e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1251bbe418f2SJia Liu break; 1252bbe418f2SJia Liu 1253bbe418f2SJia Liu case 0x01: /* lf.sub.s */ 1254bbe418f2SJia Liu LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); 12556597c28dSRichard Henderson check_r0_write(rd); 1256bbe418f2SJia Liu gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12574e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1258bbe418f2SJia Liu break; 1259bbe418f2SJia Liu 1260bbe418f2SJia Liu case 0x02: /* lf.mul.s */ 1261bbe418f2SJia Liu LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); 12626597c28dSRichard Henderson check_r0_write(rd); 1263bbe418f2SJia Liu gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12644e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1265bbe418f2SJia Liu break; 1266bbe418f2SJia Liu 1267bbe418f2SJia Liu case 0x03: /* lf.div.s */ 1268bbe418f2SJia Liu LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); 12696597c28dSRichard Henderson check_r0_write(rd); 1270bbe418f2SJia Liu gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12714e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1272bbe418f2SJia Liu break; 1273bbe418f2SJia Liu 1274bbe418f2SJia Liu case 0x04: /* lf.itof.s */ 1275bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 12766597c28dSRichard Henderson check_r0_write(rd); 1277bbe418f2SJia Liu gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); 12784e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1279bbe418f2SJia Liu break; 1280bbe418f2SJia Liu 1281bbe418f2SJia Liu case 0x05: /* lf.ftoi.s */ 1282bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 12836597c28dSRichard Henderson check_r0_write(rd); 1284bbe418f2SJia Liu gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); 12854e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1286bbe418f2SJia Liu break; 1287bbe418f2SJia Liu 1288bbe418f2SJia Liu case 0x06: /* lf.rem.s */ 1289bbe418f2SJia Liu LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); 12906597c28dSRichard Henderson check_r0_write(rd); 1291bbe418f2SJia Liu gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12924e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1293bbe418f2SJia Liu break; 1294bbe418f2SJia Liu 1295bbe418f2SJia Liu case 0x07: /* lf.madd.s */ 1296bbe418f2SJia Liu LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); 12976597c28dSRichard Henderson check_r0_write(rd); 1298762e22edSRichard Henderson gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], 1299762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 13004e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1301bbe418f2SJia Liu break; 1302bbe418f2SJia Liu 1303bbe418f2SJia Liu case 0x08: /* lf.sfeq.s */ 1304bbe418f2SJia Liu LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); 130584775c43SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13064e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1307bbe418f2SJia Liu break; 1308bbe418f2SJia Liu 1309bbe418f2SJia Liu case 0x09: /* lf.sfne.s */ 1310bbe418f2SJia Liu LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); 13114e2d3007SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13124e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 13134e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1314bbe418f2SJia Liu break; 1315bbe418f2SJia Liu 1316bbe418f2SJia Liu case 0x0a: /* lf.sfgt.s */ 1317bbe418f2SJia Liu LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); 13184e2d3007SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13194e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1320bbe418f2SJia Liu break; 1321bbe418f2SJia Liu 1322bbe418f2SJia Liu case 0x0b: /* lf.sfge.s */ 1323bbe418f2SJia Liu LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); 13244e2d3007SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13254e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1326bbe418f2SJia Liu break; 1327bbe418f2SJia Liu 1328bbe418f2SJia Liu case 0x0c: /* lf.sflt.s */ 1329bbe418f2SJia Liu LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); 133084775c43SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13314e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1332bbe418f2SJia Liu break; 1333bbe418f2SJia Liu 1334bbe418f2SJia Liu case 0x0d: /* lf.sfle.s */ 1335bbe418f2SJia Liu LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); 133684775c43SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13374e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1338bbe418f2SJia Liu break; 1339bbe418f2SJia Liu 13404e2d3007SRichard Henderson #ifdef TARGET_OPENRISC64 13414e2d3007SRichard Henderson case 0x10: /* lf.add.d */ 1342bbe418f2SJia Liu LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); 1343bbe418f2SJia Liu check_of64s(dc); 13446597c28dSRichard Henderson check_r0_write(rd); 1345bbe418f2SJia Liu gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13464e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1347bbe418f2SJia Liu break; 1348bbe418f2SJia Liu 13494e2d3007SRichard Henderson case 0x11: /* lf.sub.d */ 1350bbe418f2SJia Liu LOG_DIS("lf.sub.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_sub_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 0x12: /* lf.mul.d */ 1358bbe418f2SJia Liu LOG_DIS("lf.mul.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_mul_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 0x13: /* lf.div.d */ 1366bbe418f2SJia Liu LOG_DIS("lf.div.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_div_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 0x14: /* lf.itof.d */ 1374bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 1375bbe418f2SJia Liu check_of64s(dc); 13766597c28dSRichard Henderson check_r0_write(rd); 1377bbe418f2SJia Liu gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); 13784e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1379bbe418f2SJia Liu break; 1380bbe418f2SJia Liu 13814e2d3007SRichard Henderson case 0x15: /* lf.ftoi.d */ 1382bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 1383bbe418f2SJia Liu check_of64s(dc); 13846597c28dSRichard Henderson check_r0_write(rd); 1385bbe418f2SJia Liu gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); 13864e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1387bbe418f2SJia Liu break; 1388bbe418f2SJia Liu 13894e2d3007SRichard Henderson case 0x16: /* lf.rem.d */ 1390bbe418f2SJia Liu LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); 1391bbe418f2SJia Liu check_of64s(dc); 13926597c28dSRichard Henderson check_r0_write(rd); 1393bbe418f2SJia Liu gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13944e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1395bbe418f2SJia Liu break; 1396bbe418f2SJia Liu 13974e2d3007SRichard Henderson case 0x17: /* lf.madd.d */ 1398bbe418f2SJia Liu LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); 1399bbe418f2SJia Liu check_of64s(dc); 14006597c28dSRichard Henderson check_r0_write(rd); 1401762e22edSRichard Henderson gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], 1402762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 14034e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1404bbe418f2SJia Liu break; 1405bbe418f2SJia Liu 14064e2d3007SRichard Henderson case 0x18: /* lf.sfeq.d */ 1407bbe418f2SJia Liu LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); 1408bbe418f2SJia Liu check_of64s(dc); 140984775c43SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14104e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1411bbe418f2SJia Liu break; 1412bbe418f2SJia Liu 14134e2d3007SRichard Henderson case 0x1a: /* lf.sfgt.d */ 1414bbe418f2SJia Liu LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); 1415bbe418f2SJia Liu check_of64s(dc); 14164e2d3007SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14174e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1418bbe418f2SJia Liu break; 1419bbe418f2SJia Liu 14204e2d3007SRichard Henderson case 0x1b: /* lf.sfge.d */ 1421bbe418f2SJia Liu LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); 1422bbe418f2SJia Liu check_of64s(dc); 14234e2d3007SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14244e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1425bbe418f2SJia Liu break; 1426bbe418f2SJia Liu 14274e2d3007SRichard Henderson case 0x19: /* lf.sfne.d */ 1428bbe418f2SJia Liu LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); 1429bbe418f2SJia Liu check_of64s(dc); 14304e2d3007SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14314e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 14324e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1433bbe418f2SJia Liu break; 1434bbe418f2SJia Liu 14354e2d3007SRichard Henderson case 0x1c: /* lf.sflt.d */ 1436bbe418f2SJia Liu LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); 1437bbe418f2SJia Liu check_of64s(dc); 143884775c43SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14394e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1440bbe418f2SJia Liu break; 1441bbe418f2SJia Liu 14424e2d3007SRichard Henderson case 0x1d: /* lf.sfle.d */ 1443bbe418f2SJia Liu LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); 1444bbe418f2SJia Liu check_of64s(dc); 144584775c43SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14464e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1447bbe418f2SJia Liu break; 14484e2d3007SRichard Henderson #endif 1449bbe418f2SJia Liu 1450bbe418f2SJia Liu default: 1451bbe418f2SJia Liu gen_illegal_exception(dc); 1452bbe418f2SJia Liu break; 1453bbe418f2SJia Liu } 1454bbe418f2SJia Liu } 1455bbe418f2SJia Liu 1456bbe418f2SJia Liu static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) 1457bbe418f2SJia Liu { 1458bbe418f2SJia Liu uint32_t op0; 14597de9729fSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1460bbe418f2SJia Liu 14617de9729fSRichard Henderson /* Transition to the auto-generated decoder. */ 14627de9729fSRichard Henderson if (decode(dc, insn)) { 14637de9729fSRichard Henderson return; 14647de9729fSRichard Henderson } 14657de9729fSRichard Henderson 14667de9729fSRichard Henderson op0 = extract32(insn, 26, 6); 1467bbe418f2SJia Liu switch (op0) { 1468bbe418f2SJia Liu case 0x06: 1469bbe418f2SJia Liu dec_M(dc, insn); 1470bbe418f2SJia Liu break; 1471bbe418f2SJia Liu 1472bbe418f2SJia Liu case 0x2e: 1473bbe418f2SJia Liu dec_logic(dc, insn); 1474bbe418f2SJia Liu break; 1475bbe418f2SJia Liu 1476bbe418f2SJia Liu case 0x2f: 1477bbe418f2SJia Liu dec_compi(dc, insn); 1478bbe418f2SJia Liu break; 1479bbe418f2SJia Liu 1480bbe418f2SJia Liu case 0x31: 1481bbe418f2SJia Liu dec_mac(dc, insn); 1482bbe418f2SJia Liu break; 1483bbe418f2SJia Liu 1484bbe418f2SJia Liu case 0x32: 1485bbe418f2SJia Liu dec_float(dc, insn); 1486bbe418f2SJia Liu break; 1487bbe418f2SJia Liu 1488bbe418f2SJia Liu case 0x38: 1489bbe418f2SJia Liu dec_calc(dc, insn); 1490bbe418f2SJia Liu break; 1491bbe418f2SJia Liu 1492bbe418f2SJia Liu case 0x39: 1493bbe418f2SJia Liu dec_comp(dc, insn); 1494bbe418f2SJia Liu break; 1495bbe418f2SJia Liu 1496bbe418f2SJia Liu default: 1497*8816f70bSRichard Henderson gen_illegal_exception(dc); 1498bbe418f2SJia Liu break; 1499bbe418f2SJia Liu } 1500bbe418f2SJia Liu } 1501bbe418f2SJia Liu 1502a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1503e67db06eSJia Liu { 1504a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 15059c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1506a4fd3ec3SEmilio G. Cota int bound; 1507bbe418f2SJia Liu 1508a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 15091ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1510a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1511a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1512a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1513190ce7fbSRichard Henderson } 1514bbe418f2SJia Liu 1515a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1516a4fd3ec3SEmilio G. Cota { 1517a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1518bbe418f2SJia Liu 15196597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15206597c28dSRichard Henderson when it's true, which is the common case. */ 15216597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 15226597c28dSRichard Henderson cpu_R[0] = tcg_const_tl(0); 15236597c28dSRichard Henderson } else { 15246597c28dSRichard Henderson cpu_R[0] = cpu_R0; 15256597c28dSRichard Henderson } 1526a4fd3ec3SEmilio G. Cota } 15276597c28dSRichard Henderson 1528a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1529a4fd3ec3SEmilio G. Cota { 1530a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1531a4fd3ec3SEmilio G. Cota 15321ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1533a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1534a4fd3ec3SEmilio G. Cota } 1535bbe418f2SJia Liu 1536a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1537a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1538a4fd3ec3SEmilio G. Cota { 1539a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1540a4fd3ec3SEmilio G. Cota 15411ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1542b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 15431ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1544522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1545522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1546522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1547522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 15481ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1549a4fd3ec3SEmilio G. Cota return true; 1550b933066aSRichard Henderson } 1551b933066aSRichard Henderson 1552a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1553a4fd3ec3SEmilio G. Cota { 1554a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1555a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1556a4fd3ec3SEmilio G. Cota 1557bbe418f2SJia Liu disas_openrisc_insn(dc, cpu); 15581ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 155924c32852SRichard Henderson 1560bbe418f2SJia Liu /* delay slot */ 1561bbe418f2SJia Liu if (dc->delayed_branch) { 1562bbe418f2SJia Liu dc->delayed_branch--; 1563bbe418f2SJia Liu if (!dc->delayed_branch) { 1564bbe418f2SJia Liu tcg_gen_mov_tl(cpu_pc, jmp_pc); 156524c32852SRichard Henderson tcg_gen_discard_tl(jmp_pc); 15661ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 1567a4fd3ec3SEmilio G. Cota return; 1568bbe418f2SJia Liu } 1569bbe418f2SJia Liu } 1570a4fd3ec3SEmilio G. Cota } 1571bbe418f2SJia Liu 1572a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1573a4fd3ec3SEmilio G. Cota { 1574a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 157524c32852SRichard Henderson 1576a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1577a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1578a01deb36SRichard Henderson } 1579a01deb36SRichard Henderson 15801ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4); 15811ffa4bceSEmilio G. Cota if (dc->base.is_jmp == DISAS_NEXT) { 15821ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 15831ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1584bbe418f2SJia Liu } 15851ffa4bceSEmilio G. Cota if (unlikely(dc->base.singlestep_enabled)) { 1586bbe418f2SJia Liu gen_exception(dc, EXCP_DEBUG); 1587bbe418f2SJia Liu } else { 15881ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 1589a4fd3ec3SEmilio G. Cota case DISAS_TOO_MANY: 15901ffa4bceSEmilio G. Cota gen_goto_tb(dc, 0, dc->base.pc_next); 1591bbe418f2SJia Liu break; 15921ffa4bceSEmilio G. Cota case DISAS_NORETURN: 1593bbe418f2SJia Liu case DISAS_JUMP: 15941ffa4bceSEmilio G. Cota case DISAS_TB_JUMP: 1595bbe418f2SJia Liu break; 1596bbe418f2SJia Liu case DISAS_UPDATE: 1597bbe418f2SJia Liu /* indicate that the hash table must be used 1598bbe418f2SJia Liu to find the next TB */ 1599bbe418f2SJia Liu tcg_gen_exit_tb(0); 1600bbe418f2SJia Liu break; 1601a4fd3ec3SEmilio G. Cota default: 1602a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1603a4fd3ec3SEmilio G. Cota } 1604bbe418f2SJia Liu } 1605bbe418f2SJia Liu } 1606bbe418f2SJia Liu 1607a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1608a4fd3ec3SEmilio G. Cota { 1609a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 16100a7df5daSRichard Henderson 1611a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1612a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1613bbe418f2SJia Liu } 1614a4fd3ec3SEmilio G. Cota 1615a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1616a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1617a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1618a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1619a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1620a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1621a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1622a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1623a4fd3ec3SEmilio G. Cota }; 1624a4fd3ec3SEmilio G. Cota 1625a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) 1626a4fd3ec3SEmilio G. Cota { 1627a4fd3ec3SEmilio G. Cota DisasContext ctx; 1628a4fd3ec3SEmilio G. Cota 1629a4fd3ec3SEmilio G. Cota translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb); 1630e67db06eSJia Liu } 1631e67db06eSJia Liu 1632878096eeSAndreas Färber void openrisc_cpu_dump_state(CPUState *cs, FILE *f, 1633e67db06eSJia Liu fprintf_function cpu_fprintf, 1634e67db06eSJia Liu int flags) 1635e67db06eSJia Liu { 1636878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1637878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1638e67db06eSJia Liu int i; 1639878096eeSAndreas Färber 1640e67db06eSJia Liu cpu_fprintf(f, "PC=%08x\n", env->pc); 1641e67db06eSJia Liu for (i = 0; i < 32; ++i) { 1642d89e71e8SStafford Horne cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1643e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1644e67db06eSJia Liu } 1645e67db06eSJia Liu } 1646e67db06eSJia Liu 1647e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1648bad729e2SRichard Henderson target_ulong *data) 1649e67db06eSJia Liu { 1650bad729e2SRichard Henderson env->pc = data[0]; 1651a01deb36SRichard Henderson env->dflag = data[1] & 1; 1652a01deb36SRichard Henderson if (data[1] & 2) { 165324c32852SRichard Henderson env->ppc = env->pc - 4; 165424c32852SRichard Henderson } 1655e67db06eSJia Liu } 1656