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 bool trans_mulh(DisasContext *ctx, arg_mulh *a) 29{ 30 REQUIRE_EXT(ctx, RVM); 31 TCGv source1 = tcg_temp_new(); 32 TCGv source2 = tcg_temp_new(); 33 gen_get_gpr(ctx, source1, a->rs1); 34 gen_get_gpr(ctx, source2, a->rs2); 35 36 tcg_gen_muls2_tl(source2, source1, source1, source2); 37 38 gen_set_gpr(ctx, a->rd, source1); 39 tcg_temp_free(source1); 40 tcg_temp_free(source2); 41 return true; 42} 43 44static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) 45{ 46 REQUIRE_EXT(ctx, RVM); 47 return gen_arith(ctx, a, EXT_NONE, gen_mulhsu); 48} 49 50static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) 51{ 52 REQUIRE_EXT(ctx, RVM); 53 TCGv source1 = tcg_temp_new(); 54 TCGv source2 = tcg_temp_new(); 55 gen_get_gpr(ctx, source1, a->rs1); 56 gen_get_gpr(ctx, source2, a->rs2); 57 58 tcg_gen_mulu2_tl(source2, source1, source1, source2); 59 60 gen_set_gpr(ctx, a->rd, source1); 61 tcg_temp_free(source1); 62 tcg_temp_free(source2); 63 return true; 64} 65 66static bool trans_div(DisasContext *ctx, arg_div *a) 67{ 68 REQUIRE_EXT(ctx, RVM); 69 return gen_arith(ctx, a, EXT_SIGN, gen_div); 70} 71 72static bool trans_divu(DisasContext *ctx, arg_divu *a) 73{ 74 REQUIRE_EXT(ctx, RVM); 75 return gen_arith(ctx, a, EXT_ZERO, gen_divu); 76} 77 78static bool trans_rem(DisasContext *ctx, arg_rem *a) 79{ 80 REQUIRE_EXT(ctx, RVM); 81 return gen_arith(ctx, a, EXT_SIGN, gen_rem); 82} 83 84static bool trans_remu(DisasContext *ctx, arg_remu *a) 85{ 86 REQUIRE_EXT(ctx, RVM); 87 return gen_arith(ctx, a, EXT_ZERO, gen_remu); 88} 89 90static bool trans_mulw(DisasContext *ctx, arg_mulw *a) 91{ 92 REQUIRE_64BIT(ctx); 93 REQUIRE_EXT(ctx, RVM); 94 ctx->w = true; 95 return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); 96} 97 98static bool trans_divw(DisasContext *ctx, arg_divw *a) 99{ 100 REQUIRE_64BIT(ctx); 101 REQUIRE_EXT(ctx, RVM); 102 ctx->w = true; 103 return gen_arith(ctx, a, EXT_SIGN, gen_div); 104} 105 106static bool trans_divuw(DisasContext *ctx, arg_divuw *a) 107{ 108 REQUIRE_64BIT(ctx); 109 REQUIRE_EXT(ctx, RVM); 110 ctx->w = true; 111 return gen_arith(ctx, a, EXT_ZERO, gen_divu); 112} 113 114static bool trans_remw(DisasContext *ctx, arg_remw *a) 115{ 116 REQUIRE_64BIT(ctx); 117 REQUIRE_EXT(ctx, RVM); 118 ctx->w = true; 119 return gen_arith(ctx, a, EXT_SIGN, gen_rem); 120} 121 122static bool trans_remuw(DisasContext *ctx, arg_remuw *a) 123{ 124 REQUIRE_64BIT(ctx); 125 REQUIRE_EXT(ctx, RVM); 126 ctx->w = true; 127 return gen_arith(ctx, a, EXT_ZERO, gen_remu); 128} 129