Chapter 8. Pseudo Op-Codes (Directives)

This chapter describes pseudo op-codes (directives). These pseudo op-codes influence the assembler's later behavior.

Op-Codes

The assembler has the following pseudo op-codes:

Pseudo Op-Codes

Pseudo-Op 

Description

.2byte expression1 [ , expression2 ] ... [ , expressionN] 

Truncates the expressions in the comma-separated list to 16-bit values and assembles the values in successive locations. The expressions must be absolute or in the form of a label difference ( label1 - label2) if both labels are defined in the same section.

This directive optionally can have the form expression1 [ : expression2 ]. The expression2 replicates expression1's value expression2 times.

This directive does no automatic alignment.

(64-bit and N32 only)

.4byteexpression1 [ , expression2 ] ... [ , expressionN] 

Truncates the expressions in the comma-separated list to 32-bit values and assembles the values in successive locations.

The expressions must be absolute or in the form of a label difference ( label1 - label2) if both labels are defined in the same section.

This directive optionally can have the form expression1 [ : expression2 ]. The expression2 replicates expression1's value expression2 times.

This directive does no automatic alignment.

(64-bit and N32 only)

.8byteexpression1 [ , expression2 ] ... [ , expressionN] 

Truncates the expressions in the comma-separated list to 64-bit values and assembles the values in successive locations. The expressions must be absolute or in the form of a label difference ( label1 - label2) if both labels are defined in the same section.

This directive optionally can have the form expression1 [ : expression2 ]. The expression2 replicates expression1's value expression2 times. This directive does no automatic alignment.

(64-bit and N32 only)

.aentname,symno 

Sets an alternate entry point for the current procedure. Use this information when you want to generate information for the debugger. It must appear inside an .ent/.end pair.

.alignexpression 

Advances the location counter to make the expression low order bits of the counter zero. Normally, the .half, .word, .float, and .double directives automatically align their data appropriately. For example, .word does an implicit .align 2 (.double does an .align 3). You disable the automatic alignment feature with .align 0. The assembler reinstates automatic alignment at the next .text, .data, .rdata, or .sdata directive.

Labels immediately preceding an automatic or explicit alignment are also realigned. For example, foo: .align 3; .word 0 is the same as .align 3; foo: .word 0.

.asciistring [, string]...  

Assembles each string from the list into successive locations. The .ascii directive does not null pad the string. You must put quotation marks (") around each string. You can use the backslash escape characters. For a list of the backslash characters, see Chapter 4, “Lexical Conventions”.

.asciiz string [, string]...  

Assembles each string in the list into successive locations and adds a null. You can use the backslash escape characters. For a list of the backslash characters, see Chapter 4, “Lexical Conventions”.

.byte expression1 [, expression2 ] ... [, expressionN] 

Truncates the expressions from the comma-separated list to 8-bit values, and assembles the values in successive locations. The expressions must be absolute. The operands can optionally have the form: expression1 [ : expression2 ]. The expression2 replicates expression1's value expression2 times.

.commname, expression [alignment] 

Unless defined elsewhere, name becomes a global common symbol at the head of a block of expression bytes of storage. The linker overlays like-named common blocks, using the maximum of the expressions. The 64-bit and N32 assembler also accepts an optional value which specifies the alignment of the symbol.

.cpadd reg 

Emits code that adds the value of "_gp" to reg.

.cploadreg 

Expands into the three instructions function prologue that sets up the $gp register. This directive is used by position-independent code.

.cplocalreg 

Causes the assembler to use reg instead of $gp as the context pointer. This directive is used by position-independent code.

(64-bit and N32 only)

.cprestoreoffset 

Causes the assembler to emit the following at the point where it occurs: sw $gp, offset ($sp)

Also, causes the assembler to generate lw $gp, offset ($sp) after every JAL or BAL operation. Offset should point to the saved register area as described in Chapter 7, “Linkage Conventions”.

This directive is used by position-independent code following the caller-saved gp convention.

.cpreturn 

Causes the assembler to emit the following at the point where it occurs:

ld $gp, offset ($sp)

The offset is obtained from the previous .cpsetup pseudo-op.

(64-bit and N32 only)

.cpsetup reg1, {offset | reg2}, label 

Causes the assembler to emit the following at the point where it occurs:

sd $gp, offset ($sp)

lui $gp, 0 {label}

daddiu $gp, $gp, 0 { label }

daddu $gp, $gp, reg1

ld $gp, offset ($sp)

This sequence is used by position-independent code following the callee-saved gp convention. It stores $gp in the saved register area and calculates the virtual address of label and places it in reg1. By convention, reg1 is $25 (t9).

If reg2 is used instead of offset, $gp is saved and restored to and from this register.

(64-bit and N32 only)

.data 

Tells the assembler to add all subsequent data to the data section.

.doubleexpression [ , expression2] ...[, expressionN]  

Initializes memory to 64-bit floating point numbers. The operands optionally can have the form: expression1 [ : expression2 ]. The expression1 is the floating point value. The optional expression2 is a non-negative expression that specifies a repetition count. The expression2 replicates expression1's value expression2 times. This directive aligns its data and any preceding labels automatically to a double-word boundary. You can disable this feature by using .align0.

.dword expression [ , expression2 ] ...[, expressionN]  

Truncates the expressions in the comma-separated list to 64-bits and assembles the values in successive locations. The expressions must be absolute. The operands optionally can have the form: expression1 [:expression2]. The expresssion2 replicates expression1's value expression2 number of times. The directive aligns its data and preceding labels automatically to a doubleword boundary. You can disable this feature by using .align0.

.dynsym namevalue 

Specifies an ELF st_other value for the object denoted by name (64-bit and N32 only).

.end [proc_name] 

Sets the end of a procedure. Use this directive when you want to generate information for the debugger. To set the beginning of a procedure, see .ent.

.endr 

Signals the end of a repeat block. To start a repeat block, see .repeat.

.entproc_name 

Sets the beginning of the procedure proc_name. Use this directive when you want to generate information for the debugger. To set the end of a procedure, see .end.

.externname expression 

name is a global undefined symbol whose size is assumed to be expression bytes. The advantage of using this directive, instead of permitting an undefined symbol to become global by default, is that the assembler can decide whether to use the economical $gp-relative addressing mode, depending on the value of the -G option. As a special case, if expression is zero, the assembler refrains from using $gp to address this symbol regardless of the size specified by -G.

.filefile_number file_name_string 

Specifies the source file corresponding to the assembly instructions that follow. For use only by compilers, not by programmers; when the assembler sees this, it refrains from generating line numbers for dbx to use unless it also sees .loc directives.

.float expression1 [ , expression2 ] ... [, expressionN] 

Initializes memory to single precision 32-bit floating point numbers. The operands optionally can have the form: expression1<_newline>[ : expression2 ]. The optional expression2 is a non-negative expression that specifies a repetition count. This optional form replicates expression1's value expression2 times. This directive aligns its data and preceding labels automatically to a word boundary. You can disable this feature by using .align0.

.fmaskmask offset 

Sets a mask with a bit turned on for each floating point register that the current routine saved. The least-significant bit corresponds to register $f0. The offset is the distance in bytes from the virtual frame pointer at which the floating point registers are saved. The assembler saves higher register numbers closer to the virtual frame pointer. You must use .ent before .fmask and only one .fmask may be used per .ent. Space should be allocated for those registers specified in the .fmask.

.frameframe-register offset return_pc_register 

Describes a stack frame. The first register is the frame-register, the offset is the distance from the frame register to the virtual frame pointer, and the second register is the return program counter (or, if the first register is $0, this directive shows that the return program counter is saved four bytes from the virtual frame pointer). You must use .ent before .frame and only one .frame may be used per .ent. No stack traces can be done in the debugger without .frame.

.globlname 

Makes the name external. If the name is defined otherwise (by its appearance as a label), the assembler will export the symbol; otherwise it will import the symbol. In general, the assembler imports undefined symbols (that is, it gives them the UNIX storage class "global undefined" and requires the linker to resolve them).

.gpvaluenumber 

Sets the offset to use in gp_rel relocations; 0 by default. (64-bit and N32 only).

.gpwordlocal-sym 

This directive is similar to .word except that the relocation entry for local-sym has the R_MIPS_GPREL32 type. After linkage, this results in a 32-bit value that is the distance between local-sym and gp. local-sym must be local. This directive is used by the code generator for PIC switch tables.

.halfexpression1 [ , expression2 ] ... {, expressionN] 

Truncates the expressions in the comma-separated list to 16-bit values and assembles the values in successive locations. The expressions must be absolute. This directive optionally can have the form: expression1 [ : expression2 ]. The expression2 replicates expression1's value expression2 times. This directive automatically aligns its data appropriately. You can disable this feature by using .align0.

.lablabel_name 

Associates a named label with the current location in the program text. For use by compilers.

.lcommname, expression 

Makes the name's data type bss. The assembler allocates the named symbol to the bss area, and the expression defines the named symbol's length. If a .globl directive also specifies the name, the assembler allocates the named symbol to external bss. The assembler puts bss symbols in one of two bss areas. If the defined size is smaller than (or equal to) the size specified by the assembler or compiler's -G command line option, the assembler puts the symbols in the sbss area and uses $gp to address the data.

.locfile_number line_number [column] 

Specifies the source file and the line within that file that corresponds to the assembly instructions that follow. For use by compilers. The assembler ignores the file number when this directive appears in the assembly source file. Then, the assembler assumes that the directive refers to the most recent .file directive. The 64-bit and N32 assembler also supports an optional value that specifies the column number.

.maskmask, offset 

Sets a mask with a bit turned on for each general purpose register that the current routine saved. For use by compilers. Bit one corresponds to register $1. The offset is the distance in bytes from the virtual frame pointer where the registers are saved. The assembler saves higher register numbers closer to the virtual frame pointer. Space should be allocated for those registers appearing in the mask. If bit zero is set it is assumed that space is allocated for all 31 registers regardless of whether they appear in the mask.

.nada 

Tells the assembler to put in an instruction that has no effect on the machine state. It has the same effect as nop (described below), but it produces more efficient code on an R8000.

(64-bit and N32 only)

.nop 

Tells the assembler to put in an instruction that has no effect on the machine state. While several instructions cause no-operation, the assembler only considers the ones generated by the nop directive to be wait instructions. This directive puts an explicit delay in the instruction stream.


Note: Unless you use .set noreorder, the reorganizer may eliminate unnecessary nop instructions.


.optionoptions 

Tells the assembler that certain options were in effect during compilation. (These options can, for example, limit the assembler's freedom to perform branch optimizations.) This option is intended for compiler-generated .s files rather than for hand-coded ones.

.originexpression 

Specifies the current offset in a section to the value of expression.

(64-bit and N32 only)

.repeatexpression 

Repeats all instructions or data between the .repeat directive and the .endr directive. The expression defines how many times the data repeats. With the .repeat directive, you cannot use labels, branch instructions, or values that require relocation in the block. To end a .repeat, see .endr.

.rdata 

Tells the assembler to add subsequent data into the rdata section.

.sdata 

Tells the assembler to add subsequent data to the sdata section.

.sectionname [, section type, section flags, section entry size, section alignment] 

Instructs the assembler to create a section with the given name and optional attributes.

Legal section type values are denoted by variables prefixed by SHT_ in<elf.h>.

Legal section flags values are denoted by variables prefixed by SHF_ in<elf.h>.

The section entry size specifies the size of each entry in the section. For example, it is 4 for .text sections.

The section alignment specifies the byte boundary requirement for the section. For example, it is 16 for .text sections.

(64-bit and N32 only)

.setoption  

Instructs the assembler to enable or to disable certain options. Use .set options only for hand-crafted assembly routines. The assembler has these default options: reorder, macro, and at. You can specify only one option for each .set directive. You can specify these .set options:

The reorder option lets the assembler reorder machine language instructions to improve performance.

The noreorder option prevents the assembler from reordering machine language instructions. If a machine language instruction violates the hardware pipeline constraints, the assembler issues a warning message.

The macro option lets the assembler generate multiple machine instructions from a single assembler instruction.

The nomacro option causes the assembler to print a warning whenever an assembler operation generates more than one machine language instruction. You must select the noreorder option before using the nomacro option; otherwise, an error results.

The at option lets the assembler use the $at register for macros, but generates warnings if the source program uses $at. When you use the noat option and an assembler operation requires the $at register, the assembler issues a warning message; however, the noat option does let source programs use $at without issuing warnings.

The nomove option tells the assembler to mark each subsequent instruction so that it cannot be moved during reorganization. Because the assembler can still insert nop instructions where necessary for pipeline constraints, this option is less stringent than noreorder. The assembler can still move instructions from below the nomove region to fill delay slots above the region or vice versa. The nomove option has part of the effect of the "volatile" C declaration; it prevents otherwise independent loads or stores from occurring in a different order than intended.

The move option cancels the effect of nomove.

The notransform option tells the assembler to mark each subsequent instruction so that it cannot be transformed by pixie(1) into an equivalent set of instructions. There are restrictions on the use of this option in order to guarantee pixie's ability to still produce code that will execute correctly with the preceding/following transformed code. The sequence of instructions marked notransform must behave like a single basic block (i.e., there is only one entry and exit from the sequences and they are the first and last instructions, respectively). If this restriction cannot be met, correct transformed execution can still be guaranteed if the sequence of instructions does not use any of the saved registers $16..$23, $30 (s0-s8).

The transform option cancels the effect of notransform.

.sizename, expression 

Specifies the size of an object denoted by name to the value of expression.

.space expression 

Advances the location counter by the value of the specified expression bytes. The assembler fills the space with zeros.

.struct expression 

This permits you to lay out a structure using labels plus directives like .word, .byte, and so forth. It ends at the next segment directive (.data, .text, etc.). It does not emit any code or data, but defines the labels within it to have values which are the sum of expression plus their offsets from the .struct itself.

(symbolic equate) 

Takes one of these forms: name = expression or name = register. You must define the name only once in the assembly, and you cannot redefine the name. The expression must be computable when you assemble the program, and the expression must involve operators, constants, and equated symbols. You can use the name as a constant in any later statement.

.text 

Tells the assembler to add subsequent code to the text section. (This is the default.)

.type name, value 

Specifies the elf type of an object denoted by name to value. Legal elf type values are denoted by variables prefixed by STT_ in <elf.h>.

(64-bit and N32 only)

.verstampmajor minor 

Specifies the major and minor version numbers (for example, version 0.15 would be .verstamp 0 15).

.weakextweak_name [strong_name] 

Defines a weak external name and optionally associates it with the strong_name.

.wordexpression1 [, expression2 ] ... [, expressionN] 

Truncates the expressions in the comma-separated list to 32-bits and assembles the values in successive locations. The expressions must be absolute. The operands optionally can have the form: expression1<_newline>[ : expression2 ]. The expression2 replicates expression1's value expression2 times. This directive aligns its data and preceding labels automatically to a word boundary. You can disable this feature by using .align0.

The directives listed below are only accepted in -o32 compiles; they are only meant for compiler-generated code, and should not be used in hand-written assembly code.

.alias
.asm0
.bgnb
.endb
.err
.gjaldef
.gjallive
.gjrlive
.livereg
.noalias
.set bopt/nobopt
.vreg

PIC Assembly Code

By default, the assembler and compilers generate position-independent code (PIC). This is needed for programs that use dynamic shared libraries. For programs assembled with the -n32 and -64 options to as(1), see the MIPSpro 64-Bit Porting and Transition Guide for further information.

If you want to generate PIC with the assembler using the -o32 option, assemble with the -KPIC and -G0 options, which are enabled by default.

The following assembler directives support PIC generation: .option pic2, .cpload, .cprestore, .gpword, and .cpadd. See “Op-Codes” for information about the directives. The following example illustrates the use of these directives with the -o32 option.

Example 8-1. KPIC directives example

Consider the following program:

     .option   pic2
     .data
     .align    2
$$5:
     .ascii    "hello world\X0A\X00"
     .text
     .align    2
main:
     .set   noreorder
     .cpload   $25
     .set   reorder
     subu $sp, 40
     sw   $31, 36($sp)
     .cprestore     32
     la   $4, $$5
     jal  printf
     move $2, $0
     lw   $31, 36($sp)
     addu $sp, 40
     j    $31

The actual instructions generated by the assembler are as follows:

     lui  gp,0     #
     addiu   gp,gp,0     #generated by .cpload
     addu gp,gp,t9 #
     lw   a0,0(g0) # gp-relative addressing used
     lw   t9,0(gp) # t9 is used for func. call
     addiu   sp,sp,-40
     sw   ra,36(sp)
     sw   gp,32(sp)# from .cprestore
     jalr ra,t9    # jal is changed to jalr
     addiu   a0,a0,0
     lw   ra,36(sp)
     lw   gp,32(sp)# activated by .cprestore
     move v0,zero
     jr   ra
     addiu   sp,sp,40
     nop 

The ABI requires that register t9 ($25) be used for indirect function calls, so .cpload should always use $25; no-reorder mode should also be used. Make sure that t9 is dead before any function call, because the register is changed (and not restored) during the function call.

If your program uses an indirect jump (jalr), you must also use t9 as the jump register.

If you have an unconditional jump to an external label (j _cerror), rewrite it into an indirect jump using t9, as in this example:

     la t9,_cerror
     j  t9

If you use branch-and-link (bal) instructions and if the target procedure begins with a .cpload, specify an alternate entry point, as in this example:

     foo: .set noreorder   #callee
          .cpload   $25
          .set reorder
     $$1: ...              # alternative entry point
          ...
          j   $31          # foo returns
     bar: ...              # caller
          ...
          bal  $$1         # bypass the .cpload
          ...

The alternate entry point is important because .cpload assumes register $25 contains the address of foo, but in this case, $25 is not set up. Because both foo and bar reside in the same file, they must have the same value for $gp. The .cpload instructions can be and must be bypassed, but because foo can still be called from outside, the .cpload is still required.

If you don't want to have an alternate entry point, you can set up register $25 before the bal, as in the following:

     la   t9, foo
     bal  foo

Entries of the address table created by .gpword are converted into displacement from the context pointer. To get the correct text address, .cpadd should be used to add the value of gp back to them. The gp is updated by the runtime linker, so the correct text address can be reconstructed regardless of the location of the DSO.