1 /* 2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "asm/assembler.hpp" 28 #include "c1/c1_LIRAssembler.hpp" 29 #include "c1/c1_MacroAssembler.hpp" 30 31 #ifndef PRODUCT 32 #define COMMENT(x) do { __ block_comment(x); } while (0) 33 #else 34 #define COMMENT(x) 35 #endif 36 37 #define __ _masm-> 38 39 void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr illegal, 40 LIR_Opr result, CodeEmitInfo* info) { 41 // opcode check 42 assert((code == lir_idiv) || (code == lir_irem), "opcode must be idiv or irem"); 43 bool is_irem = (code == lir_irem); 44 // opreand check 45 assert(left->is_single_cpu(), "left must be a register"); 46 assert(right->is_single_cpu() || right->is_constant(), "right must be a register or constant"); 47 assert(result->is_single_cpu(), "result must be a register"); 48 Register lreg = left->as_register(); 49 Register dreg = result->as_register(); 50 51 // power-of-2 constant check and codegen 52 if (right->is_constant()) { 53 int c = right->as_constant_ptr()->as_jint(); 54 assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); 55 if (is_irem) { 56 if (c == 1) { 57 // move 0 to dreg if divisor is 1 58 __ mv(dreg, zr); 59 } else { 60 unsigned int shift = exact_log2(c); 61 __ sraiw(t0, lreg, 0x1f); 62 __ srliw(t0, t0, BitsPerInt - shift); 63 __ addw(t1, lreg, t0); 64 if (is_imm_in_range(c - 1, 12, 0)) { 65 __ andi(t1, t1, c - 1); 66 } else { 67 __ zero_extend(t1, t1, shift); 68 } 69 __ subw(dreg, t1, t0); 70 } 71 } else { 72 if (c == 1) { 73 // move lreg to dreg if divisor is 1 74 __ mv(dreg, lreg); 75 } else { 76 unsigned int shift = exact_log2(c); 77 __ sraiw(t0, lreg, 0x1f); 78 if (is_imm_in_range(c - 1, 12, 0)) { 79 __ andi(t0, t0, c - 1); 80 } else { 81 __ zero_extend(t0, t0, shift); 82 } 83 __ addw(dreg, t0, lreg); 84 __ sraiw(dreg, dreg, shift); 85 } 86 } 87 } else { 88 Register rreg = right->as_register(); 89 __ corrected_idivl(dreg, lreg, rreg, is_irem); 90 } 91 } 92 93 void LIR_Assembler::arith_op_single_cpu_right_constant(LIR_Code code, LIR_Opr left, LIR_Opr right, 94 Register lreg, Register dreg) { 95 // cpu register - constant 96 jlong c; 97 98 switch (right->type()) { 99 case T_LONG: 100 c = right->as_constant_ptr()->as_jlong(); break; 101 case T_INT: // fall through 102 case T_ADDRESS: 103 c = right->as_constant_ptr()->as_jint(); break; 104 default: 105 ShouldNotReachHere(); 106 c = 0; // unreachable 107 } 108 109 assert(code == lir_add || code == lir_sub, "mismatched arithmetic op"); 110 if (c == 0 && dreg == lreg) { 111 COMMENT("effective nop elided"); 112 return; 113 } 114 switch (left->type()) { 115 case T_INT: 116 switch (code) { 117 case lir_add: __ addw(dreg, lreg, c); break; 118 case lir_sub: __ subw(dreg, lreg, c); break; 119 default: ShouldNotReachHere(); 120 } 121 break; 122 case T_OBJECT: // fall through 123 case T_ADDRESS: 124 switch (code) { 125 case lir_add: __ add(dreg, lreg, c); break; 126 case lir_sub: __ sub(dreg, lreg, c); break; 127 default: ShouldNotReachHere(); 128 } 129 break; 130 default: 131 ShouldNotReachHere(); 132 } 133 } 134 135 void LIR_Assembler::arith_op_single_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { 136 Register lreg = left->as_register(); 137 Register dreg = as_reg(dest); 138 139 if (right->is_single_cpu()) { 140 // cpu register - cpu register 141 assert(left->type() == T_INT && right->type() == T_INT && dest->type() == T_INT, "should be"); 142 Register rreg = right->as_register(); 143 switch (code) { 144 case lir_add: __ addw(dest->as_register(), lreg, rreg); break; 145 case lir_sub: __ subw(dest->as_register(), lreg, rreg); break; 146 case lir_mul: __ mulw(dest->as_register(), lreg, rreg); break; 147 default: ShouldNotReachHere(); 148 } 149 } else if (right->is_double_cpu()) { 150 Register rreg = right->as_register_lo(); 151 // sigle_cpu + double_cpu; can happen with obj_long 152 assert(code == lir_add || code == lir_sub, "mismatched arithmetic op"); 153 switch (code) { 154 case lir_add: __ add(dreg, lreg, rreg); break; 155 case lir_sub: __ sub(dreg, lreg, rreg); break; 156 default: ShouldNotReachHere(); 157 } 158 } else if (right->is_constant()) { 159 arith_op_single_cpu_right_constant(code, left, right, lreg, dreg); 160 } else { 161 ShouldNotReachHere(); 162 } 163 } 164 165 void LIR_Assembler::arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { 166 Register lreg_lo = left->as_register_lo(); 167 168 if (right->is_double_cpu()) { 169 // cpu register - cpu register 170 Register rreg_lo = right->as_register_lo(); 171 switch (code) { 172 case lir_add: __ add(dest->as_register_lo(), lreg_lo, rreg_lo); break; 173 case lir_sub: __ sub(dest->as_register_lo(), lreg_lo, rreg_lo); break; 174 case lir_mul: __ mul(dest->as_register_lo(), lreg_lo, rreg_lo); break; 175 case lir_div: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo, false); break; 176 case lir_rem: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo, true); break; 177 default: 178 ShouldNotReachHere(); 179 } 180 } else if (right->is_constant()) { 181 jlong c = right->as_constant_ptr()->as_jlong(); 182 Register dreg = as_reg(dest); 183 switch (code) { 184 case lir_add: // fall through 185 case lir_sub: 186 if (c == 0 && dreg == lreg_lo) { 187 COMMENT("effective nop elided"); 188 return; 189 } 190 code == lir_add ? __ add(dreg, lreg_lo, c) : __ sub(dreg, lreg_lo, c); 191 break; 192 case lir_div: 193 assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); 194 if (c == 1) { 195 // move lreg_lo to dreg if divisor is 1 196 __ mv(dreg, lreg_lo); 197 } else { 198 unsigned int shift = exact_log2_long(c); 199 // use t0 as intermediate result register 200 __ srai(t0, lreg_lo, 0x3f); 201 if (is_imm_in_range(c - 1, 12, 0)) { 202 __ andi(t0, t0, c - 1); 203 } else { 204 __ zero_extend(t0, t0, shift); 205 } 206 __ add(dreg, t0, lreg_lo); 207 __ srai(dreg, dreg, shift); 208 } 209 break; 210 case lir_rem: 211 assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); 212 if (c == 1) { 213 // move 0 to dreg if divisor is 1 214 __ mv(dreg, zr); 215 } else { 216 unsigned int shift = exact_log2_long(c); 217 __ srai(t0, lreg_lo, 0x3f); 218 __ srli(t0, t0, BitsPerLong - shift); 219 __ add(t1, lreg_lo, t0); 220 if (is_imm_in_range(c - 1, 12, 0)) { 221 __ andi(t1, t1, c - 1); 222 } else { 223 __ zero_extend(t1, t1, shift); 224 } 225 __ sub(dreg, t1, t0); 226 } 227 break; 228 default: 229 ShouldNotReachHere(); 230 } 231 } else { 232 ShouldNotReachHere(); 233 } 234 } 235 236 void LIR_Assembler::arith_op_single_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { 237 assert(right->is_single_fpu(), "right hand side of float arithmetics needs to be float register"); 238 switch (code) { 239 case lir_add: __ fadd_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; 240 case lir_sub: __ fsub_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; 241 case lir_mul: __ fmul_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; 242 case lir_div: __ fdiv_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; 243 default: 244 ShouldNotReachHere(); 245 } 246 } 247 248 void LIR_Assembler::arith_op_double_fpu(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) { 249 if (right->is_double_fpu()) { 250 // fpu register - fpu register 251 switch (code) { 252 case lir_add: __ fadd_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; 253 case lir_sub: __ fsub_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; 254 case lir_mul: __ fmul_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; 255 case lir_div: __ fdiv_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; 256 default: 257 ShouldNotReachHere(); 258 } 259 } else { 260 ShouldNotReachHere(); 261 } 262 } 263 264 void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, 265 CodeEmitInfo* info, bool pop_fpu_stack) { 266 assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); 267 268 if (left->is_single_cpu()) { 269 arith_op_single_cpu(code, left, right, dest); 270 } else if (left->is_double_cpu()) { 271 arith_op_double_cpu(code, left, right, dest); 272 } else if (left->is_single_fpu()) { 273 arith_op_single_fpu(code, left, right, dest); 274 } else if (left->is_double_fpu()) { 275 arith_op_double_fpu(code, left, right, dest); 276 } else { 277 ShouldNotReachHere(); 278 } 279 } 280 281 #undef __