1 /*
  2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  4  * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved.
  5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  6  *
  7  * This code is free software; you can redistribute it and/or modify it
  8  * under the terms of the GNU General Public License version 2 only, as
  9  * published by the Free Software Foundation.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 #include <stdio.h>
 27 #include <sys/types.h>
 28 
 29 #include "precompiled.hpp"
 30 #include "asm/assembler.hpp"
 31 #include "asm/assembler.inline.hpp"
 32 #include "compiler/disassembler.hpp"
 33 #include "interpreter/interpreter.hpp"
 34 #include "memory/resourceArea.hpp"
 35 #include "runtime/interfaceSupport.inline.hpp"
 36 #include "runtime/sharedRuntime.hpp"
 37 
 38 int AbstractAssembler::code_fill_byte() {
 39   return 0;
 40 }
 41 
 42 void Assembler::add(Register Rd, Register Rn, int64_t increment, Register temp) {
 43   if (is_imm_in_range(increment, 12, 0)) {
 44     addi(Rd, Rn, increment);
 45   } else {
 46     assert_different_registers(Rn, temp);
 47     li(temp, increment);
 48     add(Rd, Rn, temp);
 49   }
 50 }
 51 
 52 void Assembler::addw(Register Rd, Register Rn, int64_t increment, Register temp) {
 53   if (is_imm_in_range(increment, 12, 0)) {
 54     addiw(Rd, Rn, increment);
 55   } else {
 56     assert_different_registers(Rn, temp);
 57     li(temp, increment);
 58     addw(Rd, Rn, temp);
 59   }
 60 }
 61 
 62 void Assembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) {
 63   if (is_imm_in_range(-decrement, 12, 0)) {
 64     addi(Rd, Rn, -decrement);
 65   } else {
 66     assert_different_registers(Rn, temp);
 67     li(temp, decrement);
 68     sub(Rd, Rn, temp);
 69   }
 70 }
 71 
 72 void Assembler::subw(Register Rd, Register Rn, int64_t decrement, Register temp) {
 73   if (is_imm_in_range(-decrement, 12, 0)) {
 74     addiw(Rd, Rn, -decrement);
 75   } else {
 76     assert_different_registers(Rn, temp);
 77     li(temp, decrement);
 78     subw(Rd, Rn, temp);
 79   }
 80 }
 81 
 82 void Assembler::li(Register Rd, int64_t imm) {
 83   // int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff
 84   int shift = 12;
 85   int64_t upper = imm, lower = imm;
 86   // Split imm to a lower 12-bit sign-extended part and the remainder, because addi will sign-extend the lower imm.
 87   lower = ((int32_t)imm << 20) >> 20;
 88   upper -= lower;
 89 
 90   // Test whether imm is a 32-bit integer.
 91   if (!(((imm) & ~(int64_t)0x7fffffff) == 0 ||
 92         (((imm) & ~(int64_t)0x7fffffff) == ~(int64_t)0x7fffffff))) {
 93     while (((upper >> shift) & 1) == 0) { shift++; }
 94     upper >>= shift;
 95     li(Rd, upper);
 96     slli(Rd, Rd, shift);
 97     if (lower != 0) {
 98       addi(Rd, Rd, lower);
 99     }
100   }
101   else {
102     // 32-bit integer
103     Register hi_Rd = zr;
104     if (upper != 0) {
105       lui(Rd, (int32_t)upper);
106       hi_Rd = Rd;
107     }
108     if (lower != 0 || hi_Rd == zr) {
109       addiw(Rd, hi_Rd, lower);
110     }
111   }
112 }
113 
114 void Assembler::li64(Register Rd, int64_t imm) {
115    // Load upper 32 bits. Upper = imm[63:32], but if imm[31] = 1 or (imm[31:28] == 0x7ff && imm[19] == 1),
116    // upper = imm[63:32] + 1.
117    int64_t lower = imm & 0xffffffff;
118    lower -= ((lower << 44) >> 44);
119    int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower;
120    int32_t upper = (tmp_imm - (int32_t)lower) >> 32;
121 
122    // Load upper 32 bits
123    int64_t up = upper, lo = upper;
124    lo = (lo << 52) >> 52;
125    up -= lo;
126    up = (int32_t)up;
127    lui(Rd, up);
128    addi(Rd, Rd, lo);
129 
130    // Load the rest 32 bits.
131    slli(Rd, Rd, 12);
132    addi(Rd, Rd, (int32_t)lower >> 20);
133    slli(Rd, Rd, 12);
134    lower = ((int32_t)imm << 12) >> 20;
135    addi(Rd, Rd, lower);
136    slli(Rd, Rd, 8);
137    lower = imm & 0xff;
138    addi(Rd, Rd, lower);
139 }
140 
141 void Assembler::li32(Register Rd, int32_t imm) {
142   // int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit
143   int64_t upper = imm, lower = imm;
144   lower = (imm << 20) >> 20;
145   upper -= lower;
146   upper = (int32_t)upper;
147   // lui Rd, imm[31:12] + imm[11]
148   lui(Rd, upper);
149   // use addiw to distinguish li32 to li64
150   addiw(Rd, Rd, lower);
151 }
152 
153 #define INSN(NAME, REGISTER)                                       \
154   void Assembler::NAME(const address &dest, Register temp) {       \
155     assert_cond(dest != NULL);                                     \
156     int64_t distance = dest - pc();                                \
157     if (is_imm_in_range(distance, 20, 1)) {                        \
158       jal(REGISTER, distance);                                     \
159     } else {                                                       \
160       assert(temp != noreg, "temp must not be empty register!");   \
161       int32_t offset = 0;                                          \
162       movptr_with_offset(temp, dest, offset);                      \
163       jalr(REGISTER, temp, offset);                                \
164     }                                                              \
165   }                                                                \
166   void Assembler::NAME(Label &l, Register temp) {                  \
167     jal(REGISTER, l, temp);                                        \
168   }                                                                \
169 
170   INSN(j,   x0);
171   INSN(jal, x1);
172 
173 #undef INSN
174 
175 #define INSN(NAME, REGISTER)                                       \
176   void Assembler::NAME(Register Rs) {                              \
177     jalr(REGISTER, Rs, 0);                                         \
178   }
179 
180   INSN(jr,   x0);
181   INSN(jalr, x1);
182 
183 #undef INSN
184 
185 void Assembler::ret() {
186   jalr(x0, x1, 0);
187 }
188 
189 #define INSN(NAME, REGISTER)                                      \
190   void Assembler::NAME(const address &dest, Register temp) {      \
191     assert_cond(dest != NULL);                                    \
192     assert(temp != noreg, "temp must not be empty register!");    \
193     int64_t distance = dest - pc();                               \
194     if (is_offset_in_range(distance, 32)) {                       \
195       auipc(temp, distance + 0x800);                              \
196       jalr(REGISTER, temp, ((int32_t)distance << 20) >> 20);      \
197     } else {                                                      \
198       int32_t offset = 0;                                         \
199       movptr_with_offset(temp, dest, offset);                     \
200       jalr(REGISTER, temp, offset);                               \
201     }                                                             \
202   }
203 
204   INSN(call, x1);
205   INSN(tail, x0);
206 
207 #undef INSN
208 
209 #define INSN(NAME, REGISTER)                                   \
210   void Assembler::NAME(const Address &adr, Register temp) {    \
211     switch(adr.getMode()) {                                    \
212       case Address::literal: {                                 \
213         code_section()->relocate(pc(), adr.rspec());           \
214         NAME(adr.target(), temp);                              \
215         break;                                                 \
216       }                                                        \
217       case Address::base_plus_offset:{                         \
218         int32_t offset = 0;                                    \
219         baseOffset(temp, adr, offset);                         \
220         jalr(REGISTER, temp, offset);                          \
221         break;                                                 \
222       }                                                        \
223       default:                                                 \
224         ShouldNotReachHere();                                  \
225     }                                                          \
226   }
227 
228   INSN(j,    x0);
229   INSN(jal,  x1);
230   INSN(call, x1);
231   INSN(tail, x0);
232 
233 #undef INSN
234 
235 void Assembler::wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn,
236                            compare_and_branch_label_insn neg_insn, bool is_far) {
237   if (is_far) {
238     Label done;
239     (this->*neg_insn)(r1, r2, done, /* is_far */ false);
240     j(L);
241     bind(done);
242   } else {
243     if (L.is_bound()) {
244       (this->*insn)(r1, r2, target(L));
245     } else {
246       L.add_patch_at(code(), locator());
247       (this->*insn)(r1, r2, pc());
248     }
249   }
250 }
251 
252 void Assembler::wrap_label(Register Rt, Label &L, Register tmp, load_insn_by_temp insn) {
253   if (L.is_bound()) {
254     (this->*insn)(Rt, target(L), tmp);
255   } else {
256     L.add_patch_at(code(), locator());
257     (this->*insn)(Rt, pc(), tmp);
258   }
259 }
260 
261 void Assembler::wrap_label(Register Rt, Label &L, jal_jalr_insn insn) {
262   if (L.is_bound()) {
263     (this->*insn)(Rt, target(L));
264   } else {
265     L.add_patch_at(code(), locator());
266     (this->*insn)(Rt, pc());
267   }
268 }
269 
270 void Assembler::movptr_with_offset(Register Rd, address addr, int32_t &offset) {
271   uintptr_t imm64 = (uintptr_t)addr;
272 #ifndef PRODUCT
273   {
274     char buffer[64];
275     snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64);
276     block_comment(buffer);
277   }
278 #endif
279   assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (uintptr_t)-1), "48-bit overflow in address constant");
280   // Load upper 32 bits
281   int32_t imm = imm64 >> 16;
282   int64_t upper = imm, lower = imm;
283   lower = (lower << 52) >> 52;
284   upper -= lower;
285   upper = (int32_t)upper;
286   lui(Rd, upper);
287   addi(Rd, Rd, lower);
288 
289   // Load the rest 16 bits.
290   slli(Rd, Rd, 11);
291   addi(Rd, Rd, (imm64 >> 5) & 0x7ff);
292   slli(Rd, Rd, 5);
293 
294   // Here, remove the addi instruct and return the offset directly. This offset will be used by following jalr/ld.
295   offset = imm64 & 0x1f;
296 }
297 
298 void Assembler::movptr(Register Rd, uintptr_t imm64) {
299   movptr(Rd, (address)imm64);
300 }
301 
302 void Assembler::movptr(Register Rd, address addr) {
303   int offset = 0;
304   movptr_with_offset(Rd, addr, offset);
305   addi(Rd, Rd, offset);
306 }
307 
308 void Assembler::ifence() {
309   fence_i();
310   if (UseConservativeFence) {
311     fence(ir, ir);
312   }
313 }
314 
315 #define INSN(NAME, NEG_INSN)                                                         \
316   void Assembler::NAME(Register Rs, Register Rt, const address &dest) {              \
317     NEG_INSN(Rt, Rs, dest);                                                          \
318   }                                                                                  \
319   void Assembler::NAME(Register Rs, Register Rt, Label &l, bool is_far) {            \
320     NEG_INSN(Rt, Rs, l, is_far);                                                     \
321   }
322 
323   INSN(bgt,  blt);
324   INSN(ble,  bge);
325   INSN(bgtu, bltu);
326   INSN(bleu, bgeu);
327 #undef INSN
328 
329 #undef __
330 
331 Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) {
332   _target = target;
333   switch (rtype) {
334     case relocInfo::oop_type:
335     case relocInfo::metadata_type:
336       // Oops are a special case. Normally they would be their own section
337       // but in cases like icBuffer they are literals in the code stream that
338       // we don't have a section for. We use none so that we get a literal address
339       // which is always patchable.
340       break;
341     case relocInfo::external_word_type:
342       _rspec = external_word_Relocation::spec(target);
343       break;
344     case relocInfo::internal_word_type:
345       _rspec = internal_word_Relocation::spec(target);
346       break;
347     case relocInfo::opt_virtual_call_type:
348       _rspec = opt_virtual_call_Relocation::spec();
349       break;
350     case relocInfo::static_call_type:
351       _rspec = static_call_Relocation::spec();
352       break;
353     case relocInfo::runtime_call_type:
354       _rspec = runtime_call_Relocation::spec();
355       break;
356     case relocInfo::poll_type:
357     case relocInfo::poll_return_type:
358       _rspec = Relocation::spec_simple(rtype);
359       break;
360     case relocInfo::none:
361       _rspec = RelocationHolder::none;
362       break;
363     default:
364       ShouldNotReachHere();
365   }
366 }
367