]> Git Repo - qemu.git/blob - target/loongarch/insn_trans/trans_fmov.c.inc
target/loongarch: Add floating point move instruction translation
[qemu.git] / target / loongarch / insn_trans / trans_fmov.c.inc
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (c) 2021 Loongson Technology Corporation Limited
4  */
5
6 static const uint32_t fcsr_mask[4] = {
7     UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3
8 };
9
10 static bool trans_fsel(DisasContext *ctx, arg_fsel *a)
11 {
12     TCGv zero = tcg_constant_tl(0);
13     TCGv cond = tcg_temp_new();
14
15     tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca]));
16     tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero,
17                        cpu_fpr[a->fj], cpu_fpr[a->fk]);
18     tcg_temp_free(cond);
19
20     return true;
21 }
22
23 static bool gen_f2f(DisasContext *ctx, arg_ff *a,
24                     void (*func)(TCGv, TCGv), bool nanbox)
25 {
26     TCGv dest = cpu_fpr[a->fd];
27     TCGv src = cpu_fpr[a->fj];
28
29     func(dest, src);
30     if (nanbox) {
31         gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
32     }
33
34     return true;
35 }
36
37 static bool gen_r2f(DisasContext *ctx, arg_fr *a,
38                     void (*func)(TCGv, TCGv))
39 {
40     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
41
42     func(cpu_fpr[a->fd], src);
43     return true;
44 }
45
46 static bool gen_f2r(DisasContext *ctx, arg_rf *a,
47                     void (*func)(TCGv, TCGv))
48 {
49     TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
50
51     func(dest, cpu_fpr[a->fj]);
52     gen_set_gpr(a->rd, dest, EXT_NONE);
53
54     return true;
55 }
56
57 static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a)
58 {
59     uint32_t mask = fcsr_mask[a->fcsrd];
60     TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE);
61
62     if (mask == UINT32_MAX) {
63         tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj);
64     } else {
65         TCGv_i32 temp = tcg_temp_new_i32();
66
67         tcg_gen_extrl_i64_i32(temp, Rj);
68         tcg_gen_andi_i32(temp, temp, mask);
69         tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask);
70         tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp);
71         tcg_temp_free_i32(temp);
72
73         /*
74          * Install the new rounding mode to fpu_status, if changed.
75          * Note that FCSR3 is exactly the rounding mode field.
76          */
77         if (mask != FCSR0_M3) {
78             return true;
79         }
80     }
81     gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0);
82
83     return true;
84 }
85
86 static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a)
87 {
88     TCGv_i32 temp = tcg_temp_new_i32();
89     TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
90
91     tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]);
92     tcg_gen_ext_i32_i64(dest, temp);
93     gen_set_gpr(a->rd, dest, EXT_NONE);
94     tcg_temp_free_i32(temp);
95
96     return true;
97 }
98
99 static void gen_movgr2fr_w(TCGv dest, TCGv src)
100 {
101     tcg_gen_deposit_i64(dest, dest, src, 0, 32);
102 }
103
104 static void gen_movgr2frh_w(TCGv dest, TCGv src)
105 {
106     tcg_gen_deposit_i64(dest, dest, src, 32, 32);
107 }
108
109 static void gen_movfrh2gr_s(TCGv dest, TCGv src)
110 {
111     tcg_gen_sextract_tl(dest, src, 32, 32);
112 }
113
114 static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a)
115 {
116     TCGv t0 = tcg_temp_new();
117
118     tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1);
119     tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7]));
120     tcg_temp_free(t0);
121
122     return true;
123 }
124
125 static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a)
126 {
127     tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_env,
128                     offsetof(CPULoongArchState, cf[a->cj & 0x7]));
129     return true;
130 }
131
132 static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a)
133 {
134     TCGv t0 = tcg_temp_new();
135
136     tcg_gen_andi_tl(t0, gpr_src(ctx, a->rj, EXT_NONE), 0x1);
137     tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7]));
138     tcg_temp_free(t0);
139
140     return true;
141 }
142
143 static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a)
144 {
145     tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd, EXT_NONE), cpu_env,
146                     offsetof(CPULoongArchState, cf[a->cj & 0x7]));
147     return true;
148 }
149
150 TRANS(fmov_s, gen_f2f, tcg_gen_mov_tl, true)
151 TRANS(fmov_d, gen_f2f, tcg_gen_mov_tl, false)
152 TRANS(movgr2fr_w, gen_r2f, gen_movgr2fr_w)
153 TRANS(movgr2fr_d, gen_r2f, tcg_gen_mov_tl)
154 TRANS(movgr2frh_w, gen_r2f, gen_movgr2frh_w)
155 TRANS(movfr2gr_s, gen_f2r, tcg_gen_ext32s_tl)
156 TRANS(movfr2gr_d, gen_f2r, tcg_gen_mov_tl)
157 TRANS(movfrh2gr_s, gen_f2r, gen_movfrh2gr_s)
This page took 0.032521 seconds and 4 git commands to generate.