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" 34*7de9729fSRichard 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 55*7de9729fSRichard Henderson /* Include the auto-generated decoder. */ 56*7de9729fSRichard Henderson #include "decode.inc.c" 57*7de9729fSRichard 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 1966da544a6SRichard Henderson static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) 197bbe418f2SJia Liu { 1981ffa4bceSEmilio G. Cota target_ulong tmp_pc = dc->base.pc_next + n26 * 4; 199bbe418f2SJia Liu 200da1d7759SSebastian Macke switch (op0) { 201da1d7759SSebastian Macke case 0x00: /* l.j */ 202bbe418f2SJia Liu tcg_gen_movi_tl(jmp_pc, tmp_pc); 203da1d7759SSebastian Macke break; 204da1d7759SSebastian Macke case 0x01: /* l.jal */ 2051ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); 206a8000cb4SRichard Henderson /* Optimize jal being used to load the PC for PIC. */ 2071ffa4bceSEmilio G. Cota if (tmp_pc == dc->base.pc_next + 8) { 208a8000cb4SRichard Henderson return; 209a8000cb4SRichard Henderson } 210bbe418f2SJia Liu tcg_gen_movi_tl(jmp_pc, tmp_pc); 211da1d7759SSebastian Macke break; 212da1d7759SSebastian Macke case 0x03: /* l.bnf */ 213da1d7759SSebastian Macke case 0x04: /* l.bf */ 214da1d7759SSebastian Macke { 2151ffa4bceSEmilio G. Cota TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); 216784696d1SRichard Henderson TCGv t_true = tcg_const_tl(tmp_pc); 217784696d1SRichard Henderson TCGv t_zero = tcg_const_tl(0); 218784696d1SRichard Henderson 219784696d1SRichard Henderson tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, 220784696d1SRichard Henderson jmp_pc, cpu_sr_f, t_zero, t_true, t_next); 221784696d1SRichard Henderson 222784696d1SRichard Henderson tcg_temp_free(t_next); 223784696d1SRichard Henderson tcg_temp_free(t_true); 224784696d1SRichard Henderson tcg_temp_free(t_zero); 225da1d7759SSebastian Macke } 226da1d7759SSebastian Macke break; 227da1d7759SSebastian Macke case 0x11: /* l.jr */ 228bbe418f2SJia Liu tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); 229da1d7759SSebastian Macke break; 230da1d7759SSebastian Macke case 0x12: /* l.jalr */ 2311ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_R[9], (dc->base.pc_next + 8)); 232bbe418f2SJia Liu tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); 233da1d7759SSebastian Macke break; 234da1d7759SSebastian Macke default: 235bbe418f2SJia Liu gen_illegal_exception(dc); 236da1d7759SSebastian Macke break; 237bbe418f2SJia Liu } 238bbe418f2SJia Liu 239bbe418f2SJia Liu dc->delayed_branch = 2; 240bbe418f2SJia Liu } 241bbe418f2SJia Liu 24297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc) 2439ecaa27eSRichard Henderson { 2440c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 24597458071SRichard Henderson gen_helper_ove_cy(cpu_env); 2469ecaa27eSRichard Henderson } 2470c53d734SRichard Henderson } 2489ecaa27eSRichard Henderson 24997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc) 2509ecaa27eSRichard Henderson { 2510c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 25297458071SRichard Henderson gen_helper_ove_ov(cpu_env); 2539ecaa27eSRichard Henderson } 2540c53d734SRichard Henderson } 2559ecaa27eSRichard Henderson 25697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc) 2579ecaa27eSRichard Henderson { 2580c53d734SRichard Henderson if (dc->tb_flags & SR_OVE) { 25997458071SRichard Henderson gen_helper_ove_cyov(cpu_env); 2609ecaa27eSRichard Henderson } 2610c53d734SRichard Henderson } 2629ecaa27eSRichard Henderson 2639ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2649ecaa27eSRichard Henderson { 2659ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2669ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2679ecaa27eSRichard Henderson 26897458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); 26997458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2709ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 27197458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2729ecaa27eSRichard Henderson tcg_temp_free(t0); 2739ecaa27eSRichard Henderson 2749ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2759ecaa27eSRichard Henderson tcg_temp_free(res); 2769ecaa27eSRichard Henderson 27797458071SRichard Henderson gen_ove_cyov(dc); 2789ecaa27eSRichard Henderson } 2799ecaa27eSRichard Henderson 2809ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2819ecaa27eSRichard Henderson { 2829ecaa27eSRichard Henderson TCGv t0 = tcg_const_tl(0); 2839ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 2849ecaa27eSRichard Henderson 28597458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); 28697458071SRichard Henderson tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); 28797458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); 2889ecaa27eSRichard Henderson tcg_gen_xor_tl(t0, res, srcb); 28997458071SRichard Henderson tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); 2909ecaa27eSRichard Henderson tcg_temp_free(t0); 2919ecaa27eSRichard Henderson 2929ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 2939ecaa27eSRichard Henderson tcg_temp_free(res); 2949ecaa27eSRichard Henderson 29597458071SRichard Henderson gen_ove_cyov(dc); 2969ecaa27eSRichard Henderson } 2979ecaa27eSRichard Henderson 2989ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 2999ecaa27eSRichard Henderson { 3009ecaa27eSRichard Henderson TCGv res = tcg_temp_new(); 3019ecaa27eSRichard Henderson 3029ecaa27eSRichard Henderson tcg_gen_sub_tl(res, srca, srcb); 30397458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); 30497458071SRichard Henderson tcg_gen_xor_tl(cpu_sr_ov, res, srcb); 30597458071SRichard Henderson tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); 30697458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); 3079ecaa27eSRichard Henderson 3089ecaa27eSRichard Henderson tcg_gen_mov_tl(dest, res); 3099ecaa27eSRichard Henderson tcg_temp_free(res); 3109ecaa27eSRichard Henderson 31197458071SRichard Henderson gen_ove_cyov(dc); 3129ecaa27eSRichard Henderson } 3139ecaa27eSRichard Henderson 3149ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 3159ecaa27eSRichard Henderson { 3169ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 3179ecaa27eSRichard Henderson 31897458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); 3199ecaa27eSRichard Henderson tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); 32097458071SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); 3219ecaa27eSRichard Henderson tcg_temp_free(t0); 3229ecaa27eSRichard Henderson 32397458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 32497458071SRichard Henderson gen_ove_ov(dc); 3259ecaa27eSRichard Henderson } 3269ecaa27eSRichard Henderson 3279ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 3289ecaa27eSRichard Henderson { 32997458071SRichard Henderson tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); 33097458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); 3319ecaa27eSRichard Henderson 33297458071SRichard Henderson gen_ove_cy(dc); 3339ecaa27eSRichard Henderson } 3349ecaa27eSRichard Henderson 3359ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 3369ecaa27eSRichard Henderson { 3379ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 3389ecaa27eSRichard Henderson 33997458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); 3409ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 3419ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 34297458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_ov); 3439ecaa27eSRichard Henderson tcg_gen_div_tl(dest, srca, t0); 3449ecaa27eSRichard Henderson tcg_temp_free(t0); 3459ecaa27eSRichard Henderson 34697458071SRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 34797458071SRichard Henderson gen_ove_ov(dc); 3489ecaa27eSRichard Henderson } 3499ecaa27eSRichard Henderson 3509ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) 3519ecaa27eSRichard Henderson { 3529ecaa27eSRichard Henderson TCGv t0 = tcg_temp_new(); 3539ecaa27eSRichard Henderson 35497458071SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); 3559ecaa27eSRichard Henderson /* The result of divide-by-zero is undefined. 3569ecaa27eSRichard Henderson Supress the host-side exception by dividing by 1. */ 35797458071SRichard Henderson tcg_gen_or_tl(t0, srcb, cpu_sr_cy); 3589ecaa27eSRichard Henderson tcg_gen_divu_tl(dest, srca, t0); 3599ecaa27eSRichard Henderson tcg_temp_free(t0); 3609ecaa27eSRichard Henderson 36197458071SRichard Henderson gen_ove_cy(dc); 3629ecaa27eSRichard Henderson } 363da1d7759SSebastian Macke 364cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) 365cc5de49eSRichard Henderson { 366cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 367cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 368cc5de49eSRichard Henderson 369cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 370cc5de49eSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 371cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 372cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 373cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_ov, 0); 374cc5de49eSRichard Henderson } else { 375cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 376cc5de49eSRichard Henderson 377cc5de49eSRichard Henderson tcg_gen_muls2_i64(cpu_mac, high, t1, t2); 378cc5de49eSRichard Henderson tcg_gen_sari_i64(t1, cpu_mac, 63); 379cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); 380cc5de49eSRichard Henderson tcg_temp_free_i64(high); 381cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); 382cc5de49eSRichard Henderson tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); 383cc5de49eSRichard Henderson 384cc5de49eSRichard Henderson gen_ove_ov(dc); 385cc5de49eSRichard Henderson } 386cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 387cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 388cc5de49eSRichard Henderson } 389cc5de49eSRichard Henderson 390cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) 391cc5de49eSRichard Henderson { 392cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 393cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 394cc5de49eSRichard Henderson 395cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 396cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 397cc5de49eSRichard Henderson if (TARGET_LONG_BITS == 32) { 398cc5de49eSRichard Henderson tcg_gen_mul_i64(cpu_mac, t1, t2); 399cc5de49eSRichard Henderson tcg_gen_movi_tl(cpu_sr_cy, 0); 400cc5de49eSRichard Henderson } else { 401cc5de49eSRichard Henderson TCGv_i64 high = tcg_temp_new_i64(); 402cc5de49eSRichard Henderson 403cc5de49eSRichard Henderson tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); 404cc5de49eSRichard Henderson tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); 405cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, high); 406cc5de49eSRichard Henderson tcg_temp_free_i64(high); 407cc5de49eSRichard Henderson 408cc5de49eSRichard Henderson gen_ove_cy(dc); 409cc5de49eSRichard Henderson } 410cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 411cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 412cc5de49eSRichard Henderson } 413cc5de49eSRichard Henderson 4146f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) 4156f7332baSRichard Henderson { 4166f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4176f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4186f7332baSRichard Henderson 4196f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4206f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4216f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4226f7332baSRichard Henderson 4236f7332baSRichard Henderson /* Note that overflow is only computed during addition stage. */ 4246f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4256f7332baSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 4266f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4276f7332baSRichard Henderson tcg_gen_andc_i64(t1, t1, t2); 4286f7332baSRichard Henderson tcg_temp_free_i64(t2); 4296f7332baSRichard Henderson 4306f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4316f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4326f7332baSRichard Henderson #else 4336f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4346f7332baSRichard Henderson #endif 4356f7332baSRichard Henderson tcg_temp_free_i64(t1); 4366f7332baSRichard Henderson 4376f7332baSRichard Henderson gen_ove_ov(dc); 4386f7332baSRichard Henderson } 4396f7332baSRichard Henderson 440cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) 441cc5de49eSRichard Henderson { 442cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 443cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 444cc5de49eSRichard Henderson 445cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 446cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 447cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 448cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 449cc5de49eSRichard Henderson 450cc5de49eSRichard Henderson /* Note that overflow is only computed during addition stage. */ 451cc5de49eSRichard Henderson tcg_gen_add_i64(cpu_mac, cpu_mac, t1); 452cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); 453cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); 454cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 455cc5de49eSRichard Henderson 456cc5de49eSRichard Henderson gen_ove_cy(dc); 457cc5de49eSRichard Henderson } 458cc5de49eSRichard Henderson 4596f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) 4606f7332baSRichard Henderson { 4616f7332baSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 4626f7332baSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 4636f7332baSRichard Henderson 4646f7332baSRichard Henderson tcg_gen_ext_tl_i64(t1, srca); 4656f7332baSRichard Henderson tcg_gen_ext_tl_i64(t2, srcb); 4666f7332baSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 4676f7332baSRichard Henderson 4686f7332baSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 4696f7332baSRichard Henderson tcg_gen_xor_i64(t2, cpu_mac, t1); 4706f7332baSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 4716f7332baSRichard Henderson tcg_gen_xor_i64(t1, t1, cpu_mac); 4726f7332baSRichard Henderson tcg_gen_and_i64(t1, t1, t2); 4736f7332baSRichard Henderson tcg_temp_free_i64(t2); 4746f7332baSRichard Henderson 4756f7332baSRichard Henderson #if TARGET_LONG_BITS == 32 4766f7332baSRichard Henderson tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); 4776f7332baSRichard Henderson #else 4786f7332baSRichard Henderson tcg_gen_mov_i64(cpu_sr_ov, t1); 4796f7332baSRichard Henderson #endif 4806f7332baSRichard Henderson tcg_temp_free_i64(t1); 4816f7332baSRichard Henderson 4826f7332baSRichard Henderson gen_ove_ov(dc); 4836f7332baSRichard Henderson } 4846f7332baSRichard Henderson 485cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) 486cc5de49eSRichard Henderson { 487cc5de49eSRichard Henderson TCGv_i64 t1 = tcg_temp_new_i64(); 488cc5de49eSRichard Henderson TCGv_i64 t2 = tcg_temp_new_i64(); 489cc5de49eSRichard Henderson 490cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t1, srca); 491cc5de49eSRichard Henderson tcg_gen_extu_tl_i64(t2, srcb); 492cc5de49eSRichard Henderson tcg_gen_mul_i64(t1, t1, t2); 493cc5de49eSRichard Henderson 494cc5de49eSRichard Henderson /* Note that overflow is only computed during subtraction stage. */ 495cc5de49eSRichard Henderson tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); 496cc5de49eSRichard Henderson tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); 497cc5de49eSRichard Henderson tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); 498cc5de49eSRichard Henderson tcg_temp_free_i64(t2); 499cc5de49eSRichard Henderson tcg_temp_free_i64(t1); 500cc5de49eSRichard Henderson 501cc5de49eSRichard Henderson gen_ove_cy(dc); 502cc5de49eSRichard Henderson } 503cc5de49eSRichard Henderson 504930c3d00SRichard Henderson static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) 505930c3d00SRichard Henderson { 506930c3d00SRichard Henderson TCGv ea = tcg_temp_new(); 507930c3d00SRichard Henderson 508930c3d00SRichard Henderson tcg_gen_addi_tl(ea, ra, ofs); 509930c3d00SRichard Henderson tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL); 510930c3d00SRichard Henderson tcg_gen_mov_tl(cpu_lock_addr, ea); 511930c3d00SRichard Henderson tcg_gen_mov_tl(cpu_lock_value, rd); 512930c3d00SRichard Henderson tcg_temp_free(ea); 513930c3d00SRichard Henderson } 514930c3d00SRichard Henderson 5156597c28dSRichard Henderson static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs) 516930c3d00SRichard Henderson { 517930c3d00SRichard Henderson TCGv ea, val; 518930c3d00SRichard Henderson TCGLabel *lab_fail, *lab_done; 519930c3d00SRichard Henderson 520930c3d00SRichard Henderson ea = tcg_temp_new(); 521930c3d00SRichard Henderson tcg_gen_addi_tl(ea, ra, ofs); 522930c3d00SRichard Henderson 5236597c28dSRichard Henderson /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned 5246597c28dSRichard Henderson to cpu_R[0]. Since l.swa is quite often immediately followed by a 5256597c28dSRichard Henderson branch, don't bother reallocating; finish the TB using the "real" R0. 5266597c28dSRichard Henderson This also takes care of RB input across the branch. */ 5276597c28dSRichard Henderson cpu_R[0] = cpu_R0; 5286597c28dSRichard Henderson 529930c3d00SRichard Henderson lab_fail = gen_new_label(); 530930c3d00SRichard Henderson lab_done = gen_new_label(); 531930c3d00SRichard Henderson tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); 532930c3d00SRichard Henderson tcg_temp_free(ea); 533930c3d00SRichard Henderson 534930c3d00SRichard Henderson val = tcg_temp_new(); 535930c3d00SRichard Henderson tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, 5366597c28dSRichard Henderson cpu_R[b], dc->mem_idx, MO_TEUL); 53784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); 538930c3d00SRichard Henderson tcg_temp_free(val); 539930c3d00SRichard Henderson 540930c3d00SRichard Henderson tcg_gen_br(lab_done); 541930c3d00SRichard Henderson 542930c3d00SRichard Henderson gen_set_label(lab_fail); 54384775c43SRichard Henderson tcg_gen_movi_tl(cpu_sr_f, 0); 544930c3d00SRichard Henderson 545930c3d00SRichard Henderson gen_set_label(lab_done); 546930c3d00SRichard Henderson tcg_gen_movi_tl(cpu_lock_addr, -1); 547930c3d00SRichard Henderson } 548930c3d00SRichard Henderson 549bbe418f2SJia Liu static void dec_calc(DisasContext *dc, uint32_t insn) 550bbe418f2SJia Liu { 551bbe418f2SJia Liu uint32_t op0, op1, op2; 552bbe418f2SJia Liu uint32_t ra, rb, rd; 553bbe418f2SJia Liu op0 = extract32(insn, 0, 4); 554bbe418f2SJia Liu op1 = extract32(insn, 8, 2); 555bbe418f2SJia Liu op2 = extract32(insn, 6, 2); 556bbe418f2SJia Liu ra = extract32(insn, 16, 5); 557bbe418f2SJia Liu rb = extract32(insn, 11, 5); 558bbe418f2SJia Liu rd = extract32(insn, 21, 5); 559bbe418f2SJia Liu 560bbe418f2SJia Liu switch (op1) { 561cf2ae442SRichard Henderson case 0: 562cf2ae442SRichard Henderson switch (op0) { 563cf2ae442SRichard Henderson case 0x0: /* l.add */ 564bbe418f2SJia Liu LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); 5659ecaa27eSRichard Henderson gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 566cf2ae442SRichard Henderson return; 567bbe418f2SJia Liu 568cf2ae442SRichard Henderson case 0x1: /* l.addc */ 569bbe418f2SJia Liu LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); 5709ecaa27eSRichard Henderson gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 571cf2ae442SRichard Henderson return; 572bbe418f2SJia Liu 573cf2ae442SRichard Henderson case 0x2: /* l.sub */ 574bbe418f2SJia Liu LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); 5759ecaa27eSRichard Henderson gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 576cf2ae442SRichard Henderson return; 577bbe418f2SJia Liu 578cf2ae442SRichard Henderson case 0x3: /* l.and */ 579bbe418f2SJia Liu LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb); 580bbe418f2SJia Liu tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 581cf2ae442SRichard Henderson return; 582bbe418f2SJia Liu 583cf2ae442SRichard Henderson case 0x4: /* l.or */ 584bbe418f2SJia Liu LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb); 585bbe418f2SJia Liu tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 586cf2ae442SRichard Henderson return; 587bbe418f2SJia Liu 588cf2ae442SRichard Henderson case 0x5: /* l.xor */ 589bbe418f2SJia Liu LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb); 590bbe418f2SJia Liu tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 591cf2ae442SRichard Henderson return; 592cf2ae442SRichard Henderson 593cf2ae442SRichard Henderson case 0x8: 594cf2ae442SRichard Henderson switch (op2) { 595cf2ae442SRichard Henderson case 0: /* l.sll */ 596cf2ae442SRichard Henderson LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); 597cf2ae442SRichard Henderson tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 598cf2ae442SRichard Henderson return; 599cf2ae442SRichard Henderson case 1: /* l.srl */ 600cf2ae442SRichard Henderson LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); 601cf2ae442SRichard Henderson tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 602cf2ae442SRichard Henderson return; 603cf2ae442SRichard Henderson case 2: /* l.sra */ 604cf2ae442SRichard Henderson LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); 605cf2ae442SRichard Henderson tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 606cf2ae442SRichard Henderson return; 607cf2ae442SRichard Henderson case 3: /* l.ror */ 608cf2ae442SRichard Henderson LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); 609cf2ae442SRichard Henderson tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); 610cf2ae442SRichard Henderson return; 611bbe418f2SJia Liu } 612bbe418f2SJia Liu break; 613bbe418f2SJia Liu 614cf2ae442SRichard Henderson case 0xc: 615cf2ae442SRichard Henderson switch (op2) { 616cf2ae442SRichard Henderson case 0: /* l.exths */ 617cf2ae442SRichard Henderson LOG_DIS("l.exths r%d, r%d\n", rd, ra); 618cf2ae442SRichard Henderson tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); 619cf2ae442SRichard Henderson return; 620cf2ae442SRichard Henderson case 1: /* l.extbs */ 621cf2ae442SRichard Henderson LOG_DIS("l.extbs r%d, r%d\n", rd, ra); 622cf2ae442SRichard Henderson tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); 623cf2ae442SRichard Henderson return; 624cf2ae442SRichard Henderson case 2: /* l.exthz */ 625cf2ae442SRichard Henderson LOG_DIS("l.exthz r%d, r%d\n", rd, ra); 626cf2ae442SRichard Henderson tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); 627cf2ae442SRichard Henderson return; 628cf2ae442SRichard Henderson case 3: /* l.extbz */ 629cf2ae442SRichard Henderson LOG_DIS("l.extbz r%d, r%d\n", rd, ra); 630cf2ae442SRichard Henderson tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); 631cf2ae442SRichard Henderson return; 632bbe418f2SJia Liu } 633bbe418f2SJia Liu break; 634bbe418f2SJia Liu 635cf2ae442SRichard Henderson case 0xd: 636cf2ae442SRichard Henderson switch (op2) { 637cf2ae442SRichard Henderson case 0: /* l.extws */ 638cf2ae442SRichard Henderson LOG_DIS("l.extws r%d, r%d\n", rd, ra); 639cf2ae442SRichard Henderson tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); 640cf2ae442SRichard Henderson return; 641cf2ae442SRichard Henderson case 1: /* l.extwz */ 642cf2ae442SRichard Henderson LOG_DIS("l.extwz r%d, r%d\n", rd, ra); 643cf2ae442SRichard Henderson tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); 644cf2ae442SRichard Henderson return; 645bbe418f2SJia Liu } 646bbe418f2SJia Liu break; 647bbe418f2SJia Liu 648cf2ae442SRichard Henderson case 0xe: /* l.cmov */ 649bbe418f2SJia Liu LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); 650bbe418f2SJia Liu { 651784696d1SRichard Henderson TCGv zero = tcg_const_tl(0); 652784696d1SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero, 653784696d1SRichard Henderson cpu_R[ra], cpu_R[rb]); 654784696d1SRichard Henderson tcg_temp_free(zero); 655bbe418f2SJia Liu } 656cf2ae442SRichard Henderson return; 657bbe418f2SJia Liu 658cf2ae442SRichard Henderson case 0xf: /* l.ff1 */ 659bbe418f2SJia Liu LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); 660555baef8SRichard Henderson tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1); 661555baef8SRichard Henderson tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1); 662cf2ae442SRichard Henderson return; 663cf2ae442SRichard Henderson } 664bbe418f2SJia Liu break; 665cf2ae442SRichard Henderson 666cf2ae442SRichard Henderson case 1: 667cf2ae442SRichard Henderson switch (op0) { 668cf2ae442SRichard Henderson case 0xf: /* l.fl1 */ 669bbe418f2SJia Liu LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); 670555baef8SRichard Henderson tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS); 671555baef8SRichard Henderson tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]); 672cf2ae442SRichard Henderson return; 673bbe418f2SJia Liu } 674bbe418f2SJia Liu break; 675bbe418f2SJia Liu 676cf2ae442SRichard Henderson case 2: 677bbe418f2SJia Liu break; 678bbe418f2SJia Liu 679cf2ae442SRichard Henderson case 3: 680cf2ae442SRichard Henderson switch (op0) { 681cf2ae442SRichard Henderson case 0x6: /* l.mul */ 682cf2ae442SRichard Henderson LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); 683cf2ae442SRichard Henderson gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 684cf2ae442SRichard Henderson return; 685cf2ae442SRichard Henderson 686cc5de49eSRichard Henderson case 0x7: /* l.muld */ 687cc5de49eSRichard Henderson LOG_DIS("l.muld r%d, r%d\n", ra, rb); 688cc5de49eSRichard Henderson gen_muld(dc, cpu_R[ra], cpu_R[rb]); 689cc5de49eSRichard Henderson break; 690cc5de49eSRichard Henderson 691cf2ae442SRichard Henderson case 0x9: /* l.div */ 692cf2ae442SRichard Henderson LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); 693cf2ae442SRichard Henderson gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 694cf2ae442SRichard Henderson return; 695cf2ae442SRichard Henderson 696cf2ae442SRichard Henderson case 0xa: /* l.divu */ 697cf2ae442SRichard Henderson LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); 698cf2ae442SRichard Henderson gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 699cf2ae442SRichard Henderson return; 700cf2ae442SRichard Henderson 701cf2ae442SRichard Henderson case 0xb: /* l.mulu */ 702cf2ae442SRichard Henderson LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); 703cf2ae442SRichard Henderson gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); 704cf2ae442SRichard Henderson return; 705cc5de49eSRichard Henderson 706cc5de49eSRichard Henderson case 0xc: /* l.muldu */ 707cc5de49eSRichard Henderson LOG_DIS("l.muldu r%d, r%d\n", ra, rb); 708cc5de49eSRichard Henderson gen_muldu(dc, cpu_R[ra], cpu_R[rb]); 709cc5de49eSRichard Henderson return; 710bbe418f2SJia Liu } 711bbe418f2SJia Liu break; 712bbe418f2SJia Liu } 713bbe418f2SJia Liu gen_illegal_exception(dc); 714bbe418f2SJia Liu } 715bbe418f2SJia Liu 716bbe418f2SJia Liu static void dec_misc(DisasContext *dc, uint32_t insn) 717bbe418f2SJia Liu { 718bbe418f2SJia Liu uint32_t op0, op1; 719bbe418f2SJia Liu uint32_t ra, rb, rd; 7206da544a6SRichard Henderson uint32_t L6, K5, K16, K5_11; 7216da544a6SRichard Henderson int32_t I16, I5_11, N26; 7225631e69cSRichard Henderson TCGMemOp mop; 7239ecaa27eSRichard Henderson TCGv t0; 7245631e69cSRichard Henderson 725bbe418f2SJia Liu op0 = extract32(insn, 26, 6); 726bbe418f2SJia Liu op1 = extract32(insn, 24, 2); 727bbe418f2SJia Liu ra = extract32(insn, 16, 5); 728bbe418f2SJia Liu rb = extract32(insn, 11, 5); 729bbe418f2SJia Liu rd = extract32(insn, 21, 5); 730bbe418f2SJia Liu L6 = extract32(insn, 5, 6); 731bbe418f2SJia Liu K5 = extract32(insn, 0, 5); 7326da544a6SRichard Henderson K16 = extract32(insn, 0, 16); 7336da544a6SRichard Henderson I16 = (int16_t)K16; 7346da544a6SRichard Henderson N26 = sextract32(insn, 0, 26); 7356da544a6SRichard Henderson K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11); 7366da544a6SRichard Henderson I5_11 = (int16_t)K5_11; 737bbe418f2SJia Liu 738bbe418f2SJia Liu switch (op0) { 739bbe418f2SJia Liu case 0x00: /* l.j */ 740bbe418f2SJia Liu LOG_DIS("l.j %d\n", N26); 741bbe418f2SJia Liu gen_jump(dc, N26, 0, op0); 742bbe418f2SJia Liu break; 743bbe418f2SJia Liu 744bbe418f2SJia Liu case 0x01: /* l.jal */ 745bbe418f2SJia Liu LOG_DIS("l.jal %d\n", N26); 746bbe418f2SJia Liu gen_jump(dc, N26, 0, op0); 747bbe418f2SJia Liu break; 748bbe418f2SJia Liu 749bbe418f2SJia Liu case 0x03: /* l.bnf */ 750bbe418f2SJia Liu LOG_DIS("l.bnf %d\n", N26); 751bbe418f2SJia Liu gen_jump(dc, N26, 0, op0); 752bbe418f2SJia Liu break; 753bbe418f2SJia Liu 754bbe418f2SJia Liu case 0x04: /* l.bf */ 755bbe418f2SJia Liu LOG_DIS("l.bf %d\n", N26); 756bbe418f2SJia Liu gen_jump(dc, N26, 0, op0); 757bbe418f2SJia Liu break; 758bbe418f2SJia Liu 759bbe418f2SJia Liu case 0x05: 760bbe418f2SJia Liu switch (op1) { 761bbe418f2SJia Liu case 0x01: /* l.nop */ 762bbe418f2SJia Liu LOG_DIS("l.nop %d\n", I16); 763bbe418f2SJia Liu break; 764bbe418f2SJia Liu 765bbe418f2SJia Liu default: 766bbe418f2SJia Liu gen_illegal_exception(dc); 767bbe418f2SJia Liu break; 768bbe418f2SJia Liu } 769bbe418f2SJia Liu break; 770bbe418f2SJia Liu 771bbe418f2SJia Liu case 0x11: /* l.jr */ 772bbe418f2SJia Liu LOG_DIS("l.jr r%d\n", rb); 773bbe418f2SJia Liu gen_jump(dc, 0, rb, op0); 774bbe418f2SJia Liu break; 775bbe418f2SJia Liu 776bbe418f2SJia Liu case 0x12: /* l.jalr */ 777bbe418f2SJia Liu LOG_DIS("l.jalr r%d\n", rb); 778bbe418f2SJia Liu gen_jump(dc, 0, rb, op0); 779bbe418f2SJia Liu break; 780bbe418f2SJia Liu 781bbe418f2SJia Liu case 0x13: /* l.maci */ 7826da544a6SRichard Henderson LOG_DIS("l.maci r%d, %d\n", ra, I16); 7836f7332baSRichard Henderson t0 = tcg_const_tl(I16); 7846f7332baSRichard Henderson gen_mac(dc, cpu_R[ra], t0); 7856f7332baSRichard Henderson tcg_temp_free(t0); 786bbe418f2SJia Liu break; 787bbe418f2SJia Liu 788bbe418f2SJia Liu case 0x09: /* l.rfe */ 789bbe418f2SJia Liu LOG_DIS("l.rfe\n"); 790bbe418f2SJia Liu { 791bbe418f2SJia Liu #if defined(CONFIG_USER_ONLY) 792bbe418f2SJia Liu return; 793bbe418f2SJia Liu #else 794bbe418f2SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 795bbe418f2SJia Liu gen_illegal_exception(dc); 796bbe418f2SJia Liu return; 797bbe418f2SJia Liu } 798bbe418f2SJia Liu gen_helper_rfe(cpu_env); 7991ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 800bbe418f2SJia Liu #endif 801bbe418f2SJia Liu } 802bbe418f2SJia Liu break; 803bbe418f2SJia Liu 804930c3d00SRichard Henderson case 0x1b: /* l.lwa */ 805930c3d00SRichard Henderson LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16); 8066597c28dSRichard Henderson check_r0_write(rd); 807930c3d00SRichard Henderson gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16); 808930c3d00SRichard Henderson break; 809930c3d00SRichard Henderson 810bbe418f2SJia Liu case 0x1c: /* l.cust1 */ 811bbe418f2SJia Liu LOG_DIS("l.cust1\n"); 812bbe418f2SJia Liu break; 813bbe418f2SJia Liu 814bbe418f2SJia Liu case 0x1d: /* l.cust2 */ 815bbe418f2SJia Liu LOG_DIS("l.cust2\n"); 816bbe418f2SJia Liu break; 817bbe418f2SJia Liu 818bbe418f2SJia Liu case 0x1e: /* l.cust3 */ 819bbe418f2SJia Liu LOG_DIS("l.cust3\n"); 820bbe418f2SJia Liu break; 821bbe418f2SJia Liu 822bbe418f2SJia Liu case 0x1f: /* l.cust4 */ 823bbe418f2SJia Liu LOG_DIS("l.cust4\n"); 824bbe418f2SJia Liu break; 825bbe418f2SJia Liu 826bbe418f2SJia Liu case 0x3c: /* l.cust5 */ 827bbe418f2SJia Liu LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5); 828bbe418f2SJia Liu break; 829bbe418f2SJia Liu 830bbe418f2SJia Liu case 0x3d: /* l.cust6 */ 831bbe418f2SJia Liu LOG_DIS("l.cust6\n"); 832bbe418f2SJia Liu break; 833bbe418f2SJia Liu 834bbe418f2SJia Liu case 0x3e: /* l.cust7 */ 835bbe418f2SJia Liu LOG_DIS("l.cust7\n"); 836bbe418f2SJia Liu break; 837bbe418f2SJia Liu 838bbe418f2SJia Liu case 0x3f: /* l.cust8 */ 839bbe418f2SJia Liu LOG_DIS("l.cust8\n"); 840bbe418f2SJia Liu break; 841bbe418f2SJia Liu 842bbe418f2SJia Liu /* not used yet, open it when we need or64. */ 843bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64 844bbe418f2SJia Liu case 0x20: l.ld 845bbe418f2SJia Liu LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); 846bbe418f2SJia Liu check_ob64s(dc); 8475631e69cSRichard Henderson mop = MO_TEQ; 8485631e69cSRichard Henderson goto do_load; 849bbe418f2SJia Liu #endif*/ 850bbe418f2SJia Liu 851bbe418f2SJia Liu case 0x21: /* l.lwz */ 852bbe418f2SJia Liu LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); 8535631e69cSRichard Henderson mop = MO_TEUL; 8545631e69cSRichard Henderson goto do_load; 855bbe418f2SJia Liu 856bbe418f2SJia Liu case 0x22: /* l.lws */ 857bbe418f2SJia Liu LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); 8585631e69cSRichard Henderson mop = MO_TESL; 8595631e69cSRichard Henderson goto do_load; 860bbe418f2SJia Liu 861bbe418f2SJia Liu case 0x23: /* l.lbz */ 862bbe418f2SJia Liu LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); 8635631e69cSRichard Henderson mop = MO_UB; 8645631e69cSRichard Henderson goto do_load; 865bbe418f2SJia Liu 866bbe418f2SJia Liu case 0x24: /* l.lbs */ 867bbe418f2SJia Liu LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); 8685631e69cSRichard Henderson mop = MO_SB; 8695631e69cSRichard Henderson goto do_load; 870bbe418f2SJia Liu 871bbe418f2SJia Liu case 0x25: /* l.lhz */ 872bbe418f2SJia Liu LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); 8735631e69cSRichard Henderson mop = MO_TEUW; 8745631e69cSRichard Henderson goto do_load; 875bbe418f2SJia Liu 876bbe418f2SJia Liu case 0x26: /* l.lhs */ 877bbe418f2SJia Liu LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); 8785631e69cSRichard Henderson mop = MO_TESW; 8795631e69cSRichard Henderson goto do_load; 8805631e69cSRichard Henderson 8815631e69cSRichard Henderson do_load: 8826597c28dSRichard Henderson check_r0_write(rd); 8836597c28dSRichard Henderson t0 = tcg_temp_new(); 8846da544a6SRichard Henderson tcg_gen_addi_tl(t0, cpu_R[ra], I16); 8855631e69cSRichard Henderson tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); 886bbe418f2SJia Liu tcg_temp_free(t0); 887bbe418f2SJia Liu break; 888bbe418f2SJia Liu 889bbe418f2SJia Liu case 0x27: /* l.addi */ 890bbe418f2SJia Liu LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); 8916597c28dSRichard Henderson check_r0_write(rd); 8929ecaa27eSRichard Henderson t0 = tcg_const_tl(I16); 8939ecaa27eSRichard Henderson gen_add(dc, cpu_R[rd], cpu_R[ra], t0); 8949ecaa27eSRichard Henderson tcg_temp_free(t0); 895bbe418f2SJia Liu break; 896bbe418f2SJia Liu 897bbe418f2SJia Liu case 0x28: /* l.addic */ 898bbe418f2SJia Liu LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); 8996597c28dSRichard Henderson check_r0_write(rd); 9009ecaa27eSRichard Henderson t0 = tcg_const_tl(I16); 9019ecaa27eSRichard Henderson gen_addc(dc, cpu_R[rd], cpu_R[ra], t0); 9029ecaa27eSRichard Henderson tcg_temp_free(t0); 903bbe418f2SJia Liu break; 904bbe418f2SJia Liu 905bbe418f2SJia Liu case 0x29: /* l.andi */ 9066da544a6SRichard Henderson LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16); 9076597c28dSRichard Henderson check_r0_write(rd); 9086da544a6SRichard Henderson tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16); 909bbe418f2SJia Liu break; 910bbe418f2SJia Liu 911bbe418f2SJia Liu case 0x2a: /* l.ori */ 9126da544a6SRichard Henderson LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16); 9136597c28dSRichard Henderson check_r0_write(rd); 9146da544a6SRichard Henderson tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16); 915bbe418f2SJia Liu break; 916bbe418f2SJia Liu 917bbe418f2SJia Liu case 0x2b: /* l.xori */ 918bbe418f2SJia Liu LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16); 9196597c28dSRichard Henderson check_r0_write(rd); 9206da544a6SRichard Henderson tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16); 921bbe418f2SJia Liu break; 922bbe418f2SJia Liu 923bbe418f2SJia Liu case 0x2c: /* l.muli */ 924bbe418f2SJia Liu LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); 9256597c28dSRichard Henderson check_r0_write(rd); 9269ecaa27eSRichard Henderson t0 = tcg_const_tl(I16); 9279ecaa27eSRichard Henderson gen_mul(dc, cpu_R[rd], cpu_R[ra], t0); 9289ecaa27eSRichard Henderson tcg_temp_free(t0); 929bbe418f2SJia Liu break; 930bbe418f2SJia Liu 931bbe418f2SJia Liu case 0x2d: /* l.mfspr */ 9326da544a6SRichard Henderson LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16); 9336597c28dSRichard Henderson check_r0_write(rd); 9344dd044c6SJia Liu { 9354dd044c6SJia Liu #if defined(CONFIG_USER_ONLY) 9364dd044c6SJia Liu return; 9374dd044c6SJia Liu #else 9386da544a6SRichard Henderson TCGv_i32 ti = tcg_const_i32(K16); 9394dd044c6SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 9404dd044c6SJia Liu gen_illegal_exception(dc); 9414dd044c6SJia Liu return; 9424dd044c6SJia Liu } 9434dd044c6SJia Liu gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); 9444dd044c6SJia Liu tcg_temp_free_i32(ti); 9454dd044c6SJia Liu #endif 9464dd044c6SJia Liu } 947bbe418f2SJia Liu break; 948bbe418f2SJia Liu 949bbe418f2SJia Liu case 0x30: /* l.mtspr */ 9506da544a6SRichard Henderson LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11); 9514dd044c6SJia Liu { 9524dd044c6SJia Liu #if defined(CONFIG_USER_ONLY) 9534dd044c6SJia Liu return; 9544dd044c6SJia Liu #else 9556da544a6SRichard Henderson TCGv_i32 im = tcg_const_i32(K5_11); 9564dd044c6SJia Liu if (dc->mem_idx == MMU_USER_IDX) { 9574dd044c6SJia Liu gen_illegal_exception(dc); 9584dd044c6SJia Liu return; 9594dd044c6SJia Liu } 9604dd044c6SJia Liu gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); 9614dd044c6SJia Liu tcg_temp_free_i32(im); 9624dd044c6SJia Liu #endif 9634dd044c6SJia Liu } 964bbe418f2SJia Liu break; 965bbe418f2SJia Liu 966930c3d00SRichard Henderson case 0x33: /* l.swa */ 9676da544a6SRichard Henderson LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11); 9686597c28dSRichard Henderson gen_swa(dc, rb, cpu_R[ra], I5_11); 969930c3d00SRichard Henderson break; 970930c3d00SRichard Henderson 971bbe418f2SJia Liu /* not used yet, open it when we need or64. */ 972bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64 973bbe418f2SJia Liu case 0x34: l.sd 9746da544a6SRichard Henderson LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11); 975bbe418f2SJia Liu check_ob64s(dc); 9765631e69cSRichard Henderson mop = MO_TEQ; 9775631e69cSRichard Henderson goto do_store; 978bbe418f2SJia Liu #endif*/ 979bbe418f2SJia Liu 980bbe418f2SJia Liu case 0x35: /* l.sw */ 9816da544a6SRichard Henderson LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11); 9825631e69cSRichard Henderson mop = MO_TEUL; 9835631e69cSRichard Henderson goto do_store; 984bbe418f2SJia Liu 985bbe418f2SJia Liu case 0x36: /* l.sb */ 9866da544a6SRichard Henderson LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11); 9875631e69cSRichard Henderson mop = MO_UB; 9885631e69cSRichard Henderson goto do_store; 989bbe418f2SJia Liu 990bbe418f2SJia Liu case 0x37: /* l.sh */ 9916da544a6SRichard Henderson LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11); 9925631e69cSRichard Henderson mop = MO_TEUW; 9935631e69cSRichard Henderson goto do_store; 9945631e69cSRichard Henderson 9955631e69cSRichard Henderson do_store: 996bbe418f2SJia Liu { 997bbe418f2SJia Liu TCGv t0 = tcg_temp_new(); 9986da544a6SRichard Henderson tcg_gen_addi_tl(t0, cpu_R[ra], I5_11); 9995631e69cSRichard Henderson tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop); 1000bbe418f2SJia Liu tcg_temp_free(t0); 1001bbe418f2SJia Liu } 1002bbe418f2SJia Liu break; 1003bbe418f2SJia Liu 1004bbe418f2SJia Liu default: 1005bbe418f2SJia Liu gen_illegal_exception(dc); 1006bbe418f2SJia Liu break; 1007bbe418f2SJia Liu } 1008bbe418f2SJia Liu } 1009bbe418f2SJia Liu 1010bbe418f2SJia Liu static void dec_mac(DisasContext *dc, uint32_t insn) 1011bbe418f2SJia Liu { 1012bbe418f2SJia Liu uint32_t op0; 1013bbe418f2SJia Liu uint32_t ra, rb; 1014bbe418f2SJia Liu op0 = extract32(insn, 0, 4); 1015bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1016bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1017bbe418f2SJia Liu 1018bbe418f2SJia Liu switch (op0) { 1019bbe418f2SJia Liu case 0x0001: /* l.mac */ 1020bbe418f2SJia Liu LOG_DIS("l.mac r%d, r%d\n", ra, rb); 10216f7332baSRichard Henderson gen_mac(dc, cpu_R[ra], cpu_R[rb]); 1022bbe418f2SJia Liu break; 1023bbe418f2SJia Liu 1024bbe418f2SJia Liu case 0x0002: /* l.msb */ 1025bbe418f2SJia Liu LOG_DIS("l.msb r%d, r%d\n", ra, rb); 10266f7332baSRichard Henderson gen_msb(dc, cpu_R[ra], cpu_R[rb]); 1027bbe418f2SJia Liu break; 1028bbe418f2SJia Liu 1029cc5de49eSRichard Henderson case 0x0003: /* l.macu */ 1030cc5de49eSRichard Henderson LOG_DIS("l.macu r%d, r%d\n", ra, rb); 1031cc5de49eSRichard Henderson gen_macu(dc, cpu_R[ra], cpu_R[rb]); 1032cc5de49eSRichard Henderson break; 1033cc5de49eSRichard Henderson 1034cc5de49eSRichard Henderson case 0x0004: /* l.msbu */ 1035cc5de49eSRichard Henderson LOG_DIS("l.msbu r%d, r%d\n", ra, rb); 1036cc5de49eSRichard Henderson gen_msbu(dc, cpu_R[ra], cpu_R[rb]); 1037cc5de49eSRichard Henderson break; 1038cc5de49eSRichard Henderson 1039bbe418f2SJia Liu default: 1040bbe418f2SJia Liu gen_illegal_exception(dc); 1041bbe418f2SJia Liu break; 1042bbe418f2SJia Liu } 1043bbe418f2SJia Liu } 1044bbe418f2SJia Liu 1045bbe418f2SJia Liu static void dec_logic(DisasContext *dc, uint32_t insn) 1046bbe418f2SJia Liu { 1047bbe418f2SJia Liu uint32_t op0; 10486da544a6SRichard Henderson uint32_t rd, ra, L6, S6; 1049bbe418f2SJia Liu op0 = extract32(insn, 6, 2); 1050bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1051bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1052bbe418f2SJia Liu L6 = extract32(insn, 0, 6); 10536da544a6SRichard Henderson S6 = L6 & (TARGET_LONG_BITS - 1); 1054bbe418f2SJia Liu 10556597c28dSRichard Henderson check_r0_write(rd); 1056bbe418f2SJia Liu switch (op0) { 1057bbe418f2SJia Liu case 0x00: /* l.slli */ 1058bbe418f2SJia Liu LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); 10596da544a6SRichard Henderson tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6); 1060bbe418f2SJia Liu break; 1061bbe418f2SJia Liu 1062bbe418f2SJia Liu case 0x01: /* l.srli */ 1063bbe418f2SJia Liu LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6); 10646da544a6SRichard Henderson tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6); 1065bbe418f2SJia Liu break; 1066bbe418f2SJia Liu 1067bbe418f2SJia Liu case 0x02: /* l.srai */ 1068bbe418f2SJia Liu LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6); 10696da544a6SRichard Henderson tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6); 10706da544a6SRichard Henderson break; 1071bbe418f2SJia Liu 1072bbe418f2SJia Liu case 0x03: /* l.rori */ 1073bbe418f2SJia Liu LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6); 10746da544a6SRichard Henderson tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6); 1075bbe418f2SJia Liu break; 1076bbe418f2SJia Liu 1077bbe418f2SJia Liu default: 1078bbe418f2SJia Liu gen_illegal_exception(dc); 1079bbe418f2SJia Liu break; 1080bbe418f2SJia Liu } 1081bbe418f2SJia Liu } 1082bbe418f2SJia Liu 1083bbe418f2SJia Liu static void dec_M(DisasContext *dc, uint32_t insn) 1084bbe418f2SJia Liu { 1085bbe418f2SJia Liu uint32_t op0; 1086bbe418f2SJia Liu uint32_t rd; 1087bbe418f2SJia Liu uint32_t K16; 1088bbe418f2SJia Liu op0 = extract32(insn, 16, 1); 1089bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1090bbe418f2SJia Liu K16 = extract32(insn, 0, 16); 1091bbe418f2SJia Liu 10926597c28dSRichard Henderson check_r0_write(rd); 1093bbe418f2SJia Liu switch (op0) { 1094bbe418f2SJia Liu case 0x0: /* l.movhi */ 1095bbe418f2SJia Liu LOG_DIS("l.movhi r%d, %d\n", rd, K16); 1096bbe418f2SJia Liu tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); 1097bbe418f2SJia Liu break; 1098bbe418f2SJia Liu 1099bbe418f2SJia Liu case 0x1: /* l.macrc */ 1100bbe418f2SJia Liu LOG_DIS("l.macrc r%d\n", rd); 11016f7332baSRichard Henderson tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac); 11026f7332baSRichard Henderson tcg_gen_movi_i64(cpu_mac, 0); 1103bbe418f2SJia Liu break; 1104bbe418f2SJia Liu 1105bbe418f2SJia Liu default: 1106bbe418f2SJia Liu gen_illegal_exception(dc); 1107bbe418f2SJia Liu break; 1108bbe418f2SJia Liu } 1109bbe418f2SJia Liu } 1110bbe418f2SJia Liu 1111bbe418f2SJia Liu static void dec_comp(DisasContext *dc, uint32_t insn) 1112bbe418f2SJia Liu { 1113bbe418f2SJia Liu uint32_t op0; 1114bbe418f2SJia Liu uint32_t ra, rb; 1115bbe418f2SJia Liu 1116bbe418f2SJia Liu op0 = extract32(insn, 21, 5); 1117bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1118bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1119bbe418f2SJia Liu 1120bbe418f2SJia Liu /* unsigned integers */ 1121bbe418f2SJia Liu tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]); 1122bbe418f2SJia Liu tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]); 1123bbe418f2SJia Liu 1124bbe418f2SJia Liu switch (op0) { 1125bbe418f2SJia Liu case 0x0: /* l.sfeq */ 1126bbe418f2SJia Liu LOG_DIS("l.sfeq r%d, r%d\n", ra, rb); 112784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1128bbe418f2SJia Liu break; 1129bbe418f2SJia Liu 1130bbe418f2SJia Liu case 0x1: /* l.sfne */ 1131bbe418f2SJia Liu LOG_DIS("l.sfne r%d, r%d\n", ra, rb); 113284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1133bbe418f2SJia Liu break; 1134bbe418f2SJia Liu 1135bbe418f2SJia Liu case 0x2: /* l.sfgtu */ 1136bbe418f2SJia Liu LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb); 113784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1138bbe418f2SJia Liu break; 1139bbe418f2SJia Liu 1140bbe418f2SJia Liu case 0x3: /* l.sfgeu */ 1141bbe418f2SJia Liu LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb); 114284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1143bbe418f2SJia Liu break; 1144bbe418f2SJia Liu 1145bbe418f2SJia Liu case 0x4: /* l.sfltu */ 1146bbe418f2SJia Liu LOG_DIS("l.sfltu r%d, r%d\n", ra, rb); 114784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1148bbe418f2SJia Liu break; 1149bbe418f2SJia Liu 1150bbe418f2SJia Liu case 0x5: /* l.sfleu */ 1151bbe418f2SJia Liu LOG_DIS("l.sfleu r%d, r%d\n", ra, rb); 115284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1153bbe418f2SJia Liu break; 1154bbe418f2SJia Liu 1155bbe418f2SJia Liu case 0xa: /* l.sfgts */ 1156bbe418f2SJia Liu LOG_DIS("l.sfgts r%d, r%d\n", ra, rb); 115784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1158bbe418f2SJia Liu break; 1159bbe418f2SJia Liu 1160bbe418f2SJia Liu case 0xb: /* l.sfges */ 1161bbe418f2SJia Liu LOG_DIS("l.sfges r%d, r%d\n", ra, rb); 116284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1163bbe418f2SJia Liu break; 1164bbe418f2SJia Liu 1165bbe418f2SJia Liu case 0xc: /* l.sflts */ 1166bbe418f2SJia Liu LOG_DIS("l.sflts r%d, r%d\n", ra, rb); 116784775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1168bbe418f2SJia Liu break; 1169bbe418f2SJia Liu 1170bbe418f2SJia Liu case 0xd: /* l.sfles */ 1171bbe418f2SJia Liu LOG_DIS("l.sfles r%d, r%d\n", ra, rb); 117284775c43SRichard Henderson tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); 1173bbe418f2SJia Liu break; 1174bbe418f2SJia Liu 1175bbe418f2SJia Liu default: 1176bbe418f2SJia Liu gen_illegal_exception(dc); 1177bbe418f2SJia Liu break; 1178bbe418f2SJia Liu } 1179bbe418f2SJia Liu } 1180bbe418f2SJia Liu 1181bbe418f2SJia Liu static void dec_compi(DisasContext *dc, uint32_t insn) 1182bbe418f2SJia Liu { 11836da544a6SRichard Henderson uint32_t op0, ra; 11846da544a6SRichard Henderson int32_t I16; 1185bbe418f2SJia Liu 1186bbe418f2SJia Liu op0 = extract32(insn, 21, 5); 1187bbe418f2SJia Liu ra = extract32(insn, 16, 5); 11886da544a6SRichard Henderson I16 = sextract32(insn, 0, 16); 1189bbe418f2SJia Liu 1190bbe418f2SJia Liu switch (op0) { 1191bbe418f2SJia Liu case 0x0: /* l.sfeqi */ 1192bbe418f2SJia Liu LOG_DIS("l.sfeqi r%d, %d\n", ra, I16); 119384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16); 1194bbe418f2SJia Liu break; 1195bbe418f2SJia Liu 1196bbe418f2SJia Liu case 0x1: /* l.sfnei */ 1197bbe418f2SJia Liu LOG_DIS("l.sfnei r%d, %d\n", ra, I16); 119884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16); 1199bbe418f2SJia Liu break; 1200bbe418f2SJia Liu 1201bbe418f2SJia Liu case 0x2: /* l.sfgtui */ 1202bbe418f2SJia Liu LOG_DIS("l.sfgtui r%d, %d\n", ra, I16); 120384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16); 1204bbe418f2SJia Liu break; 1205bbe418f2SJia Liu 1206bbe418f2SJia Liu case 0x3: /* l.sfgeui */ 1207bbe418f2SJia Liu LOG_DIS("l.sfgeui r%d, %d\n", ra, I16); 120884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16); 1209bbe418f2SJia Liu break; 1210bbe418f2SJia Liu 1211bbe418f2SJia Liu case 0x4: /* l.sfltui */ 1212bbe418f2SJia Liu LOG_DIS("l.sfltui r%d, %d\n", ra, I16); 121384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16); 1214bbe418f2SJia Liu break; 1215bbe418f2SJia Liu 1216bbe418f2SJia Liu case 0x5: /* l.sfleui */ 1217bbe418f2SJia Liu LOG_DIS("l.sfleui r%d, %d\n", ra, I16); 121884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16); 1219bbe418f2SJia Liu break; 1220bbe418f2SJia Liu 1221bbe418f2SJia Liu case 0xa: /* l.sfgtsi */ 1222bbe418f2SJia Liu LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16); 122384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16); 1224bbe418f2SJia Liu break; 1225bbe418f2SJia Liu 1226bbe418f2SJia Liu case 0xb: /* l.sfgesi */ 1227bbe418f2SJia Liu LOG_DIS("l.sfgesi r%d, %d\n", ra, I16); 122884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16); 1229bbe418f2SJia Liu break; 1230bbe418f2SJia Liu 1231bbe418f2SJia Liu case 0xc: /* l.sfltsi */ 1232bbe418f2SJia Liu LOG_DIS("l.sfltsi r%d, %d\n", ra, I16); 123384775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16); 1234bbe418f2SJia Liu break; 1235bbe418f2SJia Liu 1236bbe418f2SJia Liu case 0xd: /* l.sflesi */ 1237bbe418f2SJia Liu LOG_DIS("l.sflesi r%d, %d\n", ra, I16); 123884775c43SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16); 1239bbe418f2SJia Liu break; 1240bbe418f2SJia Liu 1241bbe418f2SJia Liu default: 1242bbe418f2SJia Liu gen_illegal_exception(dc); 1243bbe418f2SJia Liu break; 1244bbe418f2SJia Liu } 1245bbe418f2SJia Liu } 1246bbe418f2SJia Liu 1247*7de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) 1248bbe418f2SJia Liu { 1249*7de9729fSRichard Henderson LOG_DIS("l.sys %d\n", a->k); 12501ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1251bbe418f2SJia Liu gen_exception(dc, EXCP_SYSCALL); 12521ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1253*7de9729fSRichard Henderson return true; 1254*7de9729fSRichard Henderson } 1255bbe418f2SJia Liu 1256*7de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) 1257*7de9729fSRichard Henderson { 1258*7de9729fSRichard Henderson LOG_DIS("l.trap %d\n", a->k); 12591ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1260bbe418f2SJia Liu gen_exception(dc, EXCP_TRAP); 12611ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1262*7de9729fSRichard Henderson return true; 1263*7de9729fSRichard Henderson } 1264bbe418f2SJia Liu 1265*7de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) 1266*7de9729fSRichard Henderson { 1267bbe418f2SJia Liu LOG_DIS("l.msync\n"); 126824fc5c0fSRichard Henderson tcg_gen_mb(TCG_MO_ALL); 1269*7de9729fSRichard Henderson return true; 1270bbe418f2SJia Liu } 1271*7de9729fSRichard Henderson 1272*7de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) 1273*7de9729fSRichard Henderson { 1274*7de9729fSRichard Henderson LOG_DIS("l.psync\n"); 1275*7de9729fSRichard Henderson return true; 1276*7de9729fSRichard Henderson } 1277*7de9729fSRichard Henderson 1278*7de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) 1279*7de9729fSRichard Henderson { 1280*7de9729fSRichard Henderson LOG_DIS("l.csync\n"); 1281*7de9729fSRichard Henderson return true; 1282bbe418f2SJia Liu } 1283bbe418f2SJia Liu 1284bbe418f2SJia Liu static void dec_float(DisasContext *dc, uint32_t insn) 1285bbe418f2SJia Liu { 1286bbe418f2SJia Liu uint32_t op0; 1287bbe418f2SJia Liu uint32_t ra, rb, rd; 1288bbe418f2SJia Liu op0 = extract32(insn, 0, 8); 1289bbe418f2SJia Liu ra = extract32(insn, 16, 5); 1290bbe418f2SJia Liu rb = extract32(insn, 11, 5); 1291bbe418f2SJia Liu rd = extract32(insn, 21, 5); 1292bbe418f2SJia Liu 1293bbe418f2SJia Liu switch (op0) { 1294bbe418f2SJia Liu case 0x00: /* lf.add.s */ 1295bbe418f2SJia Liu LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); 12966597c28dSRichard Henderson check_r0_write(rd); 1297bbe418f2SJia Liu gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 12984e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1299bbe418f2SJia Liu break; 1300bbe418f2SJia Liu 1301bbe418f2SJia Liu case 0x01: /* lf.sub.s */ 1302bbe418f2SJia Liu LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); 13036597c28dSRichard Henderson check_r0_write(rd); 1304bbe418f2SJia Liu gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13054e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1306bbe418f2SJia Liu break; 1307bbe418f2SJia Liu 1308bbe418f2SJia Liu case 0x02: /* lf.mul.s */ 1309bbe418f2SJia Liu LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); 13106597c28dSRichard Henderson check_r0_write(rd); 1311bbe418f2SJia Liu gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13124e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1313bbe418f2SJia Liu break; 1314bbe418f2SJia Liu 1315bbe418f2SJia Liu case 0x03: /* lf.div.s */ 1316bbe418f2SJia Liu LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); 13176597c28dSRichard Henderson check_r0_write(rd); 1318bbe418f2SJia Liu gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13194e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1320bbe418f2SJia Liu break; 1321bbe418f2SJia Liu 1322bbe418f2SJia Liu case 0x04: /* lf.itof.s */ 1323bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 13246597c28dSRichard Henderson check_r0_write(rd); 1325bbe418f2SJia Liu gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); 13264e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1327bbe418f2SJia Liu break; 1328bbe418f2SJia Liu 1329bbe418f2SJia Liu case 0x05: /* lf.ftoi.s */ 1330bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 13316597c28dSRichard Henderson check_r0_write(rd); 1332bbe418f2SJia Liu gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); 13334e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1334bbe418f2SJia Liu break; 1335bbe418f2SJia Liu 1336bbe418f2SJia Liu case 0x06: /* lf.rem.s */ 1337bbe418f2SJia Liu LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); 13386597c28dSRichard Henderson check_r0_write(rd); 1339bbe418f2SJia Liu gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 13404e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1341bbe418f2SJia Liu break; 1342bbe418f2SJia Liu 1343bbe418f2SJia Liu case 0x07: /* lf.madd.s */ 1344bbe418f2SJia Liu LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); 13456597c28dSRichard Henderson check_r0_write(rd); 1346762e22edSRichard Henderson gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], 1347762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 13484e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1349bbe418f2SJia Liu break; 1350bbe418f2SJia Liu 1351bbe418f2SJia Liu case 0x08: /* lf.sfeq.s */ 1352bbe418f2SJia Liu LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); 135384775c43SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13544e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1355bbe418f2SJia Liu break; 1356bbe418f2SJia Liu 1357bbe418f2SJia Liu case 0x09: /* lf.sfne.s */ 1358bbe418f2SJia Liu LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); 13594e2d3007SRichard Henderson gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13604e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 13614e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1362bbe418f2SJia Liu break; 1363bbe418f2SJia Liu 1364bbe418f2SJia Liu case 0x0a: /* lf.sfgt.s */ 1365bbe418f2SJia Liu LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); 13664e2d3007SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13674e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1368bbe418f2SJia Liu break; 1369bbe418f2SJia Liu 1370bbe418f2SJia Liu case 0x0b: /* lf.sfge.s */ 1371bbe418f2SJia Liu LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); 13724e2d3007SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 13734e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1374bbe418f2SJia Liu break; 1375bbe418f2SJia Liu 1376bbe418f2SJia Liu case 0x0c: /* lf.sflt.s */ 1377bbe418f2SJia Liu LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); 137884775c43SRichard Henderson gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13794e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1380bbe418f2SJia Liu break; 1381bbe418f2SJia Liu 1382bbe418f2SJia Liu case 0x0d: /* lf.sfle.s */ 1383bbe418f2SJia Liu LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); 138484775c43SRichard Henderson gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 13854e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1386bbe418f2SJia Liu break; 1387bbe418f2SJia Liu 13884e2d3007SRichard Henderson #ifdef TARGET_OPENRISC64 13894e2d3007SRichard Henderson case 0x10: /* lf.add.d */ 1390bbe418f2SJia Liu LOG_DIS("lf.add.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_add_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 0x11: /* lf.sub.d */ 1398bbe418f2SJia Liu LOG_DIS("lf.sub.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_sub_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 0x12: /* lf.mul.d */ 1406bbe418f2SJia Liu LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb); 1407bbe418f2SJia Liu check_of64s(dc); 14086597c28dSRichard Henderson check_r0_write(rd); 1409bbe418f2SJia Liu gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 14104e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1411bbe418f2SJia Liu break; 1412bbe418f2SJia Liu 14134e2d3007SRichard Henderson case 0x13: /* lf.div.d */ 1414bbe418f2SJia Liu LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); 1415bbe418f2SJia Liu check_of64s(dc); 14166597c28dSRichard Henderson check_r0_write(rd); 1417bbe418f2SJia Liu gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 14184e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1419bbe418f2SJia Liu break; 1420bbe418f2SJia Liu 14214e2d3007SRichard Henderson case 0x14: /* lf.itof.d */ 1422bbe418f2SJia Liu LOG_DIS("lf.itof r%d, r%d\n", rd, ra); 1423bbe418f2SJia Liu check_of64s(dc); 14246597c28dSRichard Henderson check_r0_write(rd); 1425bbe418f2SJia Liu gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); 14264e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1427bbe418f2SJia Liu break; 1428bbe418f2SJia Liu 14294e2d3007SRichard Henderson case 0x15: /* lf.ftoi.d */ 1430bbe418f2SJia Liu LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); 1431bbe418f2SJia Liu check_of64s(dc); 14326597c28dSRichard Henderson check_r0_write(rd); 1433bbe418f2SJia Liu gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); 14344e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1435bbe418f2SJia Liu break; 1436bbe418f2SJia Liu 14374e2d3007SRichard Henderson case 0x16: /* lf.rem.d */ 1438bbe418f2SJia Liu LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); 1439bbe418f2SJia Liu check_of64s(dc); 14406597c28dSRichard Henderson check_r0_write(rd); 1441bbe418f2SJia Liu gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); 14424e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1443bbe418f2SJia Liu break; 1444bbe418f2SJia Liu 14454e2d3007SRichard Henderson case 0x17: /* lf.madd.d */ 1446bbe418f2SJia Liu LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); 1447bbe418f2SJia Liu check_of64s(dc); 14486597c28dSRichard Henderson check_r0_write(rd); 1449762e22edSRichard Henderson gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], 1450762e22edSRichard Henderson cpu_R[ra], cpu_R[rb]); 14514e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1452bbe418f2SJia Liu break; 1453bbe418f2SJia Liu 14544e2d3007SRichard Henderson case 0x18: /* lf.sfeq.d */ 1455bbe418f2SJia Liu LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); 1456bbe418f2SJia Liu check_of64s(dc); 145784775c43SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14584e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1459bbe418f2SJia Liu break; 1460bbe418f2SJia Liu 14614e2d3007SRichard Henderson case 0x1a: /* lf.sfgt.d */ 1462bbe418f2SJia Liu LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); 1463bbe418f2SJia Liu check_of64s(dc); 14644e2d3007SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14654e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1466bbe418f2SJia Liu break; 1467bbe418f2SJia Liu 14684e2d3007SRichard Henderson case 0x1b: /* lf.sfge.d */ 1469bbe418f2SJia Liu LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); 1470bbe418f2SJia Liu check_of64s(dc); 14714e2d3007SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]); 14724e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1473bbe418f2SJia Liu break; 1474bbe418f2SJia Liu 14754e2d3007SRichard Henderson case 0x19: /* lf.sfne.d */ 1476bbe418f2SJia Liu LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); 1477bbe418f2SJia Liu check_of64s(dc); 14784e2d3007SRichard Henderson gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14794e2d3007SRichard Henderson tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); 14804e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1481bbe418f2SJia Liu break; 1482bbe418f2SJia Liu 14834e2d3007SRichard Henderson case 0x1c: /* lf.sflt.d */ 1484bbe418f2SJia Liu LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); 1485bbe418f2SJia Liu check_of64s(dc); 148684775c43SRichard Henderson gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14874e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1488bbe418f2SJia Liu break; 1489bbe418f2SJia Liu 14904e2d3007SRichard Henderson case 0x1d: /* lf.sfle.d */ 1491bbe418f2SJia Liu LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); 1492bbe418f2SJia Liu check_of64s(dc); 149384775c43SRichard Henderson gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); 14944e2d3007SRichard Henderson gen_helper_update_fpcsr(cpu_env); 1495bbe418f2SJia Liu break; 14964e2d3007SRichard Henderson #endif 1497bbe418f2SJia Liu 1498bbe418f2SJia Liu default: 1499bbe418f2SJia Liu gen_illegal_exception(dc); 1500bbe418f2SJia Liu break; 1501bbe418f2SJia Liu } 1502bbe418f2SJia Liu } 1503bbe418f2SJia Liu 1504bbe418f2SJia Liu static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) 1505bbe418f2SJia Liu { 1506bbe418f2SJia Liu uint32_t op0; 1507*7de9729fSRichard Henderson uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); 1508bbe418f2SJia Liu 1509*7de9729fSRichard Henderson /* Transition to the auto-generated decoder. */ 1510*7de9729fSRichard Henderson if (decode(dc, insn)) { 1511*7de9729fSRichard Henderson return; 1512*7de9729fSRichard Henderson } 1513*7de9729fSRichard Henderson 1514*7de9729fSRichard Henderson op0 = extract32(insn, 26, 6); 1515bbe418f2SJia Liu switch (op0) { 1516bbe418f2SJia Liu case 0x06: 1517bbe418f2SJia Liu dec_M(dc, insn); 1518bbe418f2SJia Liu break; 1519bbe418f2SJia Liu 1520bbe418f2SJia Liu case 0x2e: 1521bbe418f2SJia Liu dec_logic(dc, insn); 1522bbe418f2SJia Liu break; 1523bbe418f2SJia Liu 1524bbe418f2SJia Liu case 0x2f: 1525bbe418f2SJia Liu dec_compi(dc, insn); 1526bbe418f2SJia Liu break; 1527bbe418f2SJia Liu 1528bbe418f2SJia Liu case 0x31: 1529bbe418f2SJia Liu dec_mac(dc, insn); 1530bbe418f2SJia Liu break; 1531bbe418f2SJia Liu 1532bbe418f2SJia Liu case 0x32: 1533bbe418f2SJia Liu dec_float(dc, insn); 1534bbe418f2SJia Liu break; 1535bbe418f2SJia Liu 1536bbe418f2SJia Liu case 0x38: 1537bbe418f2SJia Liu dec_calc(dc, insn); 1538bbe418f2SJia Liu break; 1539bbe418f2SJia Liu 1540bbe418f2SJia Liu case 0x39: 1541bbe418f2SJia Liu dec_comp(dc, insn); 1542bbe418f2SJia Liu break; 1543bbe418f2SJia Liu 1544bbe418f2SJia Liu default: 1545bbe418f2SJia Liu dec_misc(dc, insn); 1546bbe418f2SJia Liu break; 1547bbe418f2SJia Liu } 1548bbe418f2SJia Liu } 1549bbe418f2SJia Liu 1550a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1551e67db06eSJia Liu { 1552a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcb, DisasContext, base); 15539c489ea6SLluís Vilanova CPUOpenRISCState *env = cs->env_ptr; 1554a4fd3ec3SEmilio G. Cota int bound; 1555bbe418f2SJia Liu 1556a4fd3ec3SEmilio G. Cota dc->mem_idx = cpu_mmu_index(env, false); 15571ffa4bceSEmilio G. Cota dc->tb_flags = dc->base.tb->flags; 1558a01deb36SRichard Henderson dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; 1559a4fd3ec3SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1560a4fd3ec3SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 1561190ce7fbSRichard Henderson } 1562bbe418f2SJia Liu 1563a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) 1564a4fd3ec3SEmilio G. Cota { 1565a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(db, DisasContext, base); 1566bbe418f2SJia Liu 15676597c28dSRichard Henderson /* Allow the TCG optimizer to see that R0 == 0, 15686597c28dSRichard Henderson when it's true, which is the common case. */ 15696597c28dSRichard Henderson if (dc->tb_flags & TB_FLAGS_R0_0) { 15706597c28dSRichard Henderson cpu_R[0] = tcg_const_tl(0); 15716597c28dSRichard Henderson } else { 15726597c28dSRichard Henderson cpu_R[0] = cpu_R0; 15736597c28dSRichard Henderson } 1574a4fd3ec3SEmilio G. Cota } 15756597c28dSRichard Henderson 1576a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 1577a4fd3ec3SEmilio G. Cota { 1578a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1579a4fd3ec3SEmilio G. Cota 15801ffa4bceSEmilio G. Cota tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) 1581a4fd3ec3SEmilio G. Cota | (dc->base.num_insns > 1 ? 2 : 0)); 1582a4fd3ec3SEmilio G. Cota } 1583bbe418f2SJia Liu 1584a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 1585a4fd3ec3SEmilio G. Cota const CPUBreakpoint *bp) 1586a4fd3ec3SEmilio G. Cota { 1587a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1588a4fd3ec3SEmilio G. Cota 15891ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1590b933066aSRichard Henderson gen_exception(dc, EXCP_DEBUG); 15911ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1592522a0d4eSRichard Henderson /* The address covered by the breakpoint must be included in 1593522a0d4eSRichard Henderson [tb->pc, tb->pc + tb->size) in order to for it to be 1594522a0d4eSRichard Henderson properly cleared -- thus we increment the PC here so that 1595522a0d4eSRichard Henderson the logic setting tb->size below does the right thing. */ 15961ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 1597a4fd3ec3SEmilio G. Cota return true; 1598b933066aSRichard Henderson } 1599b933066aSRichard Henderson 1600a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 1601a4fd3ec3SEmilio G. Cota { 1602a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 1603a4fd3ec3SEmilio G. Cota OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1604a4fd3ec3SEmilio G. Cota 1605bbe418f2SJia Liu disas_openrisc_insn(dc, cpu); 16061ffa4bceSEmilio G. Cota dc->base.pc_next += 4; 160724c32852SRichard Henderson 1608bbe418f2SJia Liu /* delay slot */ 1609bbe418f2SJia Liu if (dc->delayed_branch) { 1610bbe418f2SJia Liu dc->delayed_branch--; 1611bbe418f2SJia Liu if (!dc->delayed_branch) { 1612bbe418f2SJia Liu tcg_gen_mov_tl(cpu_pc, jmp_pc); 161324c32852SRichard Henderson tcg_gen_discard_tl(jmp_pc); 16141ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 1615a4fd3ec3SEmilio G. Cota return; 1616bbe418f2SJia Liu } 1617bbe418f2SJia Liu } 1618a4fd3ec3SEmilio G. Cota } 1619bbe418f2SJia Liu 1620a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 1621a4fd3ec3SEmilio G. Cota { 1622a4fd3ec3SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 162324c32852SRichard Henderson 1624a01deb36SRichard Henderson if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { 1625a01deb36SRichard Henderson tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); 1626a01deb36SRichard Henderson } 1627a01deb36SRichard Henderson 16281ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4); 16291ffa4bceSEmilio G. Cota if (dc->base.is_jmp == DISAS_NEXT) { 16301ffa4bceSEmilio G. Cota dc->base.is_jmp = DISAS_UPDATE; 16311ffa4bceSEmilio G. Cota tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); 1632bbe418f2SJia Liu } 16331ffa4bceSEmilio G. Cota if (unlikely(dc->base.singlestep_enabled)) { 1634bbe418f2SJia Liu gen_exception(dc, EXCP_DEBUG); 1635bbe418f2SJia Liu } else { 16361ffa4bceSEmilio G. Cota switch (dc->base.is_jmp) { 1637a4fd3ec3SEmilio G. Cota case DISAS_TOO_MANY: 16381ffa4bceSEmilio G. Cota gen_goto_tb(dc, 0, dc->base.pc_next); 1639bbe418f2SJia Liu break; 16401ffa4bceSEmilio G. Cota case DISAS_NORETURN: 1641bbe418f2SJia Liu case DISAS_JUMP: 16421ffa4bceSEmilio G. Cota case DISAS_TB_JUMP: 1643bbe418f2SJia Liu break; 1644bbe418f2SJia Liu case DISAS_UPDATE: 1645bbe418f2SJia Liu /* indicate that the hash table must be used 1646bbe418f2SJia Liu to find the next TB */ 1647bbe418f2SJia Liu tcg_gen_exit_tb(0); 1648bbe418f2SJia Liu break; 1649a4fd3ec3SEmilio G. Cota default: 1650a4fd3ec3SEmilio G. Cota g_assert_not_reached(); 1651a4fd3ec3SEmilio G. Cota } 1652bbe418f2SJia Liu } 1653bbe418f2SJia Liu } 1654bbe418f2SJia Liu 1655a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 1656a4fd3ec3SEmilio G. Cota { 1657a4fd3ec3SEmilio G. Cota DisasContext *s = container_of(dcbase, DisasContext, base); 16580a7df5daSRichard Henderson 1659a4fd3ec3SEmilio G. Cota qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); 1660a4fd3ec3SEmilio G. Cota log_target_disas(cs, s->base.pc_first, s->base.tb->size); 1661bbe418f2SJia Liu } 1662a4fd3ec3SEmilio G. Cota 1663a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = { 1664a4fd3ec3SEmilio G. Cota .init_disas_context = openrisc_tr_init_disas_context, 1665a4fd3ec3SEmilio G. Cota .tb_start = openrisc_tr_tb_start, 1666a4fd3ec3SEmilio G. Cota .insn_start = openrisc_tr_insn_start, 1667a4fd3ec3SEmilio G. Cota .breakpoint_check = openrisc_tr_breakpoint_check, 1668a4fd3ec3SEmilio G. Cota .translate_insn = openrisc_tr_translate_insn, 1669a4fd3ec3SEmilio G. Cota .tb_stop = openrisc_tr_tb_stop, 1670a4fd3ec3SEmilio G. Cota .disas_log = openrisc_tr_disas_log, 1671a4fd3ec3SEmilio G. Cota }; 1672a4fd3ec3SEmilio G. Cota 1673a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) 1674a4fd3ec3SEmilio G. Cota { 1675a4fd3ec3SEmilio G. Cota DisasContext ctx; 1676a4fd3ec3SEmilio G. Cota 1677a4fd3ec3SEmilio G. Cota translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb); 1678e67db06eSJia Liu } 1679e67db06eSJia Liu 1680878096eeSAndreas Färber void openrisc_cpu_dump_state(CPUState *cs, FILE *f, 1681e67db06eSJia Liu fprintf_function cpu_fprintf, 1682e67db06eSJia Liu int flags) 1683e67db06eSJia Liu { 1684878096eeSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 1685878096eeSAndreas Färber CPUOpenRISCState *env = &cpu->env; 1686e67db06eSJia Liu int i; 1687878096eeSAndreas Färber 1688e67db06eSJia Liu cpu_fprintf(f, "PC=%08x\n", env->pc); 1689e67db06eSJia Liu for (i = 0; i < 32; ++i) { 1690d89e71e8SStafford Horne cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1691e67db06eSJia Liu (i % 4) == 3 ? '\n' : ' '); 1692e67db06eSJia Liu } 1693e67db06eSJia Liu } 1694e67db06eSJia Liu 1695e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, 1696bad729e2SRichard Henderson target_ulong *data) 1697e67db06eSJia Liu { 1698bad729e2SRichard Henderson env->pc = data[0]; 1699a01deb36SRichard Henderson env->dflag = data[1] & 1; 1700a01deb36SRichard Henderson if (data[1] & 2) { 170124c32852SRichard Henderson env->ppc = env->pc - 4; 170224c32852SRichard Henderson } 1703e67db06eSJia Liu } 1704