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    if (a->imm) {
19        temp = tcg_temp_new();
20        tcg_gen_addi_tl(temp, addr, a->imm);
21        addr = temp;
22    }
23
24    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
25    maybe_nanbox_load(cpu_fpr[a->fd], mop);
26
27    if (temp) {
28        tcg_temp_free(temp);
29    }
30
31    return true;
32}
33
34static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
35{
36    TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
37    TCGv temp = NULL;
38
39    if (a->imm) {
40        temp = tcg_temp_new();
41        tcg_gen_addi_tl(temp, addr, a->imm);
42        addr = temp;
43    }
44
45    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
46
47    if (temp) {
48        tcg_temp_free(temp);
49    }
50    return true;
51}
52
53static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
54{
55    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
56    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
57    TCGv addr = tcg_temp_new();
58
59    tcg_gen_add_tl(addr, src1, src2);
60    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
61    maybe_nanbox_load(cpu_fpr[a->fd], mop);
62    tcg_temp_free(addr);
63
64    return true;
65}
66
67static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
68{
69    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
70    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
71    TCGv addr = tcg_temp_new();
72
73    tcg_gen_add_tl(addr, src1, src2);
74    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
75    tcg_temp_free(addr);
76
77    return true;
78}
79
80static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
81{
82    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
83    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
84    TCGv addr = tcg_temp_new();
85
86    gen_helper_asrtgt_d(cpu_env, src1, src2);
87    tcg_gen_add_tl(addr, src1, src2);
88    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
89    maybe_nanbox_load(cpu_fpr[a->fd], mop);
90    tcg_temp_free(addr);
91
92    return true;
93}
94
95static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
96{
97    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
98    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
99    TCGv addr = tcg_temp_new();
100
101    gen_helper_asrtgt_d(cpu_env, src1, src2);
102    tcg_gen_add_tl(addr, src1, src2);
103    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
104    tcg_temp_free(addr);
105
106    return true;
107}
108
109static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
110{
111    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
112    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
113    TCGv addr = tcg_temp_new();
114
115    gen_helper_asrtle_d(cpu_env, src1, src2);
116    tcg_gen_add_tl(addr, src1, src2);
117    tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
118    maybe_nanbox_load(cpu_fpr[a->fd], mop);
119    tcg_temp_free(addr);
120
121    return true;
122}
123
124static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
125{
126    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
127    TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
128    TCGv addr = tcg_temp_new();
129
130    gen_helper_asrtle_d(cpu_env, src1, src2);
131    tcg_gen_add_tl(addr, src1, src2);
132    tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
133    tcg_temp_free(addr);
134
135    return true;
136}
137
138TRANS(fld_s, gen_fload_i, MO_TEUL)
139TRANS(fst_s, gen_fstore_i, MO_TEUL)
140TRANS(fld_d, gen_fload_i, MO_TEUQ)
141TRANS(fst_d, gen_fstore_i, MO_TEUQ)
142TRANS(fldx_s, gen_floadx, MO_TEUL)
143TRANS(fldx_d, gen_floadx, MO_TEUQ)
144TRANS(fstx_s, gen_fstorex, MO_TEUL)
145TRANS(fstx_d, gen_fstorex, MO_TEUQ)
146TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
147TRANS(fldgt_d, gen_fload_gt, MO_TEUQ)
148TRANS(fldle_s, gen_fload_le, MO_TEUL)
149TRANS(fldle_d, gen_fload_le, MO_TEUQ)
150TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
151TRANS(fstgt_d, gen_fstore_gt, MO_TEUQ)
152TRANS(fstle_s, gen_fstore_le, MO_TEUL)
153TRANS(fstle_d, gen_fstore_le, MO_TEUQ)
154