Z8000_AS(1)

NAME
z8000_as - assembler for Zilog z8000 (segmented version)

SYNOPSIS
/usr/em/lib/z8000_as [options] argument ...

DESCRIPTION
This assembler is made with the general framework described in uni_ass(6).

SYNTAX

instructions
    Instruction mnemonics are implemented exactly as described in `Z8000 PLZ/ASM Assembly Language Programming Manual' and `AmZ8001/2 Processor Instruction Set'.

registers
    The z8000 has sixteen 16-bit general purpose registers specified as R0 through R15. All sixteen registers can be used as accumulators. In addition to this, fifteen of the sixteen registers may be used in addressing mode calculations as either indirect, index or base-address registers. Because the instruction format encoding uses the value zero to differentiate between various addressing modes, register R0 (or the register pair RR0) cannot be used as an indirect, index or base-address register. It is also possible to address registers as groups of 8, 32 or 64 bits. These registers are specified as follows.
    - RH0, RL0, RH1, RL1, ..., RH7, RL7  for  8-bit  regis-
      ters. (`H' stands for high-order byte, and `L' stands
      for low-order byte within a  word  register).   These
      registers overlap 16-bit registers R0 through R7.
    - RR0, RR2, ..., RR14 for 32-bit register pairs.
    - RQ0, RQ4, RQ8 and RQ12 for 64-bit register quadruples.
    Besides register pair RR14 is used as stackpointer.

addressing modes
    syntax		meaning (name-mnemonic)
    $expr		the value of expr is the operand.
    		(immediate-IM)
    reg		contents of register reg is operand. Any
    		register as described above is allowed.
    		(register-R)
    *reg32		contents of register pair reg32 is add-
    		ress of operand.  Any register pair can
    		be used except RR0.
    		(indirect register-IR)
    expr		expr is address of operand.
    		(direct address-DA)
    expr(reg16)	value of expr + contents of word regis-
    		ter  reg16  yields  address of operand.
    		Any word register can be used except R0.
    		(indexed address-X)
    expr		expr is address of  operand.  This mode
    		is  implied  by its instruction.  It is
    		only used by CALR, DJNZ, JR,  LDAR  and
    		LDR  and  is the only mode available to
    		these instructions.   In fact this mode
    		differs not from the mode DA.
    		(relative address-RA)
    reg32($expr)	contents of register pair reg32 + value
    		of expr yields address of operand.  Any
    		register pair can be used except RR0.
    		(based address-BA)
    reg32(reg16)	contents  of register pair reg32 + con-
    		tents of  word  register  reg16  yields
    		address of operand.  Any register pair/
    		word register can be used except RR0/R0.
    		(based indexed address-BX)

segmented addresses
    Segmented addresses require 23 bits, 7 bits for the segment number and 16 bits for the offset within a segment. So segment 0 contains addresses 0-FFFF, segment 1 contains addresses 10000-1FFFF, and so on.
    Assembler syntax of addresses and immediate data is as described above (modes IM, DA and X). Thus the assembler treats e.g. address 2BC0F as an address in segment 2 with offset BC0F within the segment. There is also an explicit way to express this using the, more unusual, syntax <<segment>>offset.
    There are two internal representations of segmented addresses depending on the size of the offset. If the offset fits into 8 bits the address is stored in one word (the low-order byte containing the offset, bits 8 to 14 containing the segment number and bit 15 containing a zero) otherwise the address is stored in two words (the lower word containing the offset, the upper word as before but bit 15 containing 1 indicating that the offset is in the next word). This is important for instructions which has an operand of mode DA or X.

extended branches
    When the target address in a relative jump/call (JR/CALR) does not fit into the instruction format, the assembler generates a corresponding `normal' jump/call (JP/CALL).

EXAMPLE
An example of z8000 assembly code.
!   This z8000 assembly routine converts a positive number
!(in R1) to a string representing the number and puts this
!string into a buffer (R3 contains the starting address of
!this buffer.  The base is in R4 determining %x, %d or %o.
convert:
	exts	RR0		!sign-extend R1
	div	RR0, R4		!divide by the base
	test	R1		!R1 contains the quotient
	jr	EQ, 5f
			!if quotient is 0 convert is ready
			!else push remainder onto the stack
	push	*RR14, R0
	calr	convert		!and again...
	pop	R0, *RR14
5:	add	R0, $060	!add `0'
	cp	R0, $071	!compare to `9'
	jr	LE, 8f
	add	R0, $7		!in case of %x `A'-`F'
8:	ldb	0(R3), RL0	!put character into buffer
	inc	R3
	ret

SEE ALSO
uni_ass(6).
ack(1).
Z8000 PLZ/ASM Assembly Language Programming Manual, april 1979.
AmZ8001/2 Processor Instruction Set, 1979.

BUGS
You cannot use (reg16) instead of 0(reg16).
Condition codes `Z' (meaning zero), `C' (meaning carry) and <nothing> (meaning always false) are not implemented. The first two because they also represent flags and the third one because it's useless. So for `Z'/`C' use `EQ'/`ULT'.
The z8000 assembly instruction set as described in the book `AmZ8001/2 Processor Instruction Set' differs from the one described in the manual `Z8000 PLZ/ASM Assembly Language Programming Manual' in that the book includes CLRL, LDL (format F5.1) and PUSHL (format F5.1) which all in fact do not (!) work.
On the other side the book excludes SIN, SIND, SINDR, SINI, SINIR, SOUT, SOUTD, SOTDR, SOUTI and SOTIR. Whether these instructions do work as described in the manual has not been tested yet.