Instruction Set Enhancements
Is strict Z80/Z180 compatibility necessary?
The reason other Z80/Z180-compatible microprocessor manufacturers keep strict compatibility is that they are dependent on third-party development. Rabbit Semiconductor has a close relationship with Rabbit, Inc., the sole supplier of development tools for the Rabbit. Rabbit has ported its Dynamic C compiler to the Rabbit. This gives us the flexibility to sacrifice strict compatibility to gain performance.
To gain a significant performance edge we needed some new single-byte op codes. (Instructions with two-byte op codes take at least twice as long to execute as instructions with single-byte op codes.) Unfortunately there are no unused single-byte op codes on the Z180. On the other hand, many single-byte op codes correspond to rarely used (in some cases practically useless) instructions. Since those instructions can be easily emulated by a sequence of other instructions, they were replaced with the new instructions described below.
Because the dropped instructions are seldom used, porting existing Z80 or Z180 assembly code is easy. The I/O instructions are the most significant difference, but I/O code would typically be modified anyway when porting from one system to another.
New 16-bit operations
Instructions to fetch and store 16-bit variables at a computed address are very important for C, which favors the use of 16-bit integers. The Rabbit has very efficient instructions to fetch and store variables relative to hl, ix or iy index registers. New instructions facilitate use of the alternate registers. New math and shift instructions improve arithmetic. Examples are shown below.
|
clocks |
bytes |
|
ld hl,(ix+d) |
9 |
2 |
loads 16 bits at ix plus offset d (-128 to 127) |
ld hl,(iy+d) |
11 |
3 |
|
ld hl,(hl+d) |
11 |
3 |
|
ld (ix+d),hl |
11 |
2 |
|
ld (iy+d),hl |
13 |
3 |
|
ld hl,(sp+n) |
9 |
2 |
load 16 bits from sp plus offset n (0-255) |
ld (sp+d),hl |
11 |
2 |
|
mul |
12 |
1 |
signed multiply hl:bc=de*bc |
bool hl |
2 |
1 |
if hl==0 unchanged, else hl set to 1 |
ex de',hl |
2 |
1 |
exchange hl and alternate de |
ex de,hl' |
4 |
2 |
|
ex de',hl' |
4 |
2 |
|
ld ix,hl |
4 |
2 |
|
ld hl,ix |
4 |
2 |
|
ld iy,hl |
4 |
2 |
|
ld hl,iy |
4 |
2 |
|
ld dd',BC |
4 |
2 |
|
ld dd',De |
4 |
2 |
dd'= hl', de', or bc' |
ror de |
2 |
1 |
16-bit shifts |
rol de |
2 |
1 |
|
ror hl |
2 |
1 |
|
|
In C, the memory address often is computed relative to the system stack or to a pointer. The table below gives some examples of the value of the Rabbit's new instructions.
| |
Rabbit |
Z180 |
Operation |
code |
clocks |
bytes |
code |
clocks |
bytes |
Fetch 16-bit operand at stack plus offset |
ld hl,(sp+offset)
total ------------- |
9
9 |
2
2 |
ld hl,offset add hl,sp ld a,(hl) inc hl ld h,(hl) ld l,a total ------------- |
9 7 6 4 6 4 36 |
2 1 2 1 2 1 9 |
Store an integer at a location specified by a pointer to a structure passed as an argument. p->q=x; |
ld hl,(x) ld ix,(sp+p) ;pointer ld (ix+q),hl
total ------------- |
11 11 13
34
|
2 3 2
7 |
ld hl,p add hl,sp ld a,(hl) inc hl ld h,(hl) ld l,a ex de,hl ld hl,q add hl,de ;pointer ld de,(x) ld (hl),e inc hl ld (hl),d total ------------- |
9 7 6 4 6 4 3 9 7 18 6 4 6 87 |
1 1 2 1 2 1 2 1 1 2 2 1 2 19 |
Compute the logical value of an integer in hl. Zero if hl is zero, otherwise one. |
bool hl
total ------------- |
2 2 |
1 1 |
ld a,h
or l
jr z, next
ld hl,1
total -------------
|
4
4
8
9
25
|
1
2
2
2
7
|
|
Input/Output Instructions
The Z80 and Z180 perform I/O using the in and out instructions. Since these
instructions are not nearly as powerful and flexible as the memory access
instructions, the Rabbit uses a different method. The following prefixes may be
used with most Rabbit memory access instructions:
- ioi - indicates I/O to a device internal to the Rabbit chip
- ioe - indicates I/O to an external device
In addition to granting the power of the memory access instructions to I/O
operations, this method allows 16-bit I/O transfers from a single instruction
(in which case the low order byte is transferred over the bus before the high
order byte).
Memory mapping
The Z180 instruction set uses 16 bit addresses allowing direct access to 64
Kbytes of memory. Software that uses the Z180/HD64180 memory mapping unit uses
bank switching to expand the accessible memory. The 64K space is divided into
three segments (root code, data, and overlay). This method has the following
disadvantages:
- Calling a function
that resides in an overlay requires calling a subroutine resident in the root
that changes the mapping and calls the function. This involves painful
compromises and substantial overhead both in memory and execution time for each
call. Typically a call to an overlayed routine on a Z180 takes about 150 clocks to execute.
- The space reserved for banked routines must be large enough to hold
the largest function that will be banked. Typically, available memory space
tends to be squeezed since the bank may have to be 20K or 30K in size.
The Rabbit improves this situation dramatically with the following
enhancements:
- The Rabbit increases the number of segments from three to four to allow a
dedicated stack segment. This allows each task in a multitasking program to
have its own stack.
- The Rabbit has instructions that directly use a 20-bit address to
fetch and store data.
- The Rabbit has dedicated instructions called long calls, long returns and
long jumps that implement bank switching in hardware.
- The Rabbit
always uses an 8K bank no matter how large the function is. The bank is slid in
4K steps as the routine is executed, so any size function can be executed in the
8K bank.
- The call and return combined overhead is only 32 clocks, and no root
code space has to be used for linkage. The result is that programs up to a
megabyte execute almost as efficiently as programs contained entirely in the
root code space. Most of the root becomes available for data space because
banked code or extended code executes efficiently.
Return to top
Copyright © 2001 Rabbit Semiconductor. All Rights Reserved
|