1/*
2 * RISC-V translation routines for the RV64M Standard Extension.
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
6 *                    Bastian Koppelmann, kbastian@mail.uni-paderborn.de
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22static bool trans_mul(DisasContext *ctx, arg_mul *a)
23{
24    REQUIRE_EXT(ctx, RVM);
25    return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
26}
27
28static void gen_mulh(TCGv ret, TCGv s1, TCGv s2)
29{
30    TCGv discard = tcg_temp_new();
31
32    tcg_gen_muls2_tl(discard, ret, s1, s2);
33    tcg_temp_free(discard);
34}
35
36static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
37{
38    REQUIRE_EXT(ctx, RVM);
39    return gen_arith(ctx, a, EXT_NONE, gen_mulh);
40}
41
42static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
43{
44    REQUIRE_EXT(ctx, RVM);
45    return gen_arith(ctx, a, EXT_NONE, gen_mulhsu);
46}
47
48static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
49{
50    TCGv discard = tcg_temp_new();
51
52    tcg_gen_mulu2_tl(discard, ret, s1, s2);
53    tcg_temp_free(discard);
54}
55
56static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
57{
58    REQUIRE_EXT(ctx, RVM);
59    return gen_arith(ctx, a, EXT_NONE, gen_mulhu);
60}
61
62static bool trans_div(DisasContext *ctx, arg_div *a)
63{
64    REQUIRE_EXT(ctx, RVM);
65    return gen_arith(ctx, a, EXT_SIGN, gen_div);
66}
67
68static bool trans_divu(DisasContext *ctx, arg_divu *a)
69{
70    REQUIRE_EXT(ctx, RVM);
71    return gen_arith(ctx, a, EXT_ZERO, gen_divu);
72}
73
74static bool trans_rem(DisasContext *ctx, arg_rem *a)
75{
76    REQUIRE_EXT(ctx, RVM);
77    return gen_arith(ctx, a, EXT_SIGN, gen_rem);
78}
79
80static bool trans_remu(DisasContext *ctx, arg_remu *a)
81{
82    REQUIRE_EXT(ctx, RVM);
83    return gen_arith(ctx, a, EXT_ZERO, gen_remu);
84}
85
86static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
87{
88    REQUIRE_64BIT(ctx);
89    REQUIRE_EXT(ctx, RVM);
90    ctx->w = true;
91    return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
92}
93
94static bool trans_divw(DisasContext *ctx, arg_divw *a)
95{
96    REQUIRE_64BIT(ctx);
97    REQUIRE_EXT(ctx, RVM);
98    ctx->w = true;
99    return gen_arith(ctx, a, EXT_SIGN, gen_div);
100}
101
102static bool trans_divuw(DisasContext *ctx, arg_divuw *a)
103{
104    REQUIRE_64BIT(ctx);
105    REQUIRE_EXT(ctx, RVM);
106    ctx->w = true;
107    return gen_arith(ctx, a, EXT_ZERO, gen_divu);
108}
109
110static bool trans_remw(DisasContext *ctx, arg_remw *a)
111{
112    REQUIRE_64BIT(ctx);
113    REQUIRE_EXT(ctx, RVM);
114    ctx->w = true;
115    return gen_arith(ctx, a, EXT_SIGN, gen_rem);
116}
117
118static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
119{
120    REQUIRE_64BIT(ctx);
121    REQUIRE_EXT(ctx, RVM);
122    ctx->w = true;
123    return gen_arith(ctx, a, EXT_ZERO, gen_remu);
124}
125