123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371 |
- .HTML "A Manual for the Plan 9 assembler
- .ft CW
- .ta 8n +8n +8n +8n +8n +8n +8n
- .ft
- .TL
- A Manual for the Plan 9 assembler
- .AU
- Rob Pike
- rob@plan9.bell-labs.com
- .SH
- Machines
- .PP
- There is an assembler for each of the MIPS, SPARC, Intel 386, AMD64,
- Power PC, and ARM.
- The 68020 assembler,
- .CW 2a ,
- (no longer distributed)
- is the oldest and in many ways the prototype.
- The assemblers are really just variations of a single program:
- they share many properties such as left-to-right assignment order for
- instruction operands and the synthesis of macro instructions
- such as
- .CW MOVE
- to hide the peculiarities of the load and store structure of the machines.
- To keep things concrete, the first part of this manual is
- specifically about the 68020.
- At the end is a description of the differences among
- the other assemblers.
- .PP
- The document, ``How to Use the Plan 9 C Compiler'', by Rob Pike,
- is a prerequisite for this manual.
- .SH
- Registers
- .PP
- All pre-defined symbols in the assembler are upper-case.
- Data registers are
- .CW R0
- through
- .CW R7 ;
- address registers are
- .CW A0
- through
- .CW A7 ;
- floating-point registers are
- .CW F0
- through
- .CW F7 .
- .PP
- A pointer in
- .CW A6
- is used by the C compiler to point to data, enabling short addresses to
- be used more often.
- The value of
- .CW A6
- is constant and must be set during C program initialization
- to the address of the externally-defined symbol
- .CW a6base .
- .PP
- The following hardware registers are defined in the assembler; their
- meaning should be obvious given a 68020 manual:
- .CW CAAR ,
- .CW CACR ,
- .CW CCR ,
- .CW DFC ,
- .CW ISP ,
- .CW MSP ,
- .CW SFC ,
- .CW SR ,
- .CW USP ,
- and
- .CW VBR .
- .PP
- The assembler also defines several pseudo-registers that
- manipulate the stack:
- .CW FP ,
- .CW SP ,
- and
- .CW TOS .
- .CW FP
- is the frame pointer, so
- .CW 0(FP)
- is the first argument,
- .CW 4(FP)
- is the second, and so on.
- .CW SP
- is the local stack pointer, where automatic variables are held
- (SP is a pseudo-register only on the 68020);
- .CW 0(SP)
- is the first automatic, and so on as with
- .CW FP .
- Finally,
- .CW TOS
- is the top-of-stack register, used for pushing parameters to procedures,
- saving temporary values, and so on.
- .PP
- The assembler and loader track these pseudo-registers so
- the above statements are true regardless of what has been
- pushed on the hardware stack, pointed to by
- .CW A7 .
- The name
- .CW A7
- refers to the hardware stack pointer, but beware of mixed use of
- .CW A7
- and the above stack-related pseudo-registers, which will cause trouble.
- Note, too, that the
- .CW PEA
- instruction is observed by the loader to
- alter SP and thus will insert a corresponding pop before all returns.
- The assembler accepts a label-like name to be attached to
- .CW FP
- and
- .CW SP
- uses, such as
- .CW p+0(FP) ,
- to help document that
- .CW p
- is the first argument to a routine.
- The name goes in the symbol table but has no significance to the result
- of the program.
- .SH
- Referring to data
- .PP
- All external references must be made relative to some pseudo-register,
- either
- .CW PC
- (the virtual program counter) or
- .CW SB
- (the ``static base'' register).
- .CW PC
- counts instructions, not bytes of data.
- For example, to branch to the second following instruction, that is,
- to skip one instruction, one may write
- .P1
- BRA 2(PC)
- .P2
- Labels are also allowed, as in
- .P1
- BRA return
- NOP
- return:
- RTS
- .P2
- When using labels, there is no
- .CW (PC)
- annotation.
- .PP
- The pseudo-register
- .CW SB
- refers to the beginning of the address space of the program.
- Thus, references to global data and procedures are written as
- offsets to
- .CW SB ,
- as in
- .P1
- MOVL $array(SB), TOS
- .P2
- to push the address of a global array on the stack, or
- .P1
- MOVL array+4(SB), TOS
- .P2
- to push the second (4-byte) element of the array.
- Note the use of an offset; the complete list of addressing modes is given below.
- Similarly, subroutine calls must use
- .CW SB :
- .P1
- BSR exit(SB)
- .P2
- File-static variables have syntax
- .P1
- local<>+4(SB)
- .P2
- The
- .CW <>
- will be filled in at load time by a unique integer.
- .PP
- When a program starts, it must execute
- .P1
- MOVL $a6base(SB), A6
- .P2
- before accessing any global data.
- (On machines such as the MIPS and SPARC that cannot load a register
- in a single instruction, constants are loaded through the static base
- register. The loader recognizes code that initializes the static
- base register and treats it specially. You must be careful, however,
- not to load large constants on such machines when the static base
- register is not set up, such as early in interrupt routines.)
- .SH
- Expressions
- .PP
- Expressions are mostly what one might expect.
- Where an offset or a constant is expected,
- a primary expression with unary operators is allowed.
- A general C constant expression is allowed in parentheses.
- .PP
- Source files are preprocessed exactly as in the C compiler, so
- .CW #define
- and
- .CW #include
- work.
- .SH
- Addressing modes
- .PP
- The simple addressing modes are shared by all the assemblers.
- Here, for completeness, follows a table of all the 68020 addressing modes,
- since that machine has the richest set.
- In the table,
- .CW o
- is an offset, which if zero may be elided, and
- .CW d
- is a displacement, which is a constant between -128 and 127 inclusive.
- Many of the modes listed have the same name;
- scrutiny of the format will show what default is being applied.
- For instance, indexed mode with no address register supplied operates
- as though a zero-valued register were used.
- For "offset" read "displacement."
- For "\f(CW.s\fP" read one of
- .CW .L ,
- or
- .CW .W
- followed by
- .CW *1 ,
- .CW *2 ,
- .CW *4 ,
- or
- .CW *8
- to indicate the size and scaling of the data.
- .IP
- .TS
- l lfCW.
- data register R0
- address register A0
- floating-point register F0
- special names CAAR, CACR, etc.
- constant $con
- floating point constant $fcon
- external symbol name+o(SB)
- local symbol name<>+o(SB)
- automatic symbol name+o(SP)
- argument name+o(FP)
- address of external $name+o(SB)
- address of local $name<>+o(SB)
- indirect post-increment (A0)+
- indirect pre-decrement -(A0)
- indirect with offset o(A0)
- indexed with offset o()(R0.s)
- indexed with offset o(A0)(R0.s)
- external indexed name+o(SB)(R0.s)
- local indexed name<>+o(SB)(R0.s)
- automatic indexed name+o(SP)(R0.s)
- parameter indexed name+o(FP)(R0.s)
- offset indirect post-indexed d(o())(R0.s)
- offset indirect post-indexed d(o(A0))(R0.s)
- external indirect post-indexed d(name+o(SB))(R0.s)
- local indirect post-indexed d(name<>+o(SB))(R0.s)
- automatic indirect post-indexed d(name+o(SP))(R0.s)
- parameter indirect post-indexed d(name+o(FP))(R0.s)
- offset indirect pre-indexed d(o()(R0.s))
- offset indirect pre-indexed d(o(A0))
- offset indirect pre-indexed d(o(A0)(R0.s))
- external indirect pre-indexed d(name+o(SB))
- external indirect pre-indexed d(name+o(SB)(R0.s))
- local indirect pre-indexed d(name<>+o(SB))
- local indirect pre-indexed d(name<>+o(SB)(R0.s))
- automatic indirect pre-indexed d(name+o(SP))
- automatic indirect pre-indexed d(name+o(SP)(R0.s))
- parameter indirect pre-indexed d(name+o(FP))
- parameter indirect pre-indexed d(name+o(FP)(R0.s))
- .TE
- .in
- .SH
- Laying down data
- .PP
- Placing data in the instruction stream, say for interrupt vectors, is easy:
- the pseudo-instructions
- .CW LONG
- and
- .CW WORD
- (but not
- .CW BYTE )
- lay down the value of their single argument, of the appropriate size,
- as if it were an instruction:
- .P1
- LONG $12345
- .P2
- places the long 12345 (base 10)
- in the instruction stream.
- (On most machines,
- the only such operator is
- .CW WORD
- and it lays down 32-bit quantities.
- The 386 has all three:
- .CW LONG ,
- .CW WORD ,
- and
- .CW BYTE .
- The AMD64 adds
- .CW QUAD
- to that for 64-bit values.
- The 960 has only one,
- .CW LONG .)
- .PP
- Placing information in the data section is more painful.
- The pseudo-instruction
- .CW DATA
- does the work, given two arguments: an address at which to place the item,
- including its size,
- and the value to place there. For example, to define a character array
- .CW array
- containing the characters
- .CW abc
- and a terminating null:
- .P1
- DATA array+0(SB)/1, $'a'
- DATA array+1(SB)/1, $'b'
- DATA array+2(SB)/1, $'c'
- GLOBL array(SB), $4
- .P2
- or
- .P1
- DATA array+0(SB)/4, $"abc\ez"
- GLOBL array(SB), $4
- .P2
- The
- .CW /1
- defines the number of bytes to define,
- .CW GLOBL
- makes the symbol global, and the
- .CW $4
- says how many bytes the symbol occupies.
- Uninitialized data is zeroed automatically.
- The character
- .CW \ez
- is equivalent to the C
- .CW \e0.
- The string in a
- .CW DATA
- statement may contain a maximum of eight bytes;
- build larger strings piecewise.
- Two pseudo-instructions,
- .CW DYNT
- and
- .CW INIT ,
- allow the (obsolete) Alef compilers to build dynamic type information during the load
- phase.
- The
- .CW DYNT
- pseudo-instruction has two forms:
- .P1
- DYNT , ALEF_SI_5+0(SB)
- DYNT ALEF_AS+0(SB), ALEF_SI_5+0(SB)
- .P2
- In the first form,
- .CW DYNT
- defines the symbol to be a small unique integer constant, chosen by the loader,
- which is some multiple of the word size. In the second form,
- .CW DYNT
- defines the second symbol in the same way,
- places the address of the most recently
- defined text symbol in the array specified by the first symbol at the
- index defined by the value of the second symbol,
- and then adjusts the size of the array accordingly.
- .PP
- The
- .CW INIT
- pseudo-instruction takes the same parameters as a
- .CW DATA
- statement. Its symbol is used as the base of an array and the
- data item is installed in the array at the offset specified by the most recent
- .CW DYNT
- pseudo-instruction.
- The size of the array is adjusted accordingly.
- The
- .CW DYNT
- and
- .CW INIT
- pseudo-instructions are not implemented on the 68020.
- .SH
- Defining a procedure
- .PP
- Entry points are defined by the pseudo-operation
- .CW TEXT ,
- which takes as arguments the name of the procedure (including the ubiquitous
- .CW (SB) )
- and the number of bytes of automatic storage to pre-allocate on the stack,
- which will usually be zero when writing assembly language programs.
- On machines with a link register, such as the MIPS and SPARC,
- the special value -4 instructs the loader to generate no PC save
- and restore instructions, even if the function is not a leaf.
- Here is a complete procedure that returns the sum
- of its two arguments:
- .P1
- TEXT sum(SB), $0
- MOVL arg1+0(FP), R0
- ADDL arg2+4(FP), R0
- RTS
- .P2
- An optional middle argument
- to the
- .CW TEXT
- pseudo-op is a bit field of options to the loader.
- Setting the 1 bit suspends profiling the function when profiling is enabled for the rest of
- the program.
- For example,
- .P1
- TEXT sum(SB), 1, $0
- MOVL arg1+0(FP), R0
- ADDL arg2+4(FP), R0
- RTS
- .P2
- will not be profiled; the first version above would be.
- Subroutines with peculiar state, such as system call routines,
- should not be profiled.
- .PP
- Setting the 2 bit allows multiple definitions of the same
- .CW TEXT
- symbol in a program; the loader will place only one such function in the image.
- It was emitted only by the Alef compilers.
- .PP
- Subroutines to be called from C should place their result in
- .CW R0 ,
- even if it is an address.
- Floating point values are returned in
- .CW F0 .
- Functions that return a structure to a C program
- receive as their first argument the address of the location to
- store the result;
- .CW R0
- is unused in the calling protocol for such procedures.
- A subroutine is responsible for saving its own registers,
- and therefore is free to use any registers without saving them (``caller saves'').
- .CW A6
- and
- .CW A7
- are the exceptions as described above.
- .SH
- When in doubt
- .PP
- If you get confused, try using the
- .CW -S
- option to
- .CW 2c
- and compiling a sample program.
- The standard output is valid input to the assembler.
- .SH
- Instructions
- .PP
- The instruction set of the assembler is not identical to that
- of the machine.
- It is chosen to match what the compiler generates, augmented
- slightly by specific needs of the operating system.
- For example,
- .CW 2a
- does not distinguish between the various forms of
- .CW MOVE
- instruction: move quick, move address, etc. Instead the context
- does the job. For example,
- .P1
- MOVL $1, R1
- MOVL A0, R2
- MOVW SR, R3
- .P2
- generates official
- .CW MOVEQ ,
- .CW MOVEA ,
- and
- .CW MOVESR
- instructions.
- A number of instructions do not have the syntax necessary to specify
- their entire capabilities. Notable examples are the bitfield
- instructions, the
- multiply and divide instructions, etc.
- For a complete set of generated instruction names (in
- .CW 2a
- notation, not Motorola's) see the file
- .CW /sys/src/cmd/2c/2.out.h .
- Despite its name, this file contains an enumeration of the
- instructions that appear in the intermediate files generated
- by the compiler, which correspond exactly to lines of assembly language.
- .SH
- Laying down instructions
- .PP
- The loader modifies the code produced by the assembler and compiler.
- It folds branches,
- copies short sequences of code to eliminate branches,
- and discards unreachable code.
- The first instruction of every function is assumed to be reachable.
- The pseudo-instruction
- .CW NOP ,
- which you may see in compiler output,
- means no instruction at all, rather than an instruction that does nothing.
- The loader discards all
- .CW NOP 's.
- .PP
- To generate a true
- .CW NOP
- instruction, or any other instruction not known to the assembler, use a
- .CW WORD
- pseudo-instruction.
- Such instructions on RISCs are not scheduled by the loader and must have
- their delay slots filled manually.
- .SH
- MIPS
- .PP
- The registers are only addressed by number:
- .CW R0
- through
- .CW R31 .
- .CW R29
- is the stack pointer;
- .CW R30
- is used as the static base pointer, the analogue of
- .CW A6
- on the 68020.
- Its value is the address of the global symbol
- .CW setR30(SB) .
- The register holding returned values from subroutines is
- .CW R1 .
- When a function is called, space for the first argument
- is reserved at
- .CW 0(FP)
- but in C (not Alef) the value is passed in
- .CW R1
- instead.
- .PP
- The loader uses
- .CW R28
- as a temporary. The system uses
- .CW R26
- and
- .CW R27
- as interrupt-time temporaries. Therefore none of these registers
- should be used in user code.
- .PP
- The control registers are not known to the assembler.
- Instead they are numbered registers
- .CW M0 ,
- .CW M1 ,
- etc.
- Use this trick to access, say,
- .CW STATUS :
- .P1
- #define STATUS 12
- MOVW M(STATUS), R1
- .P2
- .PP
- Floating point registers are called
- .CW F0
- through
- .CW F31 .
- By convention,
- .CW F24
- must be initialized to the value 0.0,
- .CW F26
- to 0.5,
- .CW F28
- to 1.0, and
- .CW F30
- to 2.0;
- this is done by the operating system.
- .PP
- The instructions and their syntax are different from those of the manufacturer's
- manual.
- There are no
- .CW lui
- and kin; instead there are
- .CW MOVW
- (move word),
- .CW MOVH
- (move halfword),
- and
- .CW MOVB
- (move byte) pseudo-instructions. If the operand is unsigned, the instructions
- are
- .CW MOVHU
- and
- .CW MOVBU .
- The order of operands is from left to right in dataflow order, just as
- on the 68020 but not as in MIPS documentation.
- This means that the
- .CW Bcond
- instructions are reversed with respect to the book; for example, a
- .CW va
- .CW BGTZ
- generates a MIPS
- .CW bltz
- instruction.
- .PP
- The assembler is for the R2000, R3000, and most of the R4000 and R6000 architectures.
- It understands the 64-bit instructions
- .CW MOVV ,
- .CW MOVVL ,
- .CW ADDV ,
- .CW ADDVU ,
- .CW SUBV ,
- .CW SUBVU ,
- .CW MULV ,
- .CW MULVU ,
- .CW DIVV ,
- .CW DIVVU ,
- .CW SLLV ,
- .CW SRLV ,
- and
- .CW SRAV .
- The assembler does not have any cache, load-linked, or store-conditional instructions.
- .PP
- Some assembler instructions are expanded into multiple instructions by the loader.
- For example the loader may convert the load of a 32 bit constant into an
- .CW lui
- followed by an
- .CW ori .
- .PP
- Assembler instructions should be laid out as if there
- were no load, branch, or floating point compare delay slots;
- the loader will rearrange\(em\f2schedule\f1\(emthe instructions
- to guarantee correctness and improve performance.
- The only exception is that the correct scheduling of instructions
- that use control registers varies from model to model of machine
- (and is often undocumented) so you should schedule such instructions
- by hand to guarantee correct behavior.
- The loader generates
- .P1
- NOR R0, R0, R0
- .P2
- when it needs a true no-op instruction.
- Use exactly this instruction when scheduling code manually;
- the loader recognizes it and schedules the code before it and after it independently. Also,
- .CW WORD
- pseudo-ops are scheduled like no-ops.
- .PP
- The
- .CW NOSCHED
- pseudo-op disables instruction scheduling
- (scheduling is enabled by default);
- .CW SCHED
- re-enables it.
- Branch folding, code copying, and dead code elimination are
- disabled for instructions that are not scheduled.
- .SH
- SPARC
- .PP
- Once you understand the Plan 9 model for the MIPS, the SPARC is familiar.
- Registers have numerical names only:
- .CW R0
- through
- .CW R31 .
- Forget about register windows: Plan 9 doesn't use them at all.
- The machine has 32 global registers, period.
- .CW R1
- [sic] is the stack pointer.
- .CW R2
- is the static base register, with value the address of
- .CW setSB(SB) .
- .CW R7
- is the return register and also the register holding the first
- argument to a C (not Alef) function, again with space reserved at
- .CW 0(FP) .
- .CW R14
- is the loader temporary.
- .PP
- Floating-point registers are exactly as on the MIPS.
- .PP
- The control registers are known by names such as
- .CW FSR .
- The instructions to access these registers are
- .CW MOVW
- instructions, for example
- .P1
- MOVW Y, R8
- .P2
- for the SPARC instruction
- .P1
- rdy %r8
- .P2
- .PP
- Move instructions are similar to those on the MIPS: pseudo-operations
- that turn into appropriate sequences of
- .CW sethi
- instructions, adds, etc.
- Instructions read from left to right. Because the arguments are
- flipped to
- .CW SUBCC ,
- the condition codes are not inverted as on the MIPS.
- .PP
- The syntax for the ASI stuff is, for example to move a word from ASI 2:
- .P1
- MOVW (R7, 2), R8
- .P2
- The syntax for double indexing is
- .P1
- MOVW (R7+R8), R9
- .P2
- .PP
- The SPARC's instruction scheduling is similar to the MIPS's.
- The official no-op instruction is:
- .P1
- ORN R0, R0, R0
- .P2
- .SH
- i960
- .PP
- Registers are numbered
- .CW R0
- through
- .CW R31 .
- Stack pointer is
- .CW R29 ;
- return register is
- .CW R4 ;
- static base is
- .CW R28 ;
- it is initialized to the address of
- .CW setSB(SB) .
- .CW R3
- must be zero; this should be done manually early in execution by
- .P1
- SUBO R3, R3
- .P2
- .CW R27
- is the loader temporary.
- .PP
- There is no support for floating point.
- .PP
- The Intel calling convention is not supported and cannot be used; use
- .CW BAL
- instead.
- Instructions are mostly as in the book. The major change is that
- .CW LOAD
- and
- .CW STORE
- are both called
- .CW MOV .
- The extension character for
- .CW MOV
- is as in the manual:
- .CW O
- for ordinal,
- .CW W
- for signed, etc.
- .SH
- i386
- .PP
- The assembler assumes 32-bit protected mode.
- The register names are
- .CW SP ,
- .CW AX ,
- .CW BX ,
- .CW CX ,
- .CW DX ,
- .CW BP ,
- .CW DI ,
- and
- .CW SI .
- The stack pointer (not a pseudo-register) is
- .CW SP
- and the return register is
- .CW AX .
- There is no physical frame pointer but, as for the MIPS,
- .CW FP
- is a pseudo-register that acts as
- a frame pointer.
- .PP
- Opcode names are mostly the same as those listed in the Intel manual
- with an
- .CW L ,
- .CW W ,
- or
- .CW B
- appended to identify 32-bit,
- 16-bit, and 8-bit operations.
- The exceptions are loads, stores, and conditionals.
- All load and store opcodes to and from general registers, special registers
- (such as
- .CW CR0,
- .CW CR3,
- .CW GDTR,
- .CW IDTR,
- .CW SS,
- .CW CS,
- .CW DS,
- .CW ES,
- .CW FS,
- and
- .CW GS )
- or memory are written
- as
- .P1
- MOV\f2x\fP src,dst
- .P2
- where
- .I x
- is
- .CW L ,
- .CW W ,
- or
- .CW B .
- Thus to get
- .CW AL
- use a
- .CW MOVB
- instruction. If you need to access
- .CW AH ,
- you must mention it explicitly in a
- .CW MOVB :
- .P1
- MOVB AH, BX
- .P2
- There are many examples of illegal moves, for example,
- .P1
- MOVB BP, DI
- .P2
- that the loader actually implements as pseudo-operations.
- .PP
- The names of conditions in all conditional instructions
- .CW J , (
- .CW SET )
- follow the conventions of the 68020 instead of those of the Intel
- assembler:
- .CW JOS ,
- .CW JOC ,
- .CW JCS ,
- .CW JCC ,
- .CW JEQ ,
- .CW JNE ,
- .CW JLS ,
- .CW JHI ,
- .CW JMI ,
- .CW JPL ,
- .CW JPS ,
- .CW JPC ,
- .CW JLT ,
- .CW JGE ,
- .CW JLE ,
- and
- .CW JGT
- instead of
- .CW JO ,
- .CW JNO ,
- .CW JB ,
- .CW JNB ,
- .CW JZ ,
- .CW JNZ ,
- .CW JBE ,
- .CW JNBE ,
- .CW JS ,
- .CW JNS ,
- .CW JP ,
- .CW JNP ,
- .CW JL ,
- .CW JNL ,
- .CW JLE ,
- and
- .CW JNLE .
- .PP
- The addressing modes have syntax like
- .CW AX ,
- .CW (AX) ,
- .CW (AX)(BX*4) ,
- .CW 10(AX) ,
- and
- .CW 10(AX)(BX*4) .
- The offsets from
- .CW AX
- can be replaced by offsets from
- .CW FP
- or
- .CW SB
- to access names, for example
- .CW extern+5(SB)(AX*2) .
- .PP
- Other notes: Non-relative
- .CW JMP
- and
- .CW CALL
- have a
- .CW *
- added to the syntax.
- Only
- .CW LOOP ,
- .CW LOOPEQ ,
- and
- .CW LOOPNE
- are legal loop instructions. Only
- .CW REP
- and
- .CW REPN
- are recognized repeaters. These are not prefixes, but rather
- stand-alone opcodes that precede the strings, for example
- .P1
- CLD; REP; MOVSL
- .P2
- Segment override prefixes in
- .CW MOD/RM
- fields are not supported.
- .SH
- AMD64
- .PP
- The assembler assumes 64-bit mode unless a
- .CW MODE
- pseudo-operation is given:
- .P1
- MODE $32
- .P2
- to change to 32-bit mode.
- The effect is mainly to diagnose instructions that are illegal in
- the given mode, but the loader will also assume 32-bit operands and addresses,
- and 32-bit PC values for call and return.
- The assembler's conventions are similar to those for the 386, above.
- The architecture provides extra fixed-point registers
- .CW R8
- to
- .CW R15 .
- All registers are 64 bit, but instructions access low-order 8, 16 and 32 bits
- as described in the processor handbook.
- For example,
- .CW MOVL
- to
- .CW AX
- puts a value in the low-order 32 bits and clears the top 32 bits to zero.
- Literal operands are limited to signed 32 bit values, which are sign-extended
- to 64 bits in 64 bit operations; the exception is
- .CW MOVQ ,
- which allows 64-bit literals.
- The external registers in Plan 9's C are allocated from
- .CW R15
- down.
- .PP
- There are many new instructions, including the MMX and XMM media instructions,
- and conditional move instructions.
- MMX registers are
- .CW M0
- to
- .CW M7 ,
- and
- XMM registers are
- .CW X0
- to
- .CW X15 .
- As with the 386 instruction names,
- all new 64-bit integer instructions, and the MMX and XMM instructions
- uniformly use
- .CW L
- for `long word' (32 bits) and
- .CW Q
- for `quad word' (64 bits).
- Some instructions use
- .CW O
- (`octword') for 128-bit values, where the processor handbook
- variously uses
- .CW O
- or
- .CW DQ .
- The assembler also consistently uses
- .CW PL
- for `packed long' in
- XMM instructions, instead of
- .CW Q ,
- .CW DQ
- or
- .CW PI .
- Either
- .CW MOVL
- or
- .CW MOVQ
- can be used to move values to and from control registers, even when
- the registers might be 64 bits.
- The assembler often accepts the handbook's name to ease conversion
- of existing code (but remember that the operand order is uniformly
- source then destination).
- .PP
- C's
- .CW long
- .CW long
- type is 64 bits, but passed and returned by value, not by reference.
- More notably, C pointer values are 64 bits, and thus
- .CW long
- .CW long
- and
- .CW unsigned
- .CW long
- .CW long
- are the only integer types wide enough to hold a pointer value.
- The C compiler and library use the XMM floating-point instructions, not
- the old 387 ones, although the latter are implemented by assembler and loader.
- Unlike the 386, the first integer or pointer argument is passed in a register, which is
- .CW BP
- for an integer or pointer (it can be referred to in assembly code by the pseudonym
- .CW RARG ).
- .CW AX
- holds the return value from subroutines as before.
- Floating-point results are returned in
- .CW X0 ,
- although currently the first floating-point parameter is not passed in a register.
- All parameters less than 8 bytes in length have 8 byte slots reserved on the stack
- to preserve alignment and simplify variable-length argument list access,
- including the first parameter when passed in a register,
- even though bytes 4 to 7 are not initialized.
- .
- .SH
- Power PC
- .PP
- The Power PC follows the Plan 9 model set by the MIPS and SPARC,
- not the elaborate ABIs.
- The 32-bit instructions of the 60x and 8xx PowerPC architectures are supported;
- there is no support for the older POWER instructions.
- Registers are
- .CW R0
- through
- .CW R31 .
- .CW R0
- is initialized to zero; this is done by C start up code
- and assumed by the compiler and loader.
- .CW R1
- is the stack pointer.
- .CW R2
- is the static base register, with value the address of
- .CW setSB(SB) .
- .CW R3
- is the return register and also the register holding the first
- argument to a C function, with space reserved at
- .CW 0(FP)
- as on the MIPS.
- .CW R31
- is the loader temporary.
- The external registers in Plan 9's C are allocated from
- .CW R30
- down.
- .PP
- Floating point registers are called
- .CW F0
- through
- .CW F31 .
- By convention, several registers are initialized
- to specific values; this is done by the operating system.
- .CW F27
- must be initialized to the value
- .CW 0x4330000080000000
- (used by float-to-int conversion),
- .CW F28
- to the value 0.0,
- .CW F29
- to 0.5,
- .CW F30
- to 1.0, and
- .CW F31
- to 2.0.
- .PP
- As on the MIPS and SPARC, the assembler accepts arbitrary literals
- as operands to
- .CW MOVW ,
- and also to
- .CW ADD
- and others where `immediate' variants exist,
- and the loader generates sequences
- of
- .CW addi ,
- .CW addis ,
- .CW oris ,
- etc. as required.
- The register indirect addressing modes use the same syntax as the SPARC,
- including double indexing when allowed.
- .PP
- The instruction names are generally derived from the Motorola ones,
- subject to slight transformation:
- the
- .CW . ' `
- marking the setting of condition codes is replaced by
- .CW CC ,
- and when the letter
- .CW o ' `
- represents `OE=1' it is replaced by
- .CW V .
- Thus
- .CW add ,
- .CW addo.
- and
- .CW subfzeo.
- become
- .CW ADD ,
- .CW ADDVCC
- and
- .CW SUBFZEVCC .
- As well as the three-operand conditional branch instruction
- .CW BC ,
- the assembler provides pseudo-instructions for the common cases:
- .CW BEQ ,
- .CW BNE ,
- .CW BGT ,
- .CW BGE ,
- .CW BLT ,
- .CW BLE ,
- .CW BVC ,
- and
- .CW BVS .
- The unconditional branch instruction is
- .CW BR .
- Indirect branches use
- .CW "(CTR)"
- or
- .CW "(LR)"
- as target.
- .PP
- Load or store operations are replaced by
- .CW MOV
- variants in the usual way:
- .CW MOVW
- (move word),
- .CW MOVH
- (move halfword with sign extension), and
- .CW MOVB
- (move byte with sign extension, a pseudo-instruction),
- with unsigned variants
- .CW MOVHZ
- and
- .CW MOVBZ ,
- and byte-reversing
- .CW MOVWBR
- and
- .CW MOVHBR .
- `Load or store with update' versions are
- .CW MOVWU ,
- .CW MOVHU ,
- and
- .CW MOVBZU .
- Load or store multiple is
- .CW MOVMW .
- The exceptions are the string instructions, which are
- .CW LSW
- and
- .CW STSW ,
- and the reservation instructions
- .CW lwarx
- and
- .CW stwcx. ,
- which are
- .CW LWAR
- and
- .CW STWCCC ,
- all with operands in the usual data-flow order.
- Floating-point load or store instructions are
- .CW FMOVD ,
- .CW FMOVDU ,
- .CW FMOVS ,
- and
- .CW FMOVSU .
- The register to register move instructions
- .CW fmr
- and
- .CW fmr.
- are written
- .CW FMOVD
- and
- .CW FMOVDCC .
- .PP
- The assembler knows the commonly used special purpose registers:
- .CW CR ,
- .CW CTR ,
- .CW DEC ,
- .CW LR ,
- .CW MSR ,
- and
- .CW XER .
- The rest, which are often architecture-dependent, are referenced as
- .CW SPR(n) .
- The segment registers of the 60x series are similarly
- .CW SEG(n) ,
- but
- .I n
- can also be a register name, as in
- .CW SEG(R3) .
- Moves between special purpose registers and general purpose ones,
- when allowed by the architecture,
- are written as
- .CW MOVW ,
- replacing
- .CW mfcr ,
- .CW mtcr ,
- .CW mfmsr ,
- .CW mtmsr ,
- .CW mtspr ,
- .CW mfspr ,
- .CW mftb ,
- and many others.
- .PP
- The fields of the condition register
- .CW CR
- are referenced as
- .CW CR(0)
- through
- .CW CR(7) .
- They are used by the
- .CW MOVFL
- (move field) pseudo-instruction,
- which produces
- .CW mcrf
- or
- .CW mtcrf .
- For example:
- .P1
- MOVFL CR(3), CR(0)
- MOVFL R3, CR(1)
- MOVFL R3, $7, CR
- .P2
- They are also accepted in
- the conditional branch instruction, for example
- .P1
- BEQ CR(7), label
- .P2
- Fields of the
- .CW FPSCR
- are accessed using
- .CW MOVFL
- in a similar way:
- .P1
- MOVFL FPSCR, F0
- MOVFL F0, FPSCR
- MOVFL F0, $7, FPSCR
- MOVFL $0, FPSCR(3)
- .P2
- producing
- .CW mffs ,
- .CW mtfsf
- or
- .CW mtfsfi ,
- as appropriate.
- .SH
- ARM
- .PP
- The assembler provides access to
- .CW R0
- through
- .CW R14
- and the
- .CW PC .
- The stack pointer is
- .CW R13 ,
- the link register is
- .CW R14 ,
- and the static base register is
- .CW R12 .
- .CW R0
- is the return register and also the register holding
- the first argument to a subroutine.
- The external registers in Plan 9's C are allocated from
- .CW R10
- down.
- .CW R11
- is used by the loader as a temporary register.
- The assembler supports the
- .CW CPSR
- and
- .CW SPSR
- registers.
- It also knows about coprocessor registers
- .CW C0
- through
- .CW C15 .
- Floating registers are
- .CW F0
- through
- .CW F7 ,
- .CW FPSR
- and
- .CW FPCR .
- .PP
- As with the other architectures, loads and stores are called
- .CW MOV ,
- e.g.
- .CW MOVW
- for load word or store word, and
- .CW MOVM
- for
- load or store multiple,
- depending on the operands.
- .PP
- Addressing modes are supported by suffixes to the instructions:
- .CW .IA
- (increment after),
- .CW .IB
- (increment before),
- .CW .DA
- (decrement after), and
- .CW .DB
- (decrement before).
- These can only be used with the
- .CW MOV
- instructions.
- The move multiple instruction,
- .CW MOVM ,
- defines a range of registers using brackets, e.g.
- .CW [R0-R12] .
- The special
- .CW MOVM
- addressing mode bits
- .CW W ,
- .CW U ,
- and
- .CW P
- are written in the same manner, for example,
- .CW MOVM.DB.W .
- A
- .CW .S
- suffix allows a
- .CW MOVM
- instruction to access user
- .CW R13
- and
- .CW R14
- when in another processor mode.
- Shifts and rotates in addressing modes are supported by binary operators
- .CW <<
- (logical left shift),
- .CW >>
- (logical right shift),
- .CW ->
- (arithmetic right shift), and
- .CW @>
- (rotate right); for example
- .CW "R7>>R2" or
- .CW "R2@>2" .
- The assembler does not support indexing by a shifted expression;
- only names can be doubly indexed.
- .PP
- Any instruction can be followed by a suffix that makes the instruction conditional:
- .CW .EQ ,
- .CW .NE ,
- and so on, as in the ARM manual, with synonyms
- .CW .HS
- (for
- .CW .CS )
- and
- .CW .LO
- (for
- .CW .CC ),
- for example
- .CW ADD.NE .
- Arithmetic
- and logical instructions
- can have a
- .CW .S
- suffix, as ARM allows, to set condition codes.
- .PP
- The syntax of the
- .CW MCR
- and
- .CW MRC
- coprocessor instructions is largely as in the manual, with the usual adjustments.
- The assembler directly supports only the ARM floating-point coprocessor
- operations used by the compiler:
- .CW CMP ,
- .CW ADD ,
- .CW SUB ,
- .CW MUL ,
- and
- .CW DIV ,
- all with
- .CW F
- or
- .CW D
- suffix selecting single or double precision.
- Floating-point load or store become
- .CW MOVF
- and
- .CW MOVD .
- Conversion instructions are also specified by moves:
- .CW MOVWD ,
- .CW MOVWF ,
- .CW MOVDW ,
- .CW MOVWD ,
- .CW MOVFD ,
- and
- .CW MOVDF .
|