The Z180 is a very fast successor of the ever so popular Z80. It has a few additional instructions, of which the MLT instruction is the most welcome one. All other instructions are 100% compatible with those of the Z80, both on source and object code level.
Furthermore the Z180 is in fact nothing else than a Z80 with some built in peripherals like an MMU, 2 serial controllers, a DMA controller and a timer.
Although the MMU is capable of addressing up to 1 Mb of memory, the Z180 core can only address the traditional 64 kb.
The programming model in the picture below shows the most important registers of the Z180 processor. I only include a little summary about the features of the Z180's programming model here. It is not my intention to make the original documentation obsolete, so please refer to the original documentation for further details.
All working registers are shadowed by an identical second set. These shadow registers can be used for very fast context switching during interrupts, or can simply expand the standard register set. Special instructions exist to exchange the two register sets.
The Accumulator is the most important register for 8 bit arithmetic operations.
Its standard name is A, which is a reserved word.
The Program Status Word
The Flag register contains 6 system flags:
General Purpose Registers
Six additional general purpose 8-bit registers assist the Accumulator. These registers can be concatenated to form three 16-bit register pairs. Especially the HL pair is used as a data pointer to transfer data to and from memory and it can be used for a limited number of 16-bit arithmetic functions.
Index register IX and IY
New to the Z80 and Z180, compared to the 8080, are two identical index registers. These two register assist in indexed addressing of data and supplement the use of the HL pair.
Memory refresh register R
The Z180 has a refresh register which enables easy interfacing with DRAM memory. Seven bits of the R register are incremented after each instruction fetch. The eighth bit remains as set by a previous LD R,A instruction.
The I register
The I register provides the upper 8 address bits during interrupt vectoring, while the interrupting peripheral device supplies the lower 8 address bits.
This way interrupt service routines may be located anywhere in memory.
The least significant bit of the vector address is always 0, which means that all interrupt service routines should start at an even address.
The Stack Pointer
The stack on a Z180 can be located anywhere in RAM memory, pointed to by the stack pointer SP. Every time something is pushed on to the stack, the SP pointer is decremented, so the stack is growing down in memory.
Stack operations are always performed with register pairs.
Naturally a pop from the stack has just the opposite effect:
Please note that you should take care that the MMU doesn't switch your stack RAM out of reach, otherwise your system will most certainly crash. Unfortunately the Z180's MMU doesn't know a dedicated STACK bank, which would have simplified the bank switching considerably.
The Program Counter
The program counter PC is normally incremented after fetching each instruction or operand byte during program execution. The only way you can change this behaviour is with the jump, call and return instructions. Also interrupts can change the program counter's value.
The program counter is still 16-bits wide, resulting in an addressing range of "only" 64 kb. It's the MMU's responsibility to translate this 64 kb logical range into the 1 Mb physical range. This is done by dividing the 64 kb address range in up to 3 areas.
Version 3 of the SB-Assembler can display instruction timing information when the TON list option is switched on. The indicated values are the number of T cylces each instruction takes.
The SB-Assembler Z180 cross overlay has a few reserved words.
Reserved words are all register names.
You better avoid these reserved words when you assign your own labels.
E.g. don't call your labels IX, or A or H.
Here's the list of all reserved words:
A, F, B, C, D, E, H, L, I, R, BC, DE, HL, IX, IY, SP, NC, Z, NZ, PE, PO, P, M
None of the internal peripheral I/O locations are pre-defined by the SB-Assembler. You're free to assign them any label names you like, although I recommend you to use the names that Zilog uses in order to keep your code readable by others.
The Z180 assembler doesn't always follow the same syntax rules for equivalent instructions as you might expect. Like for instance the ADD and SUB instructions.
The SB-Assembler Z180 cross is very forgiving when it comes to these inconsistencies. In the example below you see both operand notations for the ADD and SUB instructions.
ADD A,DATA Normal notation according to Zilog ADD DATA Has the same effect as the line above ADD A,#DATA This is also possible ADD #DATA And this too SUB DATA Normal notation according to Zilog SUB A,DATA This is accepted just the same
As you can see in the example above you may also use the immediate operand identifiers, although it is not absolutely necessary. The SB-Assembler will automatically use 8 or 16-bit values, depending on the instruction's needs. If you want another part of the 32-bit number to be loaded immediately into any of the registers or register pairs you could use the other immediate mode identifiers /, =, or \.
The official indexed addressing mode using one of the new index registers is (IX+offset), where offset can be an 8-bit positive or negative number. If that number is 0 it may be omitted in the SB-Assembler. So the official notation (IX+0) can also be written as (IX).
Another peculiar property of the Z180, inherited from the 8080, is the lack of a Clear Carry instruction.
There is an instruction to set the carry and there is one to complement the carry, two instructions that I personally rarely use.
But an instruction to clear the carry is strangely missing.
Originally the 8 possible, 8080 compatible, restart vectors are numbered from 0 to 7 in other assemblers.
This is very inconvenient, because you can't let the restart vector point to the appropriate vector address by using its label name.
Please note that the value of the operand after an RST instruction may not be any other value than 0 to 7, $08, $10, $18, $20, $28, $30 or $38. Any other value will result in a "*** Range error" to be reported.
The Z180 chip has 20 address lines, and can address up to 1 Mb of physical memory.
But the Z180 processor core has only 16 address bits, so it can only access up to 64 kb of logical memory.
It's the task of the MMU to translate the 16-bit logical addresses to a 20-bit physical addresses.
It's the programmer's responsibility to set the MMU as required by the software. You can use the .PH directive to keep the logical address range below the 64 kb boundary, even though the instructions may be stored at addresses above the 64 kb boundary. In fact you let the SB-Assembler think it is still addressing memory below the 64 kb boundary this way.
As of Version 3 you can also use the .TA to set the target address of the object code in the target file. That way you can set the .OR to the proper address in the 64 kb address space, while the output bytes are stored elsewhere in the target file.
Two things are set while initializing the Z180 overlay every time it is loaded by the .CR directive.
There are some differences between the SB-Assembler and other assemblers for the Z180 processor. These differences require you to adapt existing source files before they can be assembled by the SB-Assembler. This is not too difficult though, and is the (small) price you have to pay for having a very universal cross assembler.