1 /* 2 * MIPS Loongson 64-bit translation routines 3 * 4 * Copyright (c) 2004-2005 Jocelyn Mayer 5 * Copyright (c) 2006 Marius Groeger (FPU operations) 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) 7 * Copyright (c) 2011 Richard Henderson <rth@twiddle.net> 8 * Copyright (c) 2021 Philippe Mathieu-Daudé 9 * 10 * This code is licensed under the GNU GPLv2 and later. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "translate.h" 15 16 /* Include the auto-generated decoder. */ 17 #include "decode-godson2.c.inc" 18 #include "decode-loong-ext.c.inc" 19 20 /* 21 * Word or double-word Fixed-point instructions. 22 * --------------------------------------------- 23 * 24 * Fixed-point multiplies and divisions write only 25 * one result into general-purpose registers. 26 */ 27 28 static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt, 29 bool is_double) 30 { 31 TCGv t0, t1; 32 TCGLabel *l1, *l2, *l3; 33 34 if (is_double) { 35 if (TARGET_LONG_BITS != 64) { 36 return false; 37 } 38 check_mips_64(s); 39 } 40 41 if (rd == 0) { 42 /* Treat as NOP. */ 43 return true; 44 } 45 46 t0 = tcg_temp_new(); 47 t1 = tcg_temp_new(); 48 l1 = gen_new_label(); 49 l2 = gen_new_label(); 50 l3 = gen_new_label(); 51 52 gen_load_gpr(t0, rs); 53 gen_load_gpr(t1, rt); 54 55 if (!is_double) { 56 tcg_gen_ext32s_tl(t0, t0); 57 tcg_gen_ext32s_tl(t1, t1); 58 } 59 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); 60 tcg_gen_movi_tl(cpu_gpr[rd], 0); 61 tcg_gen_br(l3); 62 gen_set_label(l1); 63 64 tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double && TARGET_LONG_BITS == 64 65 ? LLONG_MIN : INT_MIN, l2); 66 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); 67 tcg_gen_mov_tl(cpu_gpr[rd], t0); 68 69 tcg_gen_br(l3); 70 gen_set_label(l2); 71 tcg_gen_div_tl(cpu_gpr[rd], t0, t1); 72 if (!is_double) { 73 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); 74 } 75 gen_set_label(l3); 76 77 return true; 78 } 79 80 static bool trans_DIV_G(DisasContext *s, arg_muldiv *a) 81 { 82 return gen_lext_DIV_G(s, a->rd, a->rs, a->rt, false); 83 } 84 85 static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a) 86 { 87 return gen_lext_DIV_G(s, a->rd, a->rs, a->rt, true); 88 } 89 90 bool decode_ext_loongson(DisasContext *ctx, uint32_t insn) 91 { 92 if (!decode_64bit_enabled(ctx)) { 93 return false; 94 } 95 if ((ctx->insn_flags & INSN_LOONGSON2E) && decode_godson2(ctx, ctx->opcode)) { 96 return true; 97 } 98 if ((ctx->insn_flags & ASE_LEXT) && decode_loong_ext(ctx, ctx->opcode)) { 99 return true; 100 } 101 return false; 102 } 103