v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-loong64.h
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_CODEGEN_LOONG64_ASSEMBLER_LOONG64_H_
6#define V8_CODEGEN_LOONG64_ASSEMBLER_LOONG64_H_
7
8#include <stdio.h>
9
10#include <memory>
11#include <set>
12
15#include "src/codegen/label.h"
20#include "src/objects/smi.h"
21
22namespace v8 {
23namespace internal {
24
25class SafepointTableBuilder;
26
27// -----------------------------------------------------------------------------
28// Machine instruction Operands.
29constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
30constexpr uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
31// Class Operand represents a shifter operand in data processing instructions.
32class Operand {
33 public:
34 // Immediate.
41 : rm_(no_reg), rmode_(RelocInfo::EXTERNAL_REFERENCE) {
42 value_.immediate = static_cast<int64_t>(f.address());
43 }
45 : Operand(static_cast<intptr_t>(value.ptr())) {}
46
48
49 static Operand EmbeddedNumber(double number); // Smi or HeapNumber.
50
51 // Register.
53
54 // Return true if this is a register operand.
55 V8_INLINE bool is_reg() const;
56
57 inline int64_t immediate() const;
58
59 bool IsImmediate() const { return !rm_.is_valid(); }
60
65
73
74 Register rm() const { return rm_; }
75
76 RelocInfo::Mode rmode() const { return rmode_; }
77
78 private:
80 union Value {
81 Value() {}
82 HeapNumberRequest heap_number_request; // if is_heap_number_request_
83 int64_t immediate; // otherwise
84 } value_; // valid if rm_ == no_reg
85 bool is_heap_number_request_ = false;
87
88 friend class Assembler;
89 friend class MacroAssembler;
90};
91
92// Class MemOperand represents a memory operand in load and store instructions.
93// 1: base_reg + off_imm( si12 | si14<<2)
94// 2: base_reg + offset_reg
96 public:
97 explicit MemOperand(Register rj, int32_t offset = 0);
98 explicit MemOperand(Register rj, Register offset = no_reg);
99 Register base() const { return base_; }
100 Register index() const { return index_; }
101 int32_t offset() const { return offset_; }
102
103 bool hasIndexReg() const { return index_ != no_reg; }
104
105 private:
106 Register base_; // base
107 Register index_; // index
108 int32_t offset_; // offset
109
110 friend class Assembler;
111};
112
114 public:
115 // Create an assembler. Instructions and relocation information are emitted
116 // into a buffer, with the instructions starting from the beginning and the
117 // relocation information starting from the end of the buffer. See CodeDesc
118 // for a detailed comment on the layout (globals.h).
119 //
120 // If the provided buffer is nullptr, the assembler allocates and grows its
121 // own buffer. Otherwise it takes ownership of the provided buffer.
123 std::unique_ptr<AssemblerBuffer> = {});
124 // For compatibility with assemblers that require a zone.
126 std::unique_ptr<AssemblerBuffer> buffer = {})
127 : Assembler(options, std::move(buffer)) {}
128
129 virtual ~Assembler() {}
130
131 // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
132 static constexpr int kNoHandlerTable = 0;
133 static constexpr SafepointTableBuilderBase* kNoSafepointTable = nullptr;
134 void GetCode(LocalIsolate* isolate, CodeDesc* desc,
135 SafepointTableBuilderBase* safepoint_table_builder,
136 int handler_table_offset);
137
138 // Convenience wrapper for allocating with an Isolate.
139 void GetCode(Isolate* isolate, CodeDesc* desc);
140 // Convenience wrapper for code without safepoint or handler tables.
141 void GetCode(LocalIsolate* isolate, CodeDesc* desc) {
142 GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
143 }
144
145 // Unused on this architecture.
147
148 // Loong64 uses BlockTrampolinePool to prevent generating trampoline inside a
149 // continuous instruction block. In the destructor of BlockTrampolinePool, it
150 // must check if it needs to generate trampoline immediately, if it does not
151 // do this, the branch range will go beyond the max branch offset, that means
152 // the pc_offset after call CheckTrampolinePool may have changed. So we use
153 // pc_for_safepoint_ here for safepoint record.
155 return static_cast<int>(pc_for_safepoint_ - buffer_start_);
156 }
157
158 // TODO(LOONG_dev): LOONG64 Check this comment
159 // Label operations & relative jumps (PPUM Appendix D).
160 //
161 // Takes a branch opcode (cc) and a label (L) and generates
162 // either a backward branch or a forward branch and links it
163 // to the label fixup chain. Usage:
164 //
165 // Label L; // unbound label
166 // j(cc, &L); // forward branch to unbound label
167 // bind(&L); // bind label to the current pc
168 // j(cc, &L); // backward branch to bound label
169 // bind(&L); // illegal: a label may be bound only once
170 //
171 // Note: The same Label can be used for forward and backward branches
172 // but it may be bound only once.
173 void bind(Label* L); // Binds an unbound label L to current code position.
174
175 enum OffsetSize : int {
176 kOffset26 = 26,
177 kOffset21 = 21,
178 kOffset20 = 20,
179 kOffset16 = 16
180 };
181
182 // Determines if Label is bound and near enough so that branch instruction
183 // can be used to reach it, instead of jump instruction.
184 // c means conditinal branch, a means always branch.
185 bool is_near_c(Label* L);
186 bool is_near(Label* L, OffsetSize bits);
187 bool is_near_a(Label* L);
188
189 int BranchOffset(Instr instr);
190
191 // Returns the branch offset to the given label from the current code
192 // position. Links the label to the current position if it is still unbound.
193 // Manages the jump elimination optimization if the second parameter is true.
194 int32_t branch_offset_helper(Label* L, OffsetSize bits);
195 inline int32_t branch_offset(Label* L) {
196 return branch_offset_helper(L, OffsetSize::kOffset16);
197 }
198 inline int32_t branch_offset21(Label* L) {
199 return branch_offset_helper(L, OffsetSize::kOffset21);
200 }
201 inline int32_t branch_offset26(Label* L) {
202 return branch_offset_helper(L, OffsetSize::kOffset26);
203 }
204 inline int32_t shifted_branch_offset(Label* L) {
205 return branch_offset(L) >> 2;
206 }
207 inline int32_t shifted_branch_offset21(Label* L) {
208 return branch_offset21(L) >> 2;
209 }
210 inline int32_t shifted_branch_offset26(Label* L) {
211 return branch_offset26(L) >> 2;
212 }
213 uint64_t jump_address(Label* L);
214 uint64_t jump_offset(Label* L);
215 uint64_t branch_long_offset(Label* L);
216
217 // Puts a labels target address at the given position.
218 // The high 8 bits are set to zero.
219 void label_at_put(Label* L, int at_offset);
220
221 // Read/Modify the code target address in the branch/call instruction at pc.
222 // The isolate argument is unused (and may be nullptr) when skipping flushing.
223 static Address target_address_at(Address pc);
224 static uint32_t target_compressed_address_at(Address pc);
225 // On LOONG64 there is no Constant Pool so we skip that parameter.
226 inline static Address target_address_at(Address pc, Address constant_pool) {
227 return target_address_at(pc);
228 }
230 Address constant_pool) {
231 return target_compressed_address_at(pc);
232 }
233 inline static void set_target_address_at(
234 Address pc, Address constant_pool, Address target,
235 WritableJitAllocation* jit_allocation,
236 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
237 set_target_value_at(pc, target, jit_allocation, icache_flush_mode);
238 }
240 Address pc, Address constant_pool, Tagged_t target,
241 WritableJitAllocation* jit_allocation,
242 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
243 set_target_compressed_value_at(pc, target, jit_allocation,
244 icache_flush_mode);
245 }
246
247 inline Handle<Code> code_target_object_handle_at(Address pc,
248 Address constant_pool);
249
250 // During code generation builtin targets in PC-relative call/jump
251 // instructions are temporarily encoded as builtin ID until the generated
252 // code is moved into the code space.
253 static inline Builtin target_builtin_at(Address pc);
254
256 Address pc, uint64_t target,
257 WritableJitAllocation* jit_allocation = nullptr,
258 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
260 Address pc, uint32_t target,
261 WritableJitAllocation* jit_allocation = nullptr,
262 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
263
264 static void JumpLabelToJumpRegister(Address pc);
265
266 // Get the size of the special target encoded at 'instruction_payload'.
268 Address instruction_payload);
269
270 // This sets the internal reference at the pc.
272 Address pc, Address target, WritableJitAllocation& jit_allocation,
273 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
274
275 inline Handle<HeapObject> compressed_embedded_object_handle_at(
276 Address pc, Address constant_pool);
277 inline Handle<HeapObject> embedded_object_handle_at(Address pc,
278 Address constant_pool);
279
280 // Read/modify the uint32 constant used at pc.
281 static inline uint32_t uint32_constant_at(Address pc, Address constant_pool);
282 static inline void set_uint32_constant_at(
283 Address pc, Address constant_pool, uint32_t new_constant,
284 WritableJitAllocation* jit_allocation,
285 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
286
287 // Here we are patching the address in the LUI/ORI instruction pair.
288 // These values are used in the serialization process and must be zero for
289 // LOONG platform, as InstructionStream, Embedded Object or External-reference
290 // pointers are split across two consecutive instructions and don't exist
291 // separately in the code, so the serializer should not step forwards in
292 // memory after a target is resolved and written.
293 static constexpr int kSpecialTargetSize = 0;
294
295 // Number of consecutive instructions used to store 32bit/64bit constant.
296 // This constant was used in RelocInfo::target_address_address() function
297 // to tell serializer address of the instruction that follows
298 // LUI/ORI instruction pair.
299 // TODO(LOONG_dev): check this
300 static constexpr int kInstructionsFor64BitConstant = 4;
301
302 // Max offset for instructions with 16-bit offset field
303 static constexpr int kMax16BranchOffset = (1 << (18 - 1)) - 1;
304
305 // Max offset for instructions with 21-bit offset field
306 static constexpr int kMax21BranchOffset = (1 << (23 - 1)) - 1;
307
308 // Max offset for compact branch instructions with 26-bit offset field
309 static constexpr int kMax26BranchOffset = (1 << (28 - 1)) - 1;
310
311 static constexpr int kTrampolineSlotsSize = 2 * kInstrSize;
312
313 RegList* GetScratchRegisterList() { return &scratch_register_list_; }
314
316 return &scratch_fpregister_list_;
317 }
318
319 // ---------------------------------------------------------------------------
320 // InstructionStream generation.
321
322 // Insert the smallest number of nop instructions
323 // possible to align the pc offset to a multiple
324 // of m. m must be a power of 2 (>= 4).
325 void Align(int m);
326 // Insert the smallest number of zero bytes possible to align the pc offset
327 // to a mulitple of m. m must be a power of 2 (>= 2).
328 void DataAlign(int m);
329 // Aligns code to something that's optimal for a jump target for the platform.
331 void LoopHeaderAlign() { CodeTargetAlign(); }
332
333 // Different nop operations are used by the code generator to detect certain
334 // states of the generated code.
336 NON_MARKING_NOP = 0,
337 DEBUG_BREAK_NOP,
338 // IC markers.
339 PROPERTY_ACCESS_INLINED,
340 PROPERTY_ACCESS_INLINED_CONTEXT,
341 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
342 // Helper values.
343 LAST_CODE_MARKER,
344 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
345 };
346
347 // Type == 0 is the default non-marking nop. For LoongArch this is a
348 // andi(zero_reg, zero_reg, 0).
349 void nop(unsigned int type = 0) {
350 DCHECK_LT(type, 32);
351 andi(zero_reg, zero_reg, type);
352 }
353
354 // --------Branch-and-jump-instructions----------
355 // We don't use likely variant of instructions.
356 void b(int32_t offset);
357 inline void b(Label* L) { b(shifted_branch_offset26(L)); }
358 void bl(int32_t offset);
359 inline void bl(Label* L) { bl(shifted_branch_offset26(L)); }
360
361 void beq(Register rj, Register rd, int32_t offset);
362 inline void beq(Register rj, Register rd, Label* L) {
363 beq(rj, rd, shifted_branch_offset(L));
364 }
365 void bne(Register rj, Register rd, int32_t offset);
366 inline void bne(Register rj, Register rd, Label* L) {
367 bne(rj, rd, shifted_branch_offset(L));
368 }
369 void blt(Register rj, Register rd, int32_t offset);
370 inline void blt(Register rj, Register rd, Label* L) {
371 blt(rj, rd, shifted_branch_offset(L));
372 }
373 void bge(Register rj, Register rd, int32_t offset);
374 inline void bge(Register rj, Register rd, Label* L) {
375 bge(rj, rd, shifted_branch_offset(L));
376 }
377 void bltu(Register rj, Register rd, int32_t offset);
378 inline void bltu(Register rj, Register rd, Label* L) {
379 bltu(rj, rd, shifted_branch_offset(L));
380 }
381 void bgeu(Register rj, Register rd, int32_t offset);
382 inline void bgeu(Register rj, Register rd, Label* L) {
383 bgeu(rj, rd, shifted_branch_offset(L));
384 }
385 void beqz(Register rj, int32_t offset);
386 inline void beqz(Register rj, Label* L) {
387 beqz(rj, shifted_branch_offset21(L));
388 }
389 void bnez(Register rj, int32_t offset);
390 inline void bnez(Register rj, Label* L) {
391 bnez(rj, shifted_branch_offset21(L));
392 }
393
394 void jirl(Register rd, Register rj, int32_t offset);
395
396 void bceqz(CFRegister cj, int32_t si21);
397 inline void bceqz(CFRegister cj, Label* L) {
398 bceqz(cj, shifted_branch_offset21(L));
399 }
400 void bcnez(CFRegister cj, int32_t si21);
401 inline void bcnez(CFRegister cj, Label* L) {
402 bcnez(cj, shifted_branch_offset21(L));
403 }
404
405 // -------Data-processing-instructions---------
406
407 // Arithmetic.
408 void add_w(Register rd, Register rj, Register rk);
409 void add_d(Register rd, Register rj, Register rk);
410 void sub_w(Register rd, Register rj, Register rk);
411 void sub_d(Register rd, Register rj, Register rk);
412
413 void addi_w(Register rd, Register rj, int32_t si12);
414 void addi_d(Register rd, Register rj, int32_t si12);
415
416 void addu16i_d(Register rd, Register rj, int32_t si16);
417
418 void alsl_w(Register rd, Register rj, Register rk, int32_t sa2);
419 void alsl_wu(Register rd, Register rj, Register rk, int32_t sa2);
420 void alsl_d(Register rd, Register rj, Register rk, int32_t sa2);
421
422 void lu12i_w(Register rd, int32_t si20);
423 void lu32i_d(Register rd, int32_t si20);
424 void lu52i_d(Register rd, Register rj, int32_t si12);
425
426 void slt(Register rd, Register rj, Register rk);
427 void sltu(Register rd, Register rj, Register rk);
428 void slti(Register rd, Register rj, int32_t si12);
429 void sltui(Register rd, Register rj, int32_t si12);
430
431 void pcaddi(Register rd, int32_t si20);
432 void pcaddu12i(Register rd, int32_t si20);
433 void pcaddu18i(Register rd, int32_t si20);
434 void pcalau12i(Register rd, int32_t si20);
435
436 void and_(Register rd, Register rj, Register rk);
437 void or_(Register rd, Register rj, Register rk);
438 void xor_(Register rd, Register rj, Register rk);
439 void nor(Register rd, Register rj, Register rk);
440 void andn(Register rd, Register rj, Register rk);
441 void orn(Register rd, Register rj, Register rk);
442
443 void andi(Register rd, Register rj, int32_t ui12);
444 void ori(Register rd, Register rj, int32_t ui12);
445 void xori(Register rd, Register rj, int32_t ui12);
446
447 void mul_w(Register rd, Register rj, Register rk);
450 void mul_d(Register rd, Register rj, Register rk);
453
456
457 void div_w(Register rd, Register rj, Register rk);
458 void mod_w(Register rd, Register rj, Register rk);
461 void div_d(Register rd, Register rj, Register rk);
462 void mod_d(Register rd, Register rj, Register rk);
465
466 // Shifts.
467 void sll_w(Register rd, Register rj, Register rk);
468 void srl_w(Register rd, Register rj, Register rk);
469 void sra_w(Register rd, Register rj, Register rk);
471
472 void slli_w(Register rd, Register rj, int32_t ui5);
473 void srli_w(Register rd, Register rj, int32_t ui5);
474 void srai_w(Register rd, Register rj, int32_t ui5);
475 void rotri_w(Register rd, Register rj, int32_t ui5);
476
477 void sll_d(Register rd, Register rj, Register rk);
478 void srl_d(Register rd, Register rj, Register rk);
479 void sra_d(Register rd, Register rj, Register rk);
481
482 void slli_d(Register rd, Register rj, int32_t ui6);
483 void srli_d(Register rd, Register rj, int32_t ui6);
484 void srai_d(Register rd, Register rj, int32_t ui6);
485 void rotri_d(Register rd, Register rj, int32_t ui6);
486
487 // Bit twiddling.
490
491 void clo_w(Register rd, Register rj);
492 void clz_w(Register rd, Register rj);
493 void cto_w(Register rd, Register rj);
494 void ctz_w(Register rd, Register rj);
495 void clo_d(Register rd, Register rj);
496 void clz_d(Register rd, Register rj);
497 void cto_d(Register rd, Register rj);
498 void ctz_d(Register rd, Register rj);
499
500 void bytepick_w(Register rd, Register rj, Register rk, int32_t sa2);
501 void bytepick_d(Register rd, Register rj, Register rk, int32_t sa3);
502
507
510
513
516
517 void bstrins_w(Register rd, Register rj, int32_t msbw, int32_t lsbw);
518 void bstrins_d(Register rd, Register rj, int32_t msbd, int32_t lsbd);
519
520 void bstrpick_w(Register rd, Register rj, int32_t msbw, int32_t lsbw);
521 void bstrpick_d(Register rd, Register rj, int32_t msbd, int32_t lsbd);
522
525
526 // Memory-instructions
527 void ld_b(Register rd, Register rj, int32_t si12);
528 void ld_h(Register rd, Register rj, int32_t si12);
529 void ld_w(Register rd, Register rj, int32_t si12);
530 void ld_d(Register rd, Register rj, int32_t si12);
531 void ld_bu(Register rd, Register rj, int32_t si12);
532 void ld_hu(Register rd, Register rj, int32_t si12);
533 void ld_wu(Register rd, Register rj, int32_t si12);
534 void st_b(Register rd, Register rj, int32_t si12);
535 void st_h(Register rd, Register rj, int32_t si12);
536 void st_w(Register rd, Register rj, int32_t si12);
537 void st_d(Register rd, Register rj, int32_t si12);
538
539 void ldx_b(Register rd, Register rj, Register rk);
540 void ldx_h(Register rd, Register rj, Register rk);
541 void ldx_w(Register rd, Register rj, Register rk);
542 void ldx_d(Register rd, Register rj, Register rk);
546 void stx_b(Register rd, Register rj, Register rk);
547 void stx_h(Register rd, Register rj, Register rk);
548 void stx_w(Register rd, Register rj, Register rk);
549 void stx_d(Register rd, Register rj, Register rk);
550
551 void ldptr_w(Register rd, Register rj, int32_t si14);
552 void ldptr_d(Register rd, Register rj, int32_t si14);
553 void stptr_w(Register rd, Register rj, int32_t si14);
554 void stptr_d(Register rd, Register rj, int32_t si14);
555
574
593
594 void ll_w(Register rd, Register rj, int32_t si14);
595 void ll_d(Register rd, Register rj, int32_t si14);
596 void sc_w(Register rd, Register rj, int32_t si14);
597 void sc_d(Register rd, Register rj, int32_t si14);
598
599 void dbar(int32_t hint);
600 void ibar(int32_t hint);
601
602 // Break instruction
603 void break_(uint32_t code, bool break_as_stop = false);
604 void stop(uint32_t code = kMaxStopCode);
605
606 // Arithmetic.
615
624
629
634
639
646
653
656
658 CFRegister cd);
660 CFRegister cd);
661
664
673
690
693
696
698
702
706
707 void movgr2fcsr(Register rj, FPUControlRegister fcsr = FCSR0);
708 void movfcsr2gr(Register rd, FPUControlRegister fcsr = FCSR0);
709
712
715
716 void fld_s(FPURegister fd, Register rj, int32_t si12);
717 void fld_d(FPURegister fd, Register rj, int32_t si12);
718 void fst_s(FPURegister fd, Register rj, int32_t si12);
719 void fst_d(FPURegister fd, Register rj, int32_t si12);
720
725
726 // Check the code size generated from label to here.
728 return pc_offset() - label->pos();
729 }
730
731 // Check the number of instructions generated from label to here.
733 return SizeOfCodeGeneratedSince(label) / kInstrSize;
734 }
735
736 // Class for scoping postponing the trampoline pool generation.
737 class V8_NODISCARD BlockTrampolinePoolScope {
738 public:
739 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
740 assem_->StartBlockTrampolinePool();
741 }
742 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
743
744 private:
746
748 };
749
750 // Class for postponing the assembly buffer growth. Typically used for
751 // sequences of instructions that must be emitted as a unit, before
752 // buffer growth (and relocation) can occur.
753 // This blocking scope is not nestable.
755 public:
756 explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
757 assem_->StartBlockGrowBuffer();
758 }
759 ~BlockGrowBufferScope() { assem_->EndBlockGrowBuffer(); }
760
761 private:
763
765 };
766
767 // Record a deoptimization reason that can be used by a log or cpu profiler.
768 // Use --trace-deopt to enable.
769 void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
770 SourcePosition position, int id);
771
773 RelocInfo::Mode rmode, Address pc, intptr_t pc_delta,
774 WritableJitAllocation* jit_allocation = nullptr);
775
776 // Writes a single byte or word of data in the code stream. Used for
777 // inline tables, e.g., jump-tables.
778 void db(uint8_t data);
779 void dd(uint32_t data);
780 void dq(uint64_t data);
781 void dp(uintptr_t data) { dq(data); }
782 void dd(Label* label);
783
784 // Postpone the generation of the trampoline pool for the specified number of
785 // instructions.
786 void BlockTrampolinePoolFor(int instructions);
787
788 // Check if there is less than kGap bytes available in the buffer.
789 // If this is the case, we need to grow the buffer before emitting
790 // an instruction or relocation information.
791 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
792
793 // Get the number of bytes available in the buffer.
794 inline intptr_t available_space() const {
795 return reloc_info_writer.pos() - pc_;
796 }
797
798 // Read/patch instructions.
799 static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); }
800 static void instr_at_put(Address pc, Instr instr,
801 WritableJitAllocation* jit_allocation = nullptr) {
802 Instruction* i = reinterpret_cast<Instruction*>(pc);
803 i->SetInstructionBits(instr, jit_allocation);
804 }
806 return *reinterpret_cast<Instr*>(buffer_start_ + pos);
807 }
809 WritableJitAllocation* jit_allocation = nullptr) {
810 Instruction* i = reinterpret_cast<Instruction*>(buffer_start_ + pos);
811 i->SetInstructionBits(instr, jit_allocation);
812 }
813
814 // Check if an instruction is a branch of some kind.
815 static bool IsBranch(Instr instr);
816 static bool IsB(Instr instr);
817 static bool IsBz(Instr instr);
818 static bool IsNal(Instr instr);
819
820 static bool IsBeq(Instr instr);
821 static bool IsBne(Instr instr);
822
823 static bool IsJump(Instr instr);
824 static bool IsMov(Instr instr, Register rd, Register rs);
825 static bool IsPcAddi(Instr instr);
826
827 static bool IsJ(Instr instr);
828 static bool IsLu12i_w(Instr instr);
829 static bool IsOri(Instr instr);
830 static bool IsLu32i_d(Instr instr);
831 static bool IsLu52i_d(Instr instr);
832
833 static bool IsNop(Instr instr, unsigned int type);
834
838
839 static uint32_t GetRj(Instr instr);
840 static uint32_t GetRjField(Instr instr);
841 static uint32_t GetRk(Instr instr);
842 static uint32_t GetRkField(Instr instr);
843 static uint32_t GetRd(Instr instr);
844 static uint32_t GetRdField(Instr instr);
845 static uint32_t GetSa2(Instr instr);
846 static uint32_t GetSa3(Instr instr);
847 static uint32_t GetSa2Field(Instr instr);
848 static uint32_t GetSa3Field(Instr instr);
849 static uint32_t GetOpcodeField(Instr instr);
850 static uint32_t GetFunction(Instr instr);
851 static uint32_t GetFunctionField(Instr instr);
852 static uint32_t GetImmediate16(Instr instr);
853 static uint32_t GetLabelConst(Instr instr);
854
857
860
861 void CheckTrampolinePool();
862
863 // Get the code target object for a pc-relative call or jump.
865 Address pc_) const;
866
867 inline int UnboundLabelsCount() { return unbound_labels_count_; }
868
869 protected:
870 // Helper function for memory load/store.
872
873 inline static void set_target_internal_reference_encoded_at(Address pc,
874 Address target);
875
876 int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
877
878 // Decode branch instruction at pos and return branch target pos.
879 int target_at(int pos, bool is_internal);
880
881 // Patch branch instruction at pos to branch to given branch target pos.
882 void target_at_put(int pos, int target_pos, bool is_internal);
883
884 // Say if we need to relocate with this mode.
885 bool MustUseReg(RelocInfo::Mode rmode);
886
887 // Record reloc info for current pc_.
888 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
889
890 // Block the emission of the trampoline pool before pc_offset.
892 if (no_trampoline_pool_before_ < pc_offset)
893 no_trampoline_pool_before_ = pc_offset;
894 }
895
896 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
897
899 trampoline_pool_blocked_nesting_--;
900 if (trampoline_pool_blocked_nesting_ == 0) {
901 CheckTrampolinePoolQuick(1);
902 }
903 }
904
906 return trampoline_pool_blocked_nesting_ > 0;
907 }
908
909 bool has_exception() const { return internal_trampoline_exception_; }
910
911 bool is_trampoline_emitted() const { return trampoline_emitted_; }
912
913 // Temporarily block automatic assembly buffer growth.
915 DCHECK(!block_buffer_growth_);
916 block_buffer_growth_ = true;
917 }
918
920 DCHECK(block_buffer_growth_);
921 block_buffer_growth_ = false;
922 }
923
924 bool is_buffer_growth_blocked() const { return block_buffer_growth_; }
925
926 void CheckTrampolinePoolQuick(int extra_instructions = 0) {
927 if (pc_offset() >= next_buffer_check_ - extra_instructions * kInstrSize) {
928 CheckTrampolinePool();
929 }
930 }
931
932 void set_pc_for_safepoint() { pc_for_safepoint_ = pc_; }
933
934 private:
935 // Avoid overflows for displacements etc.
936 static const int kMaximalBufferSize = 512 * MB;
937
938 // Buffer size and constant pool distance are checked together at regular
939 // intervals of kBufferCheckInterval emitted bytes.
940 static constexpr int kBufferCheckInterval = 1 * KB / 2;
941
942 // InstructionStream generation.
943 // The relocation writer's position is at least kGap bytes below the end of
944 // the generated instructions. This is so that multi-instruction sequences do
945 // not have to check for overflow. The same is true for writes of large
946 // relocation info entries.
947 static constexpr int kGap = 64;
948 static_assert(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
949
950 // Repeated checking whether the trampoline pool should be emitted is rather
951 // expensive. By default we only check again once a number of instructions
952 // has been generated.
953 static constexpr int kCheckConstIntervalInst = 32;
954 static constexpr int kCheckConstInterval =
955 kCheckConstIntervalInst * kInstrSize;
956
957 int next_buffer_check_; // pc offset of next buffer check.
958
959 // Emission of the trampoline pool may be blocked in some code sequences.
960 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
961 int no_trampoline_pool_before_; // Block emission before this pc offset.
962
963 // Keep track of the last emitted pool to guarantee a maximal distance.
964 int last_trampoline_pool_end_; // pc offset of the end of the last pool.
965
966 // Automatic growth of the assembly buffer may be blocked for some sequences.
967 bool block_buffer_growth_; // Block growth when true.
968
969 // Relocation information generation.
970 // Each relocation is encoded as a variable size value.
971 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
972 RelocInfoWriter reloc_info_writer;
973
974 // The bound position, before this we cannot do instruction elimination.
975 int last_bound_pos_;
976
977 // InstructionStream emission.
978 inline void CheckBuffer();
980 inline void emit(Instr x);
981 inline void emit(uint64_t x);
982 template <typename T>
983 inline void EmitHelper(T x);
984 inline void EmitHelper(Instr x);
985
986 void GenB(Opcode opcode, Register rj, int32_t si21); // opcode:6
987 void GenB(Opcode opcode, CFRegister cj, int32_t si21, bool isEq);
988 void GenB(Opcode opcode, int32_t si26);
989 void GenBJ(Opcode opcode, Register rj, Register rd, int32_t si16);
991 CFRegister cd);
993 FPURegister rd);
994
995 void GenRegister(Opcode opcode, Register rj, Register rd, bool rjrd = true);
1005
1006 void GenRegister(Opcode opcode, Register rk, Register rj, Register rd);
1008 FPURegister fd);
1009
1011 FPURegister fj, FPURegister fd);
1013
1014 void GenImm(Opcode opcode, int32_t bit3, Register rk, Register rj,
1015 Register rd);
1016 void GenImm(Opcode opcode, int32_t bit6m, int32_t bit6l, Register rj,
1017 Register rd);
1018 void GenImm(Opcode opcode, int32_t bit20, Register rd);
1019 void GenImm(Opcode opcode, int32_t bit15);
1020 void GenImm(Opcode opcode, int32_t value, Register rj, Register rd,
1021 int32_t value_bits); // 6 | 12 | 14 | 16
1022 void GenImm(Opcode opcode, int32_t bit12, Register rj, FPURegister fd);
1023
1024 // Labels.
1025 void print(const Label* L);
1026 void bind_to(Label* L, int pos);
1027 void next(Label* L, bool is_internal);
1028
1029 // One trampoline consists of:
1030 // - space for trampoline slots,
1031 // - space for labels.
1032 //
1033 // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
1034 // Space for trampoline slots precedes space for labels. Each label is of one
1035 // instruction size, so total amount for labels is equal to
1036 // label_count * kInstrSize.
1037 class Trampoline {
1038 public:
1040 start_ = 0;
1041 next_slot_ = 0;
1042 free_slot_count_ = 0;
1043 end_ = 0;
1044 }
1045 Trampoline(int start, int slot_count) {
1046 start_ = start;
1047 next_slot_ = start;
1048 free_slot_count_ = slot_count;
1049 end_ = start + slot_count * kTrampolineSlotsSize;
1050 }
1051 int start() { return start_; }
1052 int end() { return end_; }
1054 int trampoline_slot = kInvalidSlotPos;
1055 if (free_slot_count_ <= 0) {
1056 // We have run out of space on trampolines.
1057 // Make sure we fail in debug mode, so we become aware of each case
1058 // when this happens.
1059 DCHECK(0);
1060 // Internal exception will be caught.
1061 } else {
1062 trampoline_slot = next_slot_;
1063 free_slot_count_--;
1064 next_slot_ += kTrampolineSlotsSize;
1065 }
1066 return trampoline_slot;
1067 }
1068
1069 private:
1071 int end_;
1074 };
1075
1076 int32_t get_trampoline_entry(int32_t pos);
1078 // After trampoline is emitted, long branches are used in generated code for
1079 // the forward branches whose target offsets could be beyond reach of branch
1080 // instruction. We use this information to trigger different mode of
1081 // branch instruction generation, where we use jump instructions rather
1082 // than regular branch instructions.
1084 static constexpr int kInvalidSlotPos = -1;
1085
1086 // Internal reference positions, required for unbounded internal reference
1087 // labels.
1090 return internal_reference_positions_.find(L->pos()) !=
1091 internal_reference_positions_.end();
1092 }
1093
1094 void EmittedCompactBranchInstruction() { prev_instr_compact_branch_ = true; }
1095 void ClearCompactBranchState() { prev_instr_compact_branch_ = false; }
1096 bool prev_instr_compact_branch_ = false;
1097
1100
1101 // Keep track of the last Call's position to ensure that safepoint can get the
1102 // correct information even if there is a trampoline immediately after the
1103 // Call.
1105
1106 RegList scratch_register_list_;
1107
1109
1110 private:
1112
1114
1116 friend class RelocInfo;
1118 friend class EnsureSpace;
1119};
1120
1121class EnsureSpace {
1122 public:
1123 explicit inline EnsureSpace(Assembler* assembler);
1124};
1125
1127 public:
1129 : available_(assembler->GetScratchRegisterList()),
1130 availablefp_(assembler->GetScratchFPRegisterList()),
1131 old_available_(*available_),
1132 old_availablefp_(*availablefp_) {}
1133
1135 *available_ = old_available_;
1136 *availablefp_ = old_availablefp_;
1137 }
1138
1140 return available_->PopFirst();
1141 }
1142
1144 return availablefp_->PopFirst();
1145 }
1146
1147 bool hasAvailable() const { return !available_->is_empty(); }
1148
1149 bool hasAvailableFp() const { return !availablefp_->is_empty(); }
1150
1151 void Include(const RegList& list) { *available_ |= list; }
1152 void IncludeFp(const DoubleRegList& list) { *availablefp_ |= list; }
1153 void Exclude(const RegList& list) { available_->clear(list); }
1154 void ExcludeFp(const DoubleRegList& list) { availablefp_->clear(list); }
1155 void Include(const Register& reg1, const Register& reg2 = no_reg) {
1156 RegList list({reg1, reg2});
1157 Include(list);
1158 }
1159 void IncludeFp(const DoubleRegister& reg1,
1160 const DoubleRegister& reg2 = no_dreg) {
1161 DoubleRegList list({reg1, reg2});
1162 IncludeFp(list);
1163 }
1164 void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
1165 RegList list({reg1, reg2});
1166 Exclude(list);
1167 }
1168 void ExcludeFp(const DoubleRegister& reg1,
1169 const DoubleRegister& reg2 = no_dreg) {
1170 DoubleRegList list({reg1, reg2});
1171 ExcludeFp(list);
1172 }
1173
1174 private:
1177 RegList old_available_;
1179};
1180
1181} // namespace internal
1182} // namespace v8
1183
1184#endif // V8_CODEGEN_LOONG64_ASSEMBLER_LOONG64_H_
RegList available_
SourcePosition pos
DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope)
DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope)
Trampoline(int start, int slot_count)
void bind_to(Label *L, int pos)
void ctz_d(Register rd, Register rj)
void ftintrm_w_d(FPURegister fd, FPURegister fj)
static void set_target_value_at(Address pc, uint64_t target, WritableJitAllocation *jit_allocation=nullptr, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void mod_du(Register rd, Register rj, Register rk)
void amadd_db_d(Register rd, Register rk, Register rj)
void ftint_w_s(FPURegister fd, FPURegister fj)
void fcvt_d_s(FPURegister fd, FPURegister fj)
void lu12i_w(Register rd, int32_t si20)
void fmsub_d(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void fcvt_s_d(FPURegister fd, FPURegister fj)
void GetCode(LocalIsolate *isolate, CodeDesc *desc)
void bitrev_4b(Register rd, Register rj)
void ammin_wu(Register rd, Register rk, Register rj)
void GenCmp(Opcode opcode, FPUCondition cond, FPURegister fk, FPURegister fj, CFRegister cd)
void rotri_d(Register rd, Register rj, int32_t ui6)
void ammax_wu(Register rd, Register rk, Register rj)
void frint_d(FPURegister fd, FPURegister fj)
bool is_buffer_growth_blocked() const
bool is_internal_reference(Label *L)
void addu16i_d(Register rd, Register rj, int32_t si16)
void ld_d(Register rd, Register rj, int32_t si12)
void clz_d(Register rd, Register rj)
void ldptr_w(Register rd, Register rj, int32_t si14)
static bool IsJ(Instr instr)
void fmax_d(FPURegister fd, FPURegister fj, FPURegister fk)
void frsqrt_d(FPURegister fd, FPURegister fj)
void rotri_w(Register rd, Register rj, int32_t ui5)
void masknez(Register rd, Register rj, Register rk)
static bool IsJump(Instr instr)
void fsqrt_d(FPURegister fd, FPURegister fj)
void fmov_d(FPURegister fd, FPURegister fj)
void fdiv_s(FPURegister fd, FPURegister fj, FPURegister fk)
void ftintrz_w_d(FPURegister fd, FPURegister fj)
void mulh_d(Register rd, Register rj, Register rk)
void sll_w(Register rd, Register rj, Register rk)
void fldx_s(FPURegister fd, Register rj, Register rk)
void alsl_w(Register rd, Register rj, Register rk, int32_t sa2)
void bgeu(Register rj, Register rd, int32_t offset)
void ammin_w(Register rd, Register rk, Register rj)
void slli_w(Register rd, Register rj, int32_t ui5)
void bstrpick_w(Register rd, Register rj, int32_t msbw, int32_t lsbw)
void bstrins_d(Register rd, Register rj, int32_t msbd, int32_t lsbd)
void ldptr_d(Register rd, Register rj, int32_t si14)
void beqz(Register rj, int32_t offset)
void fld_s(FPURegister fd, Register rj, int32_t si12)
void GenRegister(Opcode opcode, FPURegister fj, Register rd)
void stx_b(Register rd, Register rj, Register rk)
void ld_hu(Register rd, Register rj, int32_t si12)
void fabs_d(FPURegister fd, FPURegister fj)
void b(int32_t offset)
void ammin_db_wu(Register rd, Register rk, Register rj)
void mul_d(Register rd, Register rj, Register rk)
void mod_d(Register rd, Register rj, Register rk)
void GenRegister(Opcode opcode, CFRegister cj, FPURegister fd)
void bytepick_d(Register rd, Register rj, Register rk, int32_t sa3)
static uint32_t GetRk(Instr instr)
void srl_d(Register rd, Register rj, Register rk)
void fneg_s(FPURegister fd, FPURegister fj)
void clo_w(Register rd, Register rj)
void ld_w(Register rd, Register rj, int32_t si12)
void ext_w_b(Register rd, Register rj)
void movfrh2gr_s(Register rd, FPURegister fj)
static uint32_t GetOpcodeField(Instr instr)
void movfr2gr_s(Register rd, FPURegister fj)
void GenSel(Opcode opcode, CFRegister ca, FPURegister fk, FPURegister fj, FPURegister rd)
void fclass_d(FPURegister fd, FPURegister fj)
void fclass_s(FPURegister fd, FPURegister fj)
void flogb_s(FPURegister fd, FPURegister fj)
static bool IsBne(Instr instr)
Assembler(const MaybeAssemblerZone &, const AssemblerOptions &options, std::unique_ptr< AssemblerBuffer > buffer={})
bool is_near_c(Label *L)
void bcnez(CFRegister cj, int32_t si21)
void stx_h(Register rd, Register rj, Register rk)
void ammax_db_du(Register rd, Register rk, Register rj)
static int deserialization_special_target_size(Address instruction_payload)
void stptr_w(Register rd, Register rj, int32_t si14)
void ftintrp_l_d(FPURegister fd, FPURegister fj)
void fscaleb_s(FPURegister fd, FPURegister fj, FPURegister fk)
static void RelocateRelativeReference(RelocInfo::Mode rmode, Address pc, intptr_t pc_delta, WritableJitAllocation *jit_allocation=nullptr)
void AllocateAndInstallRequestedHeapNumbers(LocalIsolate *isolate)
void srli_w(Register rd, Register rj, int32_t ui5)
void movfr2gr_d(Register rd, FPURegister fj)
void bne(Register rj, Register rd, int32_t offset)
void orn(Register rd, Register rj, Register rk)
void fnmadd_d(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void movcf2gr(Register rd, CFRegister cj)
void div_w(Register rd, Register rj, Register rk)
void GenB(Opcode opcode, CFRegister cj, int32_t si21, bool isEq)
void alsl_d(Register rd, Register rj, Register rk, int32_t sa2)
static uint32_t GetFunctionField(Instr instr)
void beq(Register rj, Register rd, Label *L)
static void deserialization_set_target_internal_reference_at(Address pc, Address target, WritableJitAllocation &jit_allocation, RelocInfo::Mode mode=RelocInfo::INTERNAL_REFERENCE)
void srai_w(Register rd, Register rj, int32_t ui5)
void fsub_s(FPURegister fd, FPURegister fj, FPURegister fk)
void amand_db_w(Register rd, Register rk, Register rj)
void ftintrp_w_d(FPURegister fd, FPURegister fj)
void bltu(Register rj, Register rd, Label *L)
void or_(Register rd, Register rj, Register rk)
void revb_2h(Register rd, Register rj)
static Address target_address_at(Address pc)
void movgr2fr_d(FPURegister fd, Register rj)
bool is_trampoline_pool_blocked() const
void amxor_db_w(Register rd, Register rk, Register rj)
void slti(Register rd, Register rj, int32_t si12)
static uint32_t GetFunction(Instr instr)
void revh_d(Register rd, Register rj)
void nop(unsigned int type=0)
void ldx_d(Register rd, Register rj, Register rk)
void movfcsr2gr(Register rd, FPUControlRegister fcsr=FCSR0)
static uint32_t GetSa2Field(Instr instr)
void div_wu(Register rd, Register rj, Register rk)
void lu52i_d(Register rd, Register rj, int32_t si12)
void fcopysign_s(FPURegister fd, FPURegister fj, FPURegister fk)
int32_t shifted_branch_offset26(Label *L)
void fsub_d(FPURegister fd, FPURegister fj, FPURegister fk)
int InstructionsGeneratedSince(Label *label)
void db(uint8_t data)
void fmax_s(FPURegister fd, FPURegister fj, FPURegister fk)
static bool IsLu52i_d(Instr instr)
void bgeu(Register rj, Register rd, Label *L)
void bl(int32_t offset)
int32_t shifted_branch_offset(Label *L)
void GenBJ(Opcode opcode, Register rj, Register rd, int32_t si16)
static bool IsOri(Instr instr)
void amadd_w(Register rd, Register rk, Register rj)
void blt(Register rj, Register rd, int32_t offset)
void ld_wu(Register rd, Register rj, int32_t si12)
void frecip_s(FPURegister fd, FPURegister fj)
void fmul_s(FPURegister fd, FPURegister fj, FPURegister fk)
void movgr2cf(CFRegister cd, Register rj)
void GenRegister(Opcode opcode, FPURegister fj, CFRegister cd)
void clo_d(Register rd, Register rj)
void bitrev_w(Register rd, Register rj)
intptr_t available_space() const
static uint32_t GetLabelConst(Instr instr)
DoubleRegList scratch_fpregister_list_
void ibar(int32_t hint)
void ammin_db_d(Register rd, Register rk, Register rj)
static bool IsPcAddi(Instr instr)
void st_w(Register rd, Register rj, int32_t si12)
int32_t branch_offset26(Label *L)
void amand_d(Register rd, Register rk, Register rj)
void xor_(Register rd, Register rj, Register rk)
void movfr2cf(CFRegister cd, FPURegister fj)
static void set_uint32_constant_at(Address pc, Address constant_pool, uint32_t new_constant, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void ammin_db_du(Register rd, Register rk, Register rj)
void bnez(Register rj, Label *L)
void fcmp_cond_s(FPUCondition cc, FPURegister fj, FPURegister fk, CFRegister cd)
void movgr2fr_w(FPURegister fd, Register rj)
void GenImm(Opcode opcode, int32_t bit15)
static bool IsBz(Instr instr)
void revb_2w(Register rd, Register rj)
void fcmp_cond_d(FPUCondition cc, FPURegister fj, FPURegister fk, CFRegister cd)
void GenB(Opcode opcode, int32_t si26)
void GenImm(Opcode opcode, int32_t bit20, Register rd)
void ftintrp_l_s(FPURegister fd, FPURegister fj)
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data=0)
void ldx_wu(Register rd, Register rj, Register rk)
void ftintrz_l_s(FPURegister fd, FPURegister fj)
void bstrpick_d(Register rd, Register rj, int32_t msbd, int32_t lsbd)
void ammin_db_w(Register rd, Register rk, Register rj)
void jirl(Register rd, Register rj, int32_t offset)
void revb_d(Register rd, Register rj)
void ammax_d(Register rd, Register rk, Register rj)
void mul_w(Register rd, Register rj, Register rk)
void ammax_db_d(Register rd, Register rk, Register rj)
static uint32_t uint32_constant_at(Address pc, Address constant_pool)
void xori(Register rd, Register rj, int32_t ui12)
void mulh_wu(Register rd, Register rj, Register rk)
void fnmsub_s(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void fdiv_d(FPURegister fd, FPURegister fj, FPURegister fk)
void GenRegister(Opcode opcode, Register rj, FPUControlRegister fd)
void print(const Label *L)
void GenImm(Opcode opcode, int32_t bit3, Register rk, Register rj, Register rd)
static void set_target_compressed_value_at(Address pc, uint32_t target, WritableJitAllocation *jit_allocation=nullptr, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void pcaddu18i(Register rd, int32_t si20)
void srai_d(Register rd, Register rj, int32_t ui6)
void GenRegister(Opcode opcode, FPURegister fk, FPURegister fj, FPURegister fd)
static uint32_t GetRdField(Instr instr)
void ffint_s_w(FPURegister fd, FPURegister fj)
void ftintrne_w_s(FPURegister fd, FPURegister fj)
void ftintrz_w_s(FPURegister fd, FPURegister fj)
void ld_h(Register rd, Register rj, int32_t si12)
void amswap_w(Register rd, Register rk, Register rj)
void pcalau12i(Register rd, int32_t si20)
void fcopysign_d(FPURegister fd, FPURegister fj, FPURegister fk)
static Register GetRdReg(Instr instr)
void fscaleb_d(FPURegister fd, FPURegister fj, FPURegister fk)
void amswap_db_d(Register rd, Register rk, Register rj)
void fsqrt_s(FPURegister fd, FPURegister fj)
void add_w(Register rd, Register rj, Register rk)
void dbar(int32_t hint)
void fabs_s(FPURegister fd, FPURegister fj)
void sub_w(Register rd, Register rj, Register rk)
void ftintrm_w_s(FPURegister fd, FPURegister fj)
void nor(Register rd, Register rj, Register rk)
static Tagged_t target_compressed_address_at(Address pc, Address constant_pool)
void GenImm(Opcode opcode, int32_t bit12, Register rj, FPURegister fd)
void mod_w(Register rd, Register rj, Register rk)
static bool IsAddImmediate(Instr instr)
static Address target_address_at(Address pc, Address constant_pool)
int32_t shifted_branch_offset21(Label *L)
void bltu(Register rj, Register rd, int32_t offset)
void ld_bu(Register rd, Register rj, int32_t si12)
void ftintrne_w_d(FPURegister fd, FPURegister fj)
void fmin_d(FPURegister fd, FPURegister fj, FPURegister fk)
void amor_w(Register rd, Register rk, Register rj)
void andn(Register rd, Register rj, Register rk)
void GenRegister(Opcode opcode, CFRegister cj, Register rd)
void ammin_d(Register rd, Register rk, Register rj)
void sra_d(Register rd, Register rj, Register rk)
static uint32_t GetSa3(Instr instr)
void fmov_s(FPURegister fd, FPURegister fj)
void ftintrne_l_s(FPURegister fd, FPURegister fj)
void amand_w(Register rd, Register rk, Register rj)
void andi(Register rd, Register rj, int32_t ui12)
void st_b(Register rd, Register rj, int32_t si12)
uint64_t jump_offset(Label *L)
void rotr_d(Register rd, Register rj, Register rk)
bool is_near_a(Label *L)
void fnmadd_s(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
static bool IsBranch(Instr instr)
void st_h(Register rd, Register rj, int32_t si12)
void fnmsub_d(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void amand_db_d(Register rd, Register rk, Register rj)
void fld_d(FPURegister fd, Register rj, int32_t si12)
void sc_d(Register rd, Register rj, int32_t si14)
void stx_d(Register rd, Register rj, Register rk)
void movgr2fcsr(Register rj, FPUControlRegister fcsr=FCSR0)
static uint32_t GetRkField(Instr instr)
void ftintrm_l_d(FPURegister fd, FPURegister fj)
void fmaxa_d(FPURegister fd, FPURegister fj, FPURegister fk)
void amswap_d(Register rd, Register rk, Register rj)
void frint_s(FPURegister fd, FPURegister fj)
void sltu(Register rd, Register rj, Register rk)
void bne(Register rj, Register rd, Label *L)
void ld_b(Register rd, Register rj, int32_t si12)
void amxor_w(Register rd, Register rk, Register rj)
void GenRegister(Opcode opcode, FPURegister fa, FPURegister fk, FPURegister fj, FPURegister fd)
void amswap_db_w(Register rd, Register rk, Register rj)
std::set< int64_t > internal_reference_positions_
void GetCode(Isolate *isolate, CodeDesc *desc)
void GenRegister(Opcode opcode, FPURegister fj, FPURegister fd)
static Instr SetAddImmediateOffset(Instr instr, int16_t offset)
void bstrins_w(Register rd, Register rj, int32_t msbw, int32_t lsbw)
static Register GetRkReg(Instr instr)
void sc_w(Register rd, Register rj, int32_t si14)
void bytepick_w(Register rd, Register rj, Register rk, int32_t sa2)
void sra_w(Register rd, Register rj, Register rk)
void ammax_w(Register rd, Register rk, Register rj)
static uint32_t GetRd(Instr instr)
void revb_4h(Register rd, Register rj)
void fstx_s(FPURegister fd, Register rj, Register rk)
void dd(Label *label)
void ffint_s_l(FPURegister fd, FPURegister fj)
void ammin_du(Register rd, Register rk, Register rj)
void bge(Register rj, Register rd, Label *L)
static uint32_t target_compressed_address_at(Address pc)
void GenRegister(Opcode opcode, FPUControlRegister fj, Register rd)
void add_d(Register rd, Register rj, Register rk)
void GenImm(Opcode opcode, int32_t bit6m, int32_t bit6l, Register rj, Register rd)
void mulw_d_wu(Register rd, Register rj, Register rk)
static void instr_at_put(Address pc, Instr instr, WritableJitAllocation *jit_allocation=nullptr)
void revh_2w(Register rd, Register rj)
void fmina_s(FPURegister fd, FPURegister fj, FPURegister fk)
static uint32_t GetSa2(Instr instr)
void GenRegister(Opcode opcode, Register rj, FPURegister fd)
void addi_d(Register rd, Register rj, int32_t si12)
void GenRegister(Opcode opcode, Register rk, Register rj, FPURegister fd)
void fmin_s(FPURegister fd, FPURegister fj, FPURegister fk)
void fsel(CFRegister ca, FPURegister fd, FPURegister fj, FPURegister fk)
void ammax_db_wu(Register rd, Register rk, Register rj)
void dq(uint64_t data)
void beqz(Register rj, Label *L)
void fneg_d(FPURegister fd, FPURegister fj)
void fst_d(FPURegister fd, Register rj, int32_t si12)
void ll_w(Register rd, Register rj, int32_t si14)
void blt(Register rj, Register rd, Label *L)
void fst_s(FPURegister fd, Register rj, int32_t si12)
static Instr instr_at(Address pc)
void GenRegister(Opcode opcode, Register rj, CFRegister cd)
void fldx_d(FPURegister fd, Register rj, Register rk)
static bool IsEmittedConstant(Instr instr)
void GenImm(Opcode opcode, int32_t value, Register rj, Register rd, int32_t value_bits)
void ll_d(Register rd, Register rj, int32_t si14)
void sltui(Register rd, Register rj, int32_t si12)
static bool IsLu32i_d(Instr instr)
void bge(Register rj, Register rd, int32_t offset)
void fmadd_d(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void bcnez(CFRegister cj, Label *L)
void ctz_w(Register rd, Register rj)
void ffint_d_l(FPURegister fd, FPURegister fj)
V8_INLINE Handle< Code > relative_code_target_object_handle_at(Address pc_) const
void ori(Register rd, Register rj, int32_t ui12)
static bool IsMov(Instr instr, Register rd, Register rs)
void amor_db_d(Register rd, Register rk, Register rj)
void ammax_db_w(Register rd, Register rk, Register rj)
void fmul_d(FPURegister fd, FPURegister fj, FPURegister fk)
DoubleRegList * GetScratchFPRegisterList()
static bool IsLu12i_w(Instr instr)
void GetCode(LocalIsolate *isolate, CodeDesc *desc, SafepointTableBuilderBase *safepoint_table_builder, int handler_table_offset)
void cto_d(Register rd, Register rj)
static uint32_t GetRj(Instr instr)
void ffint_d_w(FPURegister fd, FPURegister fj)
void mulh_w(Register rd, Register rj, Register rk)
void bitrev_d(Register rd, Register rj)
void lu32i_d(Register rd, int32_t si20)
void ftintrm_l_s(FPURegister fd, FPURegister fj)
void ldx_b(Register rd, Register rj, Register rk)
void ftintrz_l_d(FPURegister fd, FPURegister fj)
void dp(uintptr_t data)
void maskeqz(Register rd, Register rj, Register rk)
void addi_w(Register rd, Register rj, int32_t si12)
void cto_w(Register rd, Register rj)
void and_(Register rd, Register rj, Register rk)
void rotr_w(Register rd, Register rj, Register rk)
static uint32_t GetRjField(Instr instr)
static bool IsNal(Instr instr)
void GenRegister(Opcode opcode, Register rj, Register rd, bool rjrd=true)
static uint32_t GetImmediate16(Instr instr)
void fmina_d(FPURegister fd, FPURegister fj, FPURegister fk)
void stptr_d(Register rd, Register rj, int32_t si14)
void AdjustBaseAndOffset(MemOperand *src)
void bitrev_8b(Register rd, Register rj)
static void JumpLabelToJumpRegister(Address pc)
void fadd_s(FPURegister fd, FPURegister fj, FPURegister fk)
void mulw_d_w(Register rd, Register rj, Register rk)
void stx_w(Register rd, Register rj, Register rk)
static void set_target_address_at(Address pc, Address constant_pool, Address target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void amadd_d(Register rd, Register rk, Register rj)
void ftintrne_l_d(FPURegister fd, FPURegister fj)
void fmaxa_s(FPURegister fd, FPURegister fj, FPURegister fk)
static uint32_t GetSa3Field(Instr instr)
void slt(Register rd, Register rj, Register rk)
void pcaddu12i(Register rd, int32_t si20)
void ftint_w_d(FPURegister fd, FPURegister fj)
void GenRegister(Opcode opcode, Register rk, Register rj, Register rd)
int32_t branch_offset(Label *L)
void ldx_hu(Register rd, Register rj, Register rk)
void movcf2fr(FPURegister fd, CFRegister cj)
void dd(uint32_t data)
void amxor_d(Register rd, Register rk, Register rj)
void fadd_d(FPURegister fd, FPURegister fj, FPURegister fk)
static Register GetRjReg(Instr instr)
void mulh_du(Register rd, Register rj, Register rk)
void ldx_bu(Register rd, Register rj, Register rk)
void bceqz(CFRegister cj, int32_t si21)
void clz_w(Register rd, Register rj)
static bool IsAndImmediate(Instr instr)
void ext_w_h(Register rd, Register rj)
void frecip_d(FPURegister fd, FPURegister fj)
void movgr2frh_w(FPURegister fd, Register rj)
void bceqz(CFRegister cj, Label *L)
void frsqrt_s(FPURegister fd, FPURegister fj)
Assembler(const AssemblerOptions &, std::unique_ptr< AssemblerBuffer >={})
void ftint_l_d(FPURegister fd, FPURegister fj)
void fstx_d(FPURegister fd, Register rj, Register rk)
void instr_at_put(int pos, Instr instr, WritableJitAllocation *jit_allocation=nullptr)
void slli_d(Register rd, Register rj, int32_t ui6)
void ftint_l_s(FPURegister fd, FPURegister fj)
void st_d(Register rd, Register rj, int32_t si12)
void ldx_h(Register rd, Register rj, Register rk)
void GenB(Opcode opcode, Register rj, int32_t si21)
void bnez(Register rj, int32_t offset)
static bool IsB(Instr instr)
void flogb_d(FPURegister fd, FPURegister fj)
void ldx_w(Register rd, Register rj, Register rk)
static bool IsBeq(Instr instr)
void CheckTrampolinePoolQuick(int extra_instructions=0)
int SizeOfCodeGeneratedSince(Label *label)
void mod_wu(Register rd, Register rj, Register rk)
void amor_d(Register rd, Register rk, Register rj)
void amadd_db_w(Register rd, Register rk, Register rj)
int32_t branch_offset21(Label *L)
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id, SourcePosition position, int id)
void fmadd_s(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
void BlockTrampolinePoolBefore(int pc_offset)
void srli_d(Register rd, Register rj, int32_t ui6)
void sll_d(Register rd, Register rj, Register rk)
static bool IsNop(Instr instr, unsigned int type)
void amor_db_w(Register rd, Register rk, Register rj)
void beq(Register rj, Register rd, int32_t offset)
void div_d(Register rd, Register rj, Register rk)
void sub_d(Register rd, Register rj, Register rk)
void alsl_wu(Register rd, Register rj, Register rk, int32_t sa2)
void amxor_db_d(Register rd, Register rk, Register rj)
void ftintrp_w_s(FPURegister fd, FPURegister fj)
void div_du(Register rd, Register rj, Register rk)
void srl_w(Register rd, Register rj, Register rk)
void pcaddi(Register rd, int32_t si20)
void fmsub_s(FPURegister fd, FPURegister fj, FPURegister fk, FPURegister fa)
static void set_target_compressed_address_at(Address pc, Address constant_pool, Tagged_t target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static Builtin target_builtin_at(Address pc)
void ammax_du(Register rd, Register rk, Register rj)
EnsureSpace(Assembler *assembler)
V8_EXPORT_PRIVATE Address address() const
MemOperand(Register rj, Register offset=no_reg)
V8_INLINE Operand(Tagged< Smi > value)
RelocInfo::Mode rmode() const
V8_INLINE Operand(const ExternalReference &f)
union v8::internal::Operand::Value value_
Operand(Handle< HeapObject > handle)
V8_INLINE Operand(int64_t immediate, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
RelocInfo::Mode rmode()
HeapNumberRequest heap_number_request() const
RelocInfo::Mode rmode_
bool IsHeapNumberRequest() const
V8_INLINE bool is_reg() const
static Operand EmbeddedNumber(double number)
Register rm() const
int32_t immediate() const
V8_INLINE Operand(Register rm)
constexpr bool is_valid() const
void ExcludeFp(const DoubleRegList &list)
void Exclude(const Register &reg1, const Register &reg2=no_reg)
void ExcludeFp(const DoubleRegister &reg1, const DoubleRegister &reg2=no_dreg)
void Include(const Register &reg1, const Register &reg2=no_reg)
void IncludeFp(const DoubleRegList &list)
void IncludeFp(const DoubleRegister &reg1, const DoubleRegister &reg2=no_dreg)
Operand const offset_
Register const index_
uint8_t *const start_
Definition assembler.cc:131
const v8::base::TimeTicks end_
Definition sweeper.cc:54
int start
Label label
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage * MB
int32_t offset
Instruction * instr
int pc_offset
int x
int position
Definition liveedit.cc:290
int m
Definition mul-fft.cc:294
STL namespace.
constexpr Register no_reg
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
std::variant< Zone *, AccountingAllocator * > MaybeAssemblerZone
Definition assembler.h:262
const int kSmiTagSize
Definition v8-internal.h:87
constexpr uint64_t kSmiShiftMask
Address Tagged_t
Definition globals.h:547
constexpr int L
constexpr int kSmiShift
const int kSmiShiftSize
constexpr uint8_t kInstrSize
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define V8_EXPORT_PRIVATE
Definition macros.h:460
HeapNumberRequest heap_number_request
#define V8_INLINE
Definition v8config.h:500
#define V8_NODISCARD
Definition v8config.h:693