Skip to content

Latest commit

 

History

History
1167 lines (926 loc) · 25.2 KB

9.Pseudo_Instruction_Set.adoc

File metadata and controls

1167 lines (926 loc) · 25.2 KB

CHAPTER 9. Macro Instructions

The LoongArch assembler supports a number of pseudo-instructions that are translated into the appropriate combination of LoongArch instructions during assembly.

9.1 ALU Macro Instructions

9.1.1 move

Syntax:

opcode    dest,  src1
opcode dest src1

move

$rd

$rj

Description :

move

:

$rd = $rj

Assign the value of $rj to $rd

Usage :

move                $t0, $t1
Machine Instruction ---------------
or                  $t0, $t1, $zero

9.1.2 li.w/d

Syntax:

opcode    dest,  src1
opcode dest src1

li.w

$rd

IMM32

li.d

$rd

IMM64

Description :

li.w

:

$rd = IMM32

Load a IMM32 to $rd

li.d

:

$rd = IMM64

Load a IMM64 to $rd

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

9.2 Jump Macro Instructions

9.2.1 jr

Syntax:

opcode    src1
opcode src1

jr

$rd

Description :

jr

:

jump to address($rd)

Direct register jump

Usage :

jirl                $t4
Machine Instruction -------------
jirl                $zero, $t4, 0

9.2.2 ret

Syntax:

opcode
opcode

ret

Description :

ret

:

Function return

Usage :

ret
Machine Instruction -------------
jirl                $zero, $ra, 0

9.2.3 call36

Syntax:

opcode    src1
opcode src1

call36

sym_call

Description :

call36

:

jump to sym_call

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 call36 depends on the range of {si20,18b0} in pcaddu18i. For details, see the LoongArch abi manual:8.3 .

9.2.4 tail36

Syntax:

opcode    src1,  src2
opcode src1 src2

tail36

$rd

sym_tail

Description :

tail36

:

jump to sym_tail

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 tail36 depends on the range of {si20,18b0} in pcaddu18i. For details, see the LoongArch abi manual:8.3 .

9.3 Branch Macro Instructions

9.3.1 bgt, ble, bgtu, bleu

Syntax:

opcode    src1,  src2,  src3
opcode src1 src2 src3

bgt, ble, bgtu, bleu

$rd

$rj

si18 | symbol

Description :

bgt

:

if (

signed($rj)

>

signed($rd)

) jump ( si18 | symbol )

ble

:

if (

signed($rj)

< =

signed($rd)

) jump ( si18 | symbol )

bgtu

:

if (

unsigned($rj)

>

unsigned($rd)

) jump ( si18 | symbol )

bleu

:

if (

unsigned($rj)

< =

unsigned($rd)

) jump ( si18 | symbol )

  • 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

9.3.2 bltz, bgtz, blez, bgez

Syntax:

opcode    src1,  src2
opcode src1 src2

bltz, bgtz, blez, bgez

$rd

si18 | symbol

Description :

bltz

:

if (

signed($rd)

>

0

) jump ( si18 | symbol )

bgtz

:

if (

signed($rd)

<

0

) jump ( si18 | symbol )

blez

:

if (

signed($rd)

< =

0

) jump ( si18 | symbol )

bgez

:

if (

signed($rd)

> =

0

) jump ( si18 | symbol )

  • 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

9.4 Load Address Macro Instructions

  • Load the symbol address into a general register and package the relocation information.

9.4.1 la.{local/global}

Syntax:

opcode    src1,  src2
opcode src1 src2

la.local

$rd

sym_local

la, la.global

$rd

sym_global

opcode    src1,  src2,  src3
opcode src1 src2 src3

la.local

$rd

$rj

sym_local_large

la.global

$rd

$rj

sym_global_large

Description :

la.local

:

la.local can load the addresses of symbols defined within the current module.

la.global

:

la.global can load addresses with symbols defined at any address.

la $rd, sym alias for la.global $rd, sym.

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

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 / la will directly load the content of the symbol instead of its address. In other cases, the address of the symbol is loaded.

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 will directly load the content of the symbol instead of its address. In other cases, the address of the symbol is loaded.

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

9.4.2 la.abs

Syntax:

opcode    src1,  src2
opcode src1 src2

la.abs

$rd

sym_abs

Description :

la.abs

:

It is used to load symbols defined at fixed addresses.

When loading, la.abs divides the address into four parts and uses four machine instructions to complete the loading operation for the symbol address.

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

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

9.4.3 la.pcrel

Syntax:

opcode    src1,  src2
opcode src1 src2

la.pcrel

$rd

sym_pcrel

opcode    src1,  src2,  src3
opcode src1 src2 src3

la.pcrel

$rd

$rj

sym_pcrel_large

Description :

la.pcrel

:

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 {x} in ld.{x} instruction depends on the size of the symbol contents.

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

9.4.4 la.got

Syntax:

opcode    src1,  src2
opcode src1 src2

la.got

$rd

sym_got

opcode    src1,  src2,  src3
opcode src1 src2 src3

la.got

$rd

$rj

sym_got_large

Description :

la.got

:

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

9.4.5 la.tls.{le / ie / ld / gd / desc}

Syntax:

opcode    src1,  src2
opcode src1 src2

la.tls.le

$rd

sym_le

la.tls.ie

$rd

sym_ie

la.tls.ld

$rd

sym_ld

la.tls.gd

$rd

sym_gd

la.tls.desc

$rd

sym_desc

opcode    src1,  src2,  src3
opcode src1 src2 src3

la.tls.ie

$rd

$rj

sym_ie_large

la.tls.ld

$rd

$rj

sym_ld_large

la.tls.gd

$rd

$rj

sym_gd_large

la.tls.desc

$rd

$rj

sym_desc_large

  • la.tls.ld is alias for la.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 support TLS.

la.tls.le

:

Load $tp-relative offset of TLS symbol.

la.tls.ie

:

Load runtime $tp-relative offset of TLS symbol from GOT entry.

la.tls.ld

:

Alias for la.tls.gd .

la.tls.gd

:

Load the runtime information that is passed to __tls_get_addr, which is used to access TLS symbol.

la.tls.desc

:

A more flexible address for loading symbols from TLS, which is often used for link optimization.

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 for la.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 normally
pcalau12i           $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 normally
pcalau12i           $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