The LoongArch assembler supports a number of pseudo-instructions that are translated into the appropriate combination of LoongArch instructions during assembly.
Syntax:
opcode dest, src1
opcode | dest | src1 |
---|---|---|
|
|
|
Description :
|
: |
|
Assign the value of |
Usage :
move $t0, $t1
Machine Instruction ---------------
or $t0, $t1, $zero
Syntax:
opcode dest, src1
opcode | dest | src1 |
---|---|---|
|
|
|
|
|
|
Description :
|
: |
|
Load a |
||
|
: |
|
Load a |
Usage :
-
li.w
:
li.w $t0, 0x76543210
Machine Instruction ------------------------------------------------------------------
lu12i.w $t0, si20 // load IMM32[31:12] $t0 = 0x76543000
ori $t0, $t0, si12 // load IMM32[11: 0] $t0 = 0x76543210
-
li.d
:
li.d $t0, 0xfedcba9876543210
Machine Instruction ------------------------------------------------------------------
lu12i.w $rd, si20 // load IMM64[31:12] $t0 = 0x0000000076543000
ori $rd, $rd, si12 // load IMM64[11: 0] $t0 = 0x0000000076543210
lu32i.d $rd, si20 // load IMM64[51:32] $t0 = 0x000cba9876543210
lu52i.d $rd, $rd, si12 // load IMM64[63:52] $t0 = 0xfedcba9876543210
Syntax:
opcode src1
opcode | src1 |
---|---|
|
|
Description :
|
: |
jump to address( |
Direct register jump |
Usage :
jirl $t4
Machine Instruction -------------
jirl $zero, $t4, 0
Syntax:
opcode
opcode |
---|
|
Description :
|
: |
Function return |
Usage :
ret
Machine Instruction -------------
jirl $zero, $ra, 0
Syntax:
opcode src1
opcode | src1 |
---|---|
|
|
Description :
|
: |
jump to |
Usage :
call36 sym_call
Machine Instruction ----------------------
pcaddu18i $ra, %call36(sym_call)
jirl $ra, $ra, 0
-
sym_call only allows symbol names, not immediate values.
Note
|
The addressing range of |
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
Description :
|
: |
jump to |
Usage :
tail36 $t1, sym_tail
Machine Instruction ----------------------
pcaddu18i $t1, %call36(sym_tail)
jirl $t1, $t1, 0
-
sym_call only allows symbol names, not immediate values.
Note
|
The addressing range of |
Syntax:
opcode src1, src2, src3
opcode | src1 | src2 | src3 |
---|---|---|---|
|
|
|
|
Description :
|
: |
if ( |
signed( |
|
signed( |
) jump ( |
|
: |
if ( |
signed( |
|
signed( |
) jump ( |
|
: |
if ( |
unsigned( |
|
unsigned( |
) jump ( |
|
: |
if ( |
unsigned( |
|
unsigned( |
) jump ( |
-
si18
: a 4-bytes aligned 18-bits signed immediate value in range :-
[
-131072
,131068
] or [-0x20000
,0x1fffc
]
-
-
symbol
: Tags in assembly for jump.
Usage :
bgt $rj, $rd, si18 or symbol
ble $rj, $rd, si18 or symbol
bgtu $rj, $rd, si18 or symbol
bleu $rj, $rd, si18 or symbol
Machine Instruction ------------------------
blt $rd, $rj, si18 or symbol
bge $rd, $rj, si18 or symbol
bltu $rd, $rj, si18 or symbol
bgeu $rd, $rj, si18 or symbol
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
Description :
|
: |
if ( |
signed( |
|
|
) jump ( |
|
: |
if ( |
signed( |
|
|
) jump ( |
|
: |
if ( |
signed( |
|
|
) jump ( |
|
: |
if ( |
signed( |
|
|
) jump ( |
-
si18
: a 4-bytes aligned 18-bits signed immediate value in range :-
[
-131072
,131068
] or [-0x20000
,0x1fffc
]
-
-
symbol
: Tags in assembly for jump.
Usage :
bltz $rd, si18 or symbol
bgtz $rd, si18 or symbol
blez $rd, si18 or symbol
bgez $rd, si18 or symbol
Machine Instruction --------------------------
blt $rd, $zero, si18 or symbol
blt $zero, $rd, si18 or symbol
bge $zero, $rd, si18 or symbol
bge $rd, $zero, si18 or symbol
-
Load the
symbol address
into a general register and package the relocation information.
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
|
|
|
opcode src1, src2, src3
opcode | src1 | src2 | src3 |
---|---|---|---|
|
|
|
|
|
|
|
|
Description :
|
: |
|
|
: |
|
|
Usage :
-
Method to load
sym_local
:
la.local $a0, sym_local // load sym_local address to $a0.
ld.{x} $a1, $a0, 0 // load sym_local to $a1.
Note
|
The { |
la.local
Expand normally:pcalau12i $a0, %pc_hi20(sym_local)
addi.d $a0, $a0, %pc_lo12(sym_local)
ld.{x} $a1, $a0, 0
la.local
Expand as la.abs
: (GNU: -mla-local-with-abs
LLVM: --mattr=+la-local-with-abs
)lu12i.w $a0, %abs_hi20(sym_local)
ori $a0, $a0, %abs_lo12(sym_local)
lu32i.d $a0, %abs64_lo20(sym_local)
lu52i.d $a0, $a0, %abs64_hi12(sym_local)
ld.{x} $a1, $a0, 0
-
Method to load
sym_local_large
:
la.local $a0, $a1, sym_local_large // load sym_local_large address to $a0.
ld.{x} $a2, $a0, 0 // load sym_local_large to $a2.
Note
|
The { |
la.local
Expand normally:pcalau12i $a0, %pc_hi20(sym_local_large)
addi.d $a1, $zero, %pc_lo12(sym_local_large)
lu32i.d $a1, %pc64_lo20(sym_local_large)
lu52i.d $a1, $a1, %pc64_hi12(sym_local_large)
add.d $a0, $a0, $a1
ld.{x} $a2, $a0, 0
la.local
Expand as la.abs
: (GNU: -mla-local-with-abs
LLVM: --mattr=+la-local-with-abs
)lu12i.w $a0, %abs_hi20(sym_local)
ori $a0, $a0, %abs_lo12(sym_local)
lu32i.d $a0, %abs64_lo20(sym_local)
lu52i.d $a0, $a0, %abs64_hi12(sym_local)
ld.{x} $a2, $a0, 0
-
Method to load
sym_global
:
la.global $a0, sym_global // load sym_global to $a0.
la $a0, sym_global // load sym_global to $a0.
Note
|
In normal expansion, |
la.global
Expand normally:pcalau12i $a0, %got_pc_hi20(sym_global)
ld.d $a0, $a0, %got_pc_lo12(sym_global)
la.global
Expand as la.pcrel
: (GNU: -mla-global-with-pcrel
LLVM: --mattr=+la-global-with-pcrel
)pcalau12i $a0, %pc_hi20(sym_global)
addi.d $a0, $a0, %pc_lo12(sym_global)
ld.{x} $a1, $a0, 0
la.global
Expand as la.abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %abs_hi20(sym_global)
ori $a0, $a0, %abs_lo12(sym_global)
lu32i.d $a0, %abs64_lo20(sym_global)
lu52i.d $a0, $a0, %abs64_hi12(sym_global)
ld.{x} $a1, $a0, 0
-
Method to load
sym_global_large
:
la.global $a0, $a1, sym_global_large // load sym_global_large to $a0.
Note
|
In normal expansion, |
la.global
Expand normally:pcalau12i $a0, %got_pc_hi20(sym_global_large)
addi.d $a1, $zero, %got_pc_lo12(sym_global_large)
lu32i.d $a1, %got64_pc_lo20(sym_global_large)
lu52i.d $a1, $a1, %got64_pc_hi12(sym_global_large)
ldx.d $a0, $a0, $a1
la.global
Expand as la.pcrel
: (GNU: -mla-global-with-pcrel
LLVM: --mattr=+la-global-with-pcrel
)pcalau12i $a0, %pc_hi20(sym_global_large)
addi.d $a1, $zero, %pc_lo12(sym_global_large)
lu32i.d $a1, %pc64_lo20(sym_global_large)
lu52i.d $a1, $a1, %pc64_hi12(sym_global_large)
add.d $a0, $a0, $a1
ld.{x} $a0, $a0, 0
Note
|
The { |
la.global
Expand as la.abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %abs_hi20(sym_global_large)
ori $a0, $a0, %abs_lo12(sym_global_large)
lu32i.d $a0, %abs64_lo20(sym_global_large)
lu52i.d $a0, $a0, %abs64_hi12(sym_global_large)
ld.{x} $a0, $a0, 0
Note
|
The { |
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
Description :
|
: |
It is used to load symbols defined at fixed addresses. |
When loading, |
||
For undefined weak symbols, it loads a constant value of 0. |
Usage :
-
Method to load
sym_abs
:
la.abs $a0, sym_abs // load sym_abs address to $a0.
ld.{x} $a2, $a0, 0 // load sym_abs to $a2.
Note
|
The { |
la.global
Expand normally:lu12i.w $a0, %abs_hi20(sym_abs)
ori $a0, $a0, %abs_lo12(sym_abs)
lu32i.d $a0, %abs64_lo20(sym_abs)
lu52i.d $a0, $a0, %abs64_hi12(sym_abs)
ld.{x} $a2, $a0, 0
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
opcode src1, src2, src3
opcode | src1 | src2 | src3 |
---|---|---|---|
|
|
|
|
Description :
|
: |
Load symbols at minimal cost using the local symbol’s PC-relative address. Undefined weak symbols cannot be loaded. |
Usage :
-
Method to load
sym_pcrel
:
la.pcrel $a0, sym_pcrel // load sym_pcrel address to $a0.
ld.{x} $a2, $a0, 0 // load sym_pcrel to $a2.
la.global
Expand normally:pcalau12i $a0, %pc_hi20(sym_pcrel)
addi.d $a0, $a0, %pc_lo12(sym_pcrel)
ld.{x} $a2, $a0, 0
-
Method to load
sym_pcrel_large
:
la.pcrel $a0, $a1, sym_pcrel_large // load sym_pcrel_large address to $a0.
ld.{x} $a2, $a0, 0 // load sym_pcrel_large to $a2.
Note
|
The { |
la.global
Expand normally:pcalau12i $a0, %pc_hi20(sym_pcrel_large)
addi.d $a1, $zero, %pc_lo12(sym_pcrel_large)
lu32i.d $a1, %pc64_lo20(sym_pcrel_large)
lu52i.d $a1, $a1, %pc64_hi12(sym_pcrel_large)
add.d $a0, $a0, $a1
ld.{x} $a2, $a0, 0
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
opcode src1, src2, src3
opcode | src1 | src2 | src3 |
---|---|---|---|
|
|
|
|
Description :
|
: |
Use the Global Offset Table (GOT) to load the address of a symbol from a double array constructed by the static linker. |
Usage :
-
Method to load
sym_got
:
la.got $a0, sym_got // load sym_got to $a0.
la.got
Expand normally:pcalau12i $a0, %got_pc_hi20(sym_got)
ld.d $a0, $a0, %got_pc_lo12(sym_got)
la.got
Expand abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %got_hi20(sym_got)
ori $a0, $a0, %got_lo12(sym_got)
lu32i.d $a0, %got64_lo20(sym_got)
lu52i.d $a0, $a0, %got64_hi12(sym_got)
ld.d $a0, $a0, 0
-
Method to load
sym_got_large
:
la.got $a0, $a1, sym_got_large // load sym_got_large to $a0.
la.got
Expand normally:pcalau12i $a0, %got_pc_hi20(sym_got_large)
addi.d $a1, $zero, %got_pc_lo12(sym_got_large)
lu32i.d $a1, %got64_pc_lo20(sym_got_large)
lu52i.d $a1, $a1, %got64_pc_hi12(sym_got_large)
ldx.d $a0, $a0, $a1
Syntax:
opcode src1, src2
opcode | src1 | src2 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opcode src1, src2, src3
opcode | src1 | src2 | src3 |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
la.tls.ld
is alias forla.tls.gd
.
Description :
-
Thread Local Storage
(TLS
) is a space (TLS block
) that is unique to a thread in a user program.-
$tp
is used to supportTLS
.
-
|
: |
Load |
|
: |
Load runtime |
|
: |
Alias for |
|
: |
Load the runtime information that is passed to |
|
: |
A more flexible address for loading symbols from |
Usage :
-
Method to load
sym_le
address:
la.tls.le $a0, sym_le // load sym_le address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_le address to $a0.
la.tls.le
Expand normally:lu12i.w $a0, %le_hi20(sym_le)
ori $a0, $a0, %le_lo12(sym_le)
add.{w/d} $a0, $a0, $tp
-
Method to load
sym_le_large
address:
la.tls.le $a0, sym_le_large // load sym_le_large address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_le_large address to $a0.
la.tls.le
Expand normally:lu12i.w $a0, %le_hi20(sym_le_large)
ori $a0, $a0, %le_lo12(sym_le_large)
lu32i.d $a0, %le64_hi20(sym_le_large)
lu52i.d $a0, $a0, %le64_hi12(sym_le_large)
add.{w/d} $a0, $a0, $tp
-
Method to load
sym_ie
address:
la.tls.ie $a0, sym_ie // load sym_ie address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_ie address to $a0.
la.tls.ie
Expand normally:pcalau12i $a0, %ie_pc_hi20(sym_ie)
ld.d $a0, $a0, %ie_pc_lo12(sym_ie)
add.{w/d} $a0, $a0, $tp
la.tls.ie
Expand abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %ie_hi20(sym_ie)
ori $a0, $a0, %ie_lo12(sym_ie)
lu32i.d $a0, %ie64_lo20(sym_ie)
lu52i.d $a0, $a0, %ie64_hi12(sym_ie)
ld.d $a0, $a0, 0
-
Method to load
sym_ie_large
address:
la.tls.ie $a0, $a1, sym_ie_large // load sym_ie_large address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_ie_large address to $a0.
la.tls.ie
Expand normally:pcalau12i $a0, %ie_pc_hi20(sym_ie_large)
addi.d $a1, $zero, %ie_pc_lo12(sym_ie_large)
lu32i.d $a1, %ie64_pc_lo20(sym_ie_large)
lu52i.d $a1, $a1, %ie64_pc_hi12(sym_ie_large)
ldx.d $a0, $a0, $a1
add.{w/d} $a0, $a0, $tp
-
Method to load
sym_gd
address: (la.tls.gd
alias forla.tls.ld
)
la.tls.gd $a0, sym_gd // load __tls_get_addr args to $a0.
bl %plt(__tls_get_addr) // __tls_get_addr ret sym_gd address to $a0.
la.tls.gd
Expand normally:pcalau12i $a0, %gd_pc_hi20(sym_gd)
addi.d $a0, $a0, %got_pc_lo12(sym_gd)
bl %plt(__tls_get_addr)
la.tls.gd
Expand abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %gd_hi20(sym_gd)
ori $a0, $a0, %got_lo12(sym_gd)
lu32i.d $a0, %got64_lo20(sym_gd)
lu52i.d $a0, $a0, %got64_hi12(sym_gd)
bl %plt(__tls_get_addr)
-
Method to load
sym_gd_large
address:
la.tls.gd $a0, $a1, sym_gd_large // load __tls_get_addr args to $a0.
bl %plt(__tls_get_addr) // __tls_get_addr ret sym_gd address to $a0.
la.tls.gd
Expand normally:pcalau12i $a0, %gd_pc_hi20(sym_gd_large)
addi.d $a1, $zero, %got_pc_lo12(sym_gd_large)
lu32i.d $a1, %got64_pc_lo20(sym_gd_large)
lu52i.d $a1, $a1, %got64_pc_hi12(sym_gd_large)
add.d $a0, $a0, $a1
bl %plt(__tls_get_addr)
-
Method to load
sym_desc
address:
la.tls.desc $a0, sym_desc // load sym_desc address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_desc address to $a0.
la.tls.desc
Expand normallypcalau12i $a0, %desc_pc_hi20(sym_desc)
addi.d $a0, $a0, %desc_pc_lo12(sym_desc)
ld.d $ra, $a0, %desc_ld(sym_desc)
jirl $ra, $ra, %desc_call(sym_desc)
add.{w/d} $a0, $a0, $tp
la.tls.desc
Expand abs
: (GNU: -mla-global-with-abs
LLVM: --mattr=+la-global-with-abs
)lu12i.w $a0, %desc_hi20(sym_desc) ori $a0, $a0, %desc_lo12(sym_desc) lu32i.d $a0, %desc64_lo20(sym_desc) lu52i.d $a0, $a0, %desc64_hi12(sym_desc) ld.d $ra, $a0, %desc_ld(sym_desc) jirl $ra, $ra, %desc_call(sym_desc) add.{w/d} $a0, $a0, $tp
-
Method to load
sym_desc_large
address:
la.tls.desc $a0, $a1, sym_desc_large // load sym_desc address offset to $a0.
add.{w/d} $a0, $a0, $tp // load sym_desc address to $a0.
la.tls.desc
Expand normallypcalau12i $a0, %desc_pc_hi20(sym_desc_large)
addi.d $a1, $zero, %desc_pc_lo12(sym_desc_large)
lu32i.d $a1, %desc64_pc_lo20(sym_desc_large)
lu52i.d $a1, $a1, %desc64_pc_hi12(sym_desc_large)
add.d $a0, $a0, $a1
ld.d $ra, $a0, %desc_ld(sym_desc_large)
jirl $ra, $ra, %desc_call(sym_desc_large)
add.{w/d} $a0, $a0, $tp