1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (c) 2021 Loongson Technology Corporation Limited
4 */
5
6static void maybe_nanbox_load(TCGv freg, MemOp mop)
7{
8    if ((mop & MO_SIZE) == MO_32) {
9        gen_nanbox_s(freg, freg);
10    }
11}
12
13static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
14{
15    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
16    TCGv temp = NULL;
17
18    CHECK_FPE;
19
20    if (a->imm) {
21        temp = tcg_temp_new();
22        tcg_gen_addi_tl(temp, addr, a->imm);
23        addr = temp;
24    }
25
26    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
27    maybe_nanbox_load(cpu_fpr[a->fd], mop);
28
29    if (temp) {
30        tcg_temp_free(temp);
31    }
32
33    return true;
34}
35
36static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
37{
38    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
39    TCGv temp = NULL;
40
41    CHECK_FPE;
42
43    if (a->imm) {
44        temp = tcg_temp_new();
45        tcg_gen_addi_tl(temp, addr, a->imm);
46        addr = temp;
47    }
48
49    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
50
51    if (temp) {
52        tcg_temp_free(temp);
53    }
54    return true;
55}
56
57static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
58{
59    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
60    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
61    TCGv addr;
62
63    CHECK_FPE;
64
65    addr = tcg_temp_new();
66    tcg_gen_add_tl(addr, src1, src2);
67    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
68    maybe_nanbox_load(cpu_fpr[a->fd], mop);
69    tcg_temp_free(addr);
70
71    return true;
72}
73
74static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
75{
76    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
77    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
78    TCGv addr;
79
80    CHECK_FPE;
81
82    addr = tcg_temp_new();
83    tcg_gen_add_tl(addr, src1, src2);
84    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
85    tcg_temp_free(addr);
86
87    return true;
88}
89
90static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
91{
92    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
93    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
94    TCGv addr;
95
96    CHECK_FPE;
97
98    addr = tcg_temp_new();
99    gen_helper_asrtgt_d(cpu_env, src1, src2);
100    tcg_gen_add_tl(addr, src1, src2);
101    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
102    maybe_nanbox_load(cpu_fpr[a->fd], mop);
103    tcg_temp_free(addr);
104
105    return true;
106}
107
108static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
109{
110    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
111    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
112    TCGv addr;
113
114    CHECK_FPE;
115
116    addr = tcg_temp_new();
117    gen_helper_asrtgt_d(cpu_env, src1, src2);
118    tcg_gen_add_tl(addr, src1, src2);
119    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
120    tcg_temp_free(addr);
121
122    return true;
123}
124
125static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
126{
127    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
128    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
129    TCGv addr;
130
131    CHECK_FPE;
132
133    addr = tcg_temp_new();
134    gen_helper_asrtle_d(cpu_env, src1, src2);
135    tcg_gen_add_tl(addr, src1, src2);
136    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
137    maybe_nanbox_load(cpu_fpr[a->fd], mop);
138    tcg_temp_free(addr);
139
140    return true;
141}
142
143static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
144{
145    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
146    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
147    TCGv addr;
148
149    CHECK_FPE;
150
151    addr = tcg_temp_new();
152    gen_helper_asrtle_d(cpu_env, src1, src2);
153    tcg_gen_add_tl(addr, src1, src2);
154    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
155    tcg_temp_free(addr);
156
157    return true;
158}
159
160TRANS(fld_s, gen_fload_i, MO_TEUL)
161TRANS(fst_s, gen_fstore_i, MO_TEUL)
162TRANS(fld_d, gen_fload_i, MO_TEUQ)
163TRANS(fst_d, gen_fstore_i, MO_TEUQ)
164TRANS(fldx_s, gen_floadx, MO_TEUL)
165TRANS(fldx_d, gen_floadx, MO_TEUQ)
166TRANS(fstx_s, gen_fstorex, MO_TEUL)
167TRANS(fstx_d, gen_fstorex, MO_TEUQ)
168TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
169TRANS(fldgt_d, gen_fload_gt, MO_TEUQ)
170TRANS(fldle_s, gen_fload_le, MO_TEUL)
171TRANS(fldle_d, gen_fload_le, MO_TEUQ)
172TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
173TRANS(fstgt_d, gen_fstore_gt, MO_TEUQ)
174TRANS(fstle_s, gen_fstore_le, MO_TEUL)
175TRANS(fstle_d, gen_fstore_le, MO_TEUQ)
176