HAL Assembler User Guide
------------------------

This user guide describes an assembler for the Alpha family of products.  It 
refers to features available in HAL version 0.19 and PP version 1.4



	Copyright (c) 1992
	Digital Equipment Corporation, Maynard, Massachusetts 01754

	The HAL Assembler is free software; you can redistribute it and/or 
	modify it with the sole restriction that this copyright notice be 
	attached.

	The information in this software is subject to change without notice 
	and should not be construed as a commitment by Digital Equipment
	Corporation.

	The author disclaims all warranties with regard to this software,
	including all implied warranties of merchantability and fitness, in
	no event shall he be liable for any special, indirect or consequential
	damages or any damages whatsoever resulting from loss of use, data, 
	or profits, whether in an action of contract, negligence or other
	tortious action, arising out of or in connection with the use or
	performance of this software.




The HAL Assembler is a simple, portable assembler which generates a binary 
image ready to be loaded directly into memory and executed.  It supports the 
full instruction set used by the DECchip 21064, and uses a syntax based on the 
VAX Macro-32 Assembler.  Its main feature is portability to any platform 
supporting a C compiler.  

The assembler consists of two parts - a pre-processor phase which converts 
many syntactical quirks and assembler directives into a consistent form, 
followed by the assembly phase which actually converts the mnemonics into 
machine code.  For now, these two phases must be invoked separately.

To use the assembler:

VMS:
	$pp  :== $pp.exe
	$hal :== $hal.exe
	$pp filename.mar -o temp_filename
	$hal temp_filename filename.exe -list filename.lis



U*IX:
	pp filename.mar -o temp_filename
	hal temp_filename  filename.exe  -list filename.lis




The following command qualifiers are legal:

$pp filename.mar 		-o temp_filename     (name of intermediate file)
				-d		     (affects interpretation of)
						      (instruction counter)
				-q		     (quiet mode)


$hal temp_filename filename.exe -list filename 		 (generate listing file)
				-system	^xstart_address  (defaults to 0)
				-size bytes		 (defaults to 40,000)
				-verbose	         (debugging info)



General Comments
----------------

The HAL assembler generates a loadable binary image directly.  The generation 
of object modules is not supported, nor is modular assembly or linking.  The 
maximum allowed program size is 2**32 bytes.  However, the base address of the 
program can be relocated anywhere within a 2**64 byte region.

The HAL assembler is not case sensitive.  This applies to all assembler 
directives and radix control characters, as well as user-defined symbols.

The maximum allowed line length for any source line is 1024 characters.  A 
carriage-return/form-feed always terminates the current line.  No line 
continuation character exists.

A longword is a 32-bit value (4 bytes).  A quadword is a 64-bit value (8 
bytes).



Command Line Qualifiers
-----------------------

PP  (Pre-Processor phase)
-o filename
   Specifies the name of the intermediate file generated by the pre-processor.
   This should be the same name given to the HAL input line.

-d 
   Instruction counter (dot) control.
   This switch changes the interpretation of the current instruction counter
   (see below for description of current instruction counter (.) symbol).
   By default, upon entering an instruction the current instruction counter 
   is incremented to the next location.  Therefore, any use of the current 
   instruction counter by an instruction refers to the following instruction.
   If the -d switch is used, the current instruction counter is not incremented 
   until after the instruction.  Therefore, any use of the current instruction 
   counter by an instruction refers to the current instruction.

   The default mode is compatible with the VAX Macro-32 assembler.  It is 
   recommended that programs which require the non-default mode of this option 
   clearly state such a requirement in the source file.



-q
   Quiet mode.  This switch suppresses informational messages.  This is 
   useful when piping PP output directly into HAL.




HAL (Assemble/Link phase)
-list:	
   Generates a listing file and symbol table.  The listing file is based on 
   the pre-processor output, not the original source file.  Although this is a 
   useful listing, the user should be aware of its basis.


-system ^xstart_address
   This identifies the starting address of the first instruction.  All labels 
   are relocated by the appropriate offset.  The start address must be a 64-bit 
   longword aligned value, and must be in hex form (i.e. ^x10000).  If not 
   supplied, the start address defaults to zero.

   Note that there is no header information in the executable file, and 
   therefore no mechanism for informing a loader where the executable image 
   should be loaded in memory.  The user is responsible for ensuring the 
   starting address of the assembly and the starting address of the loaded 
   image are consistent.

-size bytes
   This flag limits the maximum size that can be generated for the executable 
   image.  It is available for use on machines with a limited amount of main 
   memory.  The default value is 40,000 bytes.  If the limit is exceeded, 
   the assembler will exit with a message indicating the problem.

-verbose
   This flag turns on debugging messages.  Its use is not recommended for 
   the casual user.




Syntax
------

The syntax of a HAL input line is:
	LABEL:	OPERATOR  OPERAND(S)   ;COMMENT



Label field - A label is a symbol which defines a location in a program.  The 
label cannot be a value or expression, and must end with a colon (:).

Operator field - The operator specifies the action to be performed by this 
statement; this can be an instruction, an assembler directive, or a macro.
If an instruction, any valid Alpha instruction is legal.

Operand field - Contains the instruction operands, assembler directive
arguments, or macro arguments.

Comment field - anything following a semi-colon is ignored until a new line 
is reached.


The label and comment fields are optional.


User-defined symbols are character strings which can be used as labels, can be
equated to a specific value by a direct assignment statement, or can be used in 
expressions.  Only one symbol can be defined per line.

The following syntax applies for a direct assignment statement:

	symbol = expression


Constants are supported in decimal, hex, binary, or octal.  The default 
base is decimal.  To use a different base, the constant must be preceded 
by ^x or ^X (hex), ^b or ^B (binary), ^o or ^O (octal).

The symbol for the current instruction counter is the period (.).  It always 
has the value of the longword currently being assembled.  Every source 
statement that allocates memory increments the current instruction counter by 
the number of longwords used.  The current instruction counter can be 
explicitly set by a direct assignment statement.  The instruction counter can 
be incremented or decremented (i.e.  ". = . + 4"  is a legal statement)  The 
initial value of the instruction counter is zero, unless the -system qualifier 
is used (on the HAL command line) to relocate the starting address.  The 
point at which the current instruction counter is incremented (before
assembling an instruction or after assembling an instruction) can be
controlled by a command line switch (see command line switches above).


Expressions are combinations of terms joined by binary operators.  A term can 
be an immediate value, a symbol, or the current instruction counter.  
Expressions are evaluated as 64-bit values.  Expressions are evaluated from 
left to right with no operator precedence rules.  However, angle brackets (<>) 
can be used to change the order of evaluation.  The expressions may use the 
following operators:
	add (+)
	subtract (-)
	and (&)
	or (|)
	shift left (@)  (use a negative value to shift right)
	one's complement (^c)





Implementation-specific Opcodes

The assembler  supports the five 21064 implementation-specific opcodes 
(HW_MFPR, HW_MTPR, HW_REI, HW_LD, and HW_ST).  These opcodes are valid only 
when operating in PAL mode, or when the HWE bit in the ICSR register is set.
(See the 21064 documentation for further information.)  The syntax for using
these instructions is described below.


	HW_MFPR reg_num, IPR_num_or_name
	HW_MTPR reg_num, IPR_num_or_name

	HW_REI

	HW_LD	reg_num, disp(base_reg), qualifier
	HW_ST	reg_num, disp(base_reg), qualifier



When an Internal Processor Register (IPR) number is required, the assembler
will accept either an absolute number, or the name/mnemonic defined in the 
21064 documentation for each register.

The qualifier is a value between 0 and 15 which is used to set the control
bits <15:12> of the opcode.  

An alternative syntax for invoking the HW_LD and HW_ST instructions is also
provided.  This syntax codes the control bit settings directly into the
opcode.  Note that these are NOT standard, user-mode LD/ST instructions, but
are an alternate syntax for the HW_LD and HW_ST instructions.


	LDL/P		Hardware load, longword, physical
	LDL/V		Hardware load, longword, virtual
	LDL/A		Hardware load, longword, virtual, altmode
	LDL/W		Hardware load, longword, virtual, write-check
	LDL/AW		Hardware load, longword, virtual, altmode, write-check
	LDL/PL		Hardware load, longword, physical, locked

	LDQ/P		Hardware load, quadword, physical
	LDQ/V		Hardware load, quadword, virtual
	LDQ/A		Hardware load, quadword, virtual, altmode
	LDQ/W		Hardware load, quadword, virtual, write-check
	LDQ/AW		Hardware load, quadword, virtual, altmode, write-check
	LDQ/PL		Hardware load, quadword, physical, locked

	STL/P		Hardware store, longword, physical
	STL/V		Hardware store, longword, virtual
	STL/A		Hardware store, longword, virtual, altmode
	STL/PC		Hardware store, longword, physical, conditional

	STQ/P		Hardware store, quadword, physical
	STQ/V		Hardware store, quadword, virtual
	STQ/A		Hardware store, quadword, virtual, altmode
	STQ/PC		Hardware store, quadword, physical, conditional



examples:

	HW_MTPR r1, itb_pte
	HW_MFPR r0, exc_sum
	HW_LD	r2, 8(r20), 0
	HW_ST	r0, 0(r0), 8
	LDQ/P	R5, 12(R10)









The following assembler directives are supported:

.ADDRESS  address_label
	Stores a quadword address.

.ALIGN value  [,filler]
	Value may be "long", "quad", or any expression which can be evaluated 
	at compile time.  If a constant is used, the current instruction 
	counter is aligned at an address that is the power of 2 raised to the 
	value of the constant (i.e. ".align 5"  will align to a 2**5 = 32 byte 
	block).  Note that it is illegal to align to less than a longword.

	If the desired alignment requires incrementing the current instruction 
	counter, the skipped locations are filled with zero, by default.  
	Instead of using zero, the 'filler' parameter can be any compile-time 
	constant longword expression.  The value of this expression is used to 
	fill the skipped locations.  (Using a filler equal to a NOP opcode is 
	useful when adjusting alignments within the Istream.)


.ASCII "string"
	Stores the ASCII value of each character in the ASCII string.  If 
	the last byte of the string is not longword aligned, zeros will 
	be padded until a longword alignment is reached.  The string must 
	be enclosed in double quotes.


.ASCIZ "string"
	This directive is the same as the .ASCII directive, except a null 
	byte (zero) is guaranteed to be appended to the end of the string.
	The string must be enclosed in double quotes.

.BLKL expression
	Reserves a data block equal to the number of longwords represented 
	by the expression parameter.

.BLKQ expression
	Reserves a data block equal to the number of quadwords represented 
	by the expression parameter.



.END
	This directive must be placed at the end of the file to be assembled.


.IF condition argument
	conditionally-assembled code block
.ENDC                   

	If the specified condition is met, the instructions included in 
	the range are assembled.  The conditions that can be tested are:
	    eq:  equal to zero 		ne:  not equal to zero
	    lt:  less than zero		ge:  greater than or equal to zero
	    gt:  greater than zero	le:  less than or equal to zero
	    df:  symbol is defined	ndf: symbol is not defined

	Sub-conditional assembly blocks are supported.  The implied argument 
	to sub-conditionals is the condition test specified by the main .IF 
	conditional.  These do not re-test the argument, but merely allow 
	additional decisions based on the original argument.  Sub-conditionals 
	may only appear within the range of an .IF statement.

	Supported sub-conditionals are
	    .if_false
	    .if_true
	    .if_true_false   (always evaluates to true)

	Nested .IF statements are allowed.


.IIF condition, argument, statement
	The 'immediate if' statement provides a means of writing a one-line 
	conditional assembly block.  The legal test conditions are the same 
	as those specified for the .IF statement above.  The argument is 
	tested and, if the condition is met, the statement parameter is
	assembled.  No terminating .ENDC is needed.




.INCLUDE "filename"
	The specified file is included as part of the source file to be 
	assembled.


.LONG expression [,expression...]
	Generates a longword (4 bytes) of data for each comma-delimited 
  	expression.


.QUAD expression [,expression...]
	Generates a quadword (8 bytes) of data for each comma-delimited 
	expression.


.REPEAT expression
	repeated code block
.ENDR

	Repeats a block of code for the number of times determined by the 
	value of the expression.




Macro Capability
----------------

.MACRO macro_name [,formal-argument-list]
	macro contents
.ENDM [macro_name]


(See example at the end of this section.)


Macros provide a means for replacing a single source line with a sequence 
of replacement source lines.  This provides a capability similar to a 
subroutine, except the substitution occurs in-line.

A macro definition contains the replacement source lines.  The definition 
can optionally have formal arguments.  These formal arguments can be used 
throughout the sequence of source lines.  Later, the formal arguments are 
replaced by the actual arguments in the macro call.  Multiple arguments are 
allowed, with each argument separated by a comma.

The macro call consists of the macro name optionally followed by actual 
arguments.  The assembler replaces the line containing the macro call with 
the source lines in the macro definition.  It replaces any occurrences of 
formal arguments in the macro definition with the actual arguments specified 
in the macro call.  This process is called the macro expansion.

Formal and actual arguments maintain a strict positional relationship.  That 
is, the first actual argument in a macro call replaces all occurrences of the 
first formal argument in the macro definition.  Default argument values 
are accepted.  The default value is used when no value for a formal argument 
is specified in the macro call.  The syntax for using a default argument 
value is 'formal_arg=default_value'.

String arguments must be enclosed by delimiters, which are a pair of angle 
brackets (<>).  The following is a single string argument:
    <Hello There>

The argument concatenation operator, the apostrophe ('), concatenates a 
macro argument with some constant text.  Apostrophes can either precede 
or follow a formal argument name in the macro source.  If an apostrophe 
precedes the argument name, the text before the apostrophe is concatenated 
with the actual argument when the macro is expanded.  If an apostrophe follows 
the formal argument name, the actual argument is concatenated with the text 
that follows the apostrophe when the macros is expanded.  Note that the 
apostrophe itself does not appear in the macro expansion
      
To concatenate two arguments, separate the two formal arguments with two 
successive apostrophes.

When using labels within a macro, multiple uses of the macro may lead to 
multiple instances of the same label name, which is illegal.  Created local 
labels are useful in this case.  The assembler creates local labels in the 
macro expansion which will not conflict with other labels.

Created local labels range from 30000$ through 65535$.  Each time the
assembler creates a new local label, it increments the numeric part of the 
label name by 1.  Consequently, no user-defined labels should be in the 
range of 30000$ to 65535$.

A created local label is specified by a question mark (?) in front of the 
formal argument name.  When the macro is expanded, the assembler creates 
a new local label if the corresponding actual argument is blank.  If the 
corresponding actual argument is specified, the assembler substitutes the 
actual argument for the formal argument.

Macro string operators are supplied to perform string manipulations on macro 
arguments and ASCII strings.  They can be used only within macros.  The three 
supported string operators are %length(), %locate(), and %extract().


   %LENGTH(string)
	
	Returns the length of a string.

	(The value of %length(<abcde>) is 5)


   %LOCATE(sub_string, string)

	Locates a sub-string within a string.  The first parameter is the 
	substring, and the second parameter is the string to be searched.
	If a match is found, the character position of the first character 
	in the string is returned.  Note that the first character position 
	of a string is 0.  If a match is not found, it returns a value equal 
	to the length of the string.
	
	(The value of %locate(<D>, <ABCDEF>) is 3)


   %EXTRACT(start, length, string)

	Extracts a substring from a string.  It returns the substring that 
	begins at the specified position and is of the specified length. 
	Note that the first character in a string is in position 0.  If 
	the length goes beyond the end of the string, the extraction will 
	stop at the end of the string.

	(The value of %extract(2,3,<ABCDEF>) is CDE)





Example of macro use:

.MACRO STORE arg1, arg2=12, arg3=0, ?l2
    test'arg1':
	.long arg2
    l2:
	.quad arg3
.ENDM STORE


In this example, arg2 defaults to 12, arg3 defaults to 0.  The first label 
is created using argument concatenation.  The second label is automatically 
created using the local label feature.  A possible use of the macro would be:


	STORE 1, 5

which would expand to 

    test1:
	.long 5
    30000$:
	.quad 0











Features planned, but not yet supported:

 - limited Psect support






Other Information:


  We would appreciate knowing about problems, bugs, enhancement suggestions,
  or other comments related to the assembler.  However, please remember this
  is a free-ware product which is distributed without support and no warranty 
  of fitness for use.  We will do our best to respond to all requests, but
  make no promise of acknowledging or fixing any problem.

  All comments and problem reports can be sent via E-Mail to:

     assembler@ricks.enet.dec.com





  The source code for the pre-processor and the assembler is available via 
  anonymous FTP from any of the following hosts:

	gatekeeper.dec.com

	crl.dec.com

	decuac.dec.com


  The directory is /pub/DEC/Alpha/assembler






Notes for Macro-32 users:
       
The assembler directives .byte and .word are not supported.

Operate-format instructions which use immediate values (in place of the 
Rb operand) must be preceded by a #.  



Example

The following source file is to be assembled.  It is a simple example which 
initializes several registers.  





start:
	hwe_check = 0		;used by IF statement below




				; this code section illustrates using basic 
				; operations, plus labels

	; Init the excSum

	lda	r1, 64(r31)	; load counter
10$:	hw_mfpr	r0, exc_sum	; read and clear a bit
	subq	r1, #1, r1
	bgt	r1, 10$		; loop until done

	hw_mtpr	r31, exc_sum	; clear the exc bits



				; this code section illustrates using the 
				; .IF assembler directive, and a sub-conditional

	; Init the ICCSR

.IF eq hwe_check		;If hwe_check is zero, the HWE bit in the
	lda	r0, ^x5f8(r31)  ;ICCSR is set.  Else its cleared.
	sll	r0, #32, r0
	hw_mtpr	r0, iccsr

.if_false
	lda	r0, ^x4f8(r31)
	sll	r0, #32, r0
	hw_mtpr	r0, iccsr
.ENDC                   



				; this illustrates alignment and data storage
				; directives



	.align	quad
ROM_addr:
	.quad	^x80000000	; default ROM starting address


user_init:
	ret	r31, (r21)		; branch back to main line code

.end






To assemble this example, the following steps would be used:

Extract the code and call it "test.mar"

VMS:

  $pp  :== $pp.exe
  $hal :== $hal.exe
  $pp test.mar -o test.out
  $hal test.out test.exe  -list test.lis


UxIX:

  pp test.mar | hal -  test.exe -list test.lis


This creates the actual executable image (test.exe) and a listing file
(test.lis).  The listing file for the above example is:


Listing for: test.out
Start=00000000 00000000 End=00000000 0000002C
                      1: start:
                      2: 
                      3: 
                      4: debug_mode%0 = ^x0000000000000000  
                      5:           ;used by IF statement below
                      6:                                 ;If debug_mode is zero, the HWE bit in the
                      7:                                 ;ICCSR is set.  Else its cleared.
                      8: 
                      9: 
                     10: 
                     11: 
                     12: 
                     13:                                 ; this code section illustrates using basic
                     14:                                 ; operations, plus labels
                     15: 
                     16:         ; Init the excSum
                     17: 
[00000000] 203F0040  18:         lda     r1,^x0000000000000040(r31)     ; load counter
[00000004] 6400002A  19: 10$:    hw_mfpr r0,exc_sum     ; read and clear a bit
[00000008] 40203521  20:         subq    r1, #^x0000000000000001, r1
[0000000C] FC3FFFFD  21:         bgt     r1,10$         ; loop until done
                     22: 
[00000010] 77FF002A  23:         hw_mtpr r31,exc_sum    ; clear the exc bits
                     24: 
                     25: 
                     26: 
                     27:                                 ; this code section illustrates using the
                     28:                                 ; .IF assembler directive, and a sub-conditional
                     29:         ; Init the ICCSR
                     30: 
                     31: 
[00000014] 201F05F8  32:         lda     r0,^x00000000000005F8(r31)
[00000018] 48041720  33:         sll     r0, #^x0000000000000020, r0
[0000001C] 74000022  34:         hw_mtpr r0,iccsr
                     35: 
                     36: 
                     37: 
                     38:                                 ; this illustrates alignment and data storage
                     39:                                 ; directives
                     40: 
                     41: 
                     42: 
                     43:         .align  ^x0000000000000007
                     44: ROM_addr:
[00000020] 80000000 
[00000024] 00000000  45:         .quad   ^x0000000080000000      ; default ROM starting address
                     46: 
                     47: 
                     48: user_init:
[00000028] 6BF58000  49:         ret     r31,(r21)              ; branch back to main line code
[0000002C] 00000000  50: 
[00000030] 00000000  51: .end
[00000034] 00000000  52: 
[00000038] 00000000  53: 
**********************************************************
**Symbol Table *******************************************
**********************************************************
10$                            ->[00000000 00000004]
		Used as Branch Displacement at (ic) 3
ROM_addr                       ->[00000000 00000020]
debug_mode%0                   ->[00000000 00000000]
start                          ->[00000000 00000000]
user_init                      ->[00000000 00000028]

