.cr z180 To load this cross overlay
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 found on the Z80, both on source and object code level.
Furthermore the Z180 is in fact nothing more 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 itself can still only address the traditional 64 kB.
Because of these minor changes, the Z180 cross overlay differs only in the expanded instruction set from the Z80 cross overlay.
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 Accumulator and the Flag register F together form one single 16-bit register.
PUSH and POP treat the Accumulator and F as one pair of registers called AF, where A is the MSB and F is the LSB.
The Flag register contains 6 system flags:
S | Sign Flag |
Z | Zero Flag |
0 | Always "0" |
H | Half Carry Flag |
0 | Always 0 |
P/V | Parity/Overflow Flag |
N | ADD/SUB flag (used together with H) |
CY | Carry Flag |
Six additional general purpose 8-bit registers assist the Accumulator. Three pairs of 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.
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.
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 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.
Please note that you should take care that the MMU doesn't switch your interrupt routines out of reach, otherwise your system will most certainly crash!
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.
A push on the stack, whether it comes from the PUSH instruction, a subroutine call, or interrupt has the following sequence:
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 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 cycles 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.
If you do use the reserved words as label names you may expect unpredictable behaviour of the assembler sooner or later.
Please note that the assembler will not warn you if you try to assign a label with a reserved name!
Reserved names can not be used in expressions, like label names can.
An Undefined label error will be reported if you do try to use a reserved word in an expression because it is treated as a normal label in this case.
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 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.
Therefore I've added a compound instruction to clear the carry, called RCF.
This instruction is translated by the assembler to the instructions SCF and CCF, effectively clearing the carry.
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.
Therefore I've added another addressing format to the RST instructions.
Not only can you use the original addressing format, using a number from 0 to 7, but you can also use the appropriate vector addresses as well.
The list below shows the relationship between the vector address and interrupt number.
Vector Address | Interrupt Number |
$00 | 0 |
$08 | 1 |
$10 | 2 |
$18 | 3 |
$20 | 4 |
$28 | 5 |
$30 | 6 |
$38 | 7 |
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 Out of 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.
The SB-Assembler only has to deal with the 16-bit logical address space of the Z180, because none of the Z180 instructions can access addresses beyond the 64 kB boundary anyway.
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.