URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk/doc
- from Rev 72 to Rev 73
- ↔ Reverse comparison
Rev 72 → Rev 73
/spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/iset.html
307,7 → 307,7
<H2>Native Instructions</H2> |
The Zip CPU instruction set has one of two basic formats, with a small |
number of exceptions. These formats are shown below: |
<TABLE border> |
<TABLE border align=center> |
<TR><TH rowspan=2>Op Code</TH><TH colspan=8>31..24</TH> |
<TH colspan=8>23..16</TH> |
<TH colspan=8>15..8</TH> |
411,17 → 411,36
<TR><TD>5'h1e</TD><TD rowspan=2 colspan=3 align=center><em>Reserved for future use</em></TD></TR> |
<TR><TD>5'h1f</TD></TR> |
</TABLE> |
This leaves three instructions left: NOOP, BREAK, and LOCK. These have opcodes |
of <TT>5'h19</TT>, <TT>5'h1a</TT>, and <TT>5'h1c</TT> respectively. They |
are carved out of the floating point units opcodes, and differentiated by the |
fact that their resulting register is either the CC or PC register. (It never |
made sense to do a floating point instruction into the CC or PC register |
anyway ...) The BREAK instruction is designed to trap the CPU without ever |
entering into the ALU. It is useful for debugging purposes. The LOCK |
instruction waits the decode and prefetch pipeline stages to fill with memory |
instructions before locking the bus and letting these memory operations |
complete. It is designed to support a test and set operation. (Actually, |
since the Zip CPU doesn't truly support a LOCK bit on the wishbone bus, what |
really happens is that the CYC line is kept high throughout the operation. |
This line may be tied to a LOCK line if you would like to use the Zip CPU |
with a bus that supports LOCKing.) |
|
<H2>Derived Instructions</H2> |
<TABLE border> |
<TR><TH>Mapped</TH><TH>Actual</TH><TH WIDTH=65%>Notes</TH></TR> |
<TR><TD valign=top>ABS Rx</TD><TD>TST -1,Rx<BR>NEG.LT Rx</TD><TD>Absolute |
value, depends upon the derived NEG instruction below.</TD></TR> |
<TR><TD valign=top>ADD Ra,Rx<BR> |
ADDC Rb,Ry</TD><TD valign=top>ADD Ra,Rx<BR>ADD.C $1,Ry<BR>ADD Rb,Ry</TD><TD valign=top>Add with carry</TD></TR> |
<TR><TD valign=top rowspan=2>BRA.cond +/-$Addr</TD><TD> |
<TR><TD valign=top rowspan=3>BRA.cond +/-$Addr</TD><TD> |
MOV.cond $Addr+PC,PC</TD><TD>Branch/jump on condition. Works for 14 bit address offsets.</TD></TR> |
<TR><TD>ADD.cond $Addr,PC<TD>Branch/jump on condition that works for 18-bit |
offsets, although it does set the flags.</TD></TR> |
<TR><TD>LDI $Addr,Rx<BR> |
ADD.cond Rx,PC</TD><TD>Branch/jump on condition. Works for |
23 bit address offsets, but costs a register, an extra instruction, |
and setsthe flags.</TD></TR> |
23 bit address offsets, but costs a register and an extra one (or |
two) instruction(s).</TD></TR> |
<TR><TD valign=top>BNC PC+$Addr</TD><TD> |
TEST $Carry,CC<BR> |
MOV.Z PC+$addr,PC</TD> |
437,18 → 456,11
<TR><TD valign=top>IRET</TD><TD>OR $GIE,CC</TD><TD>Also an RTU instruction |
(Return to Userspace)</TD></TR> |
<TR><TD valign=top>JMP R6+$Addr</TD><TD>MOV $Addr(R6),PC</TD><TD> </TD></TR> |
<TR><TD valign=top rowspan=2>JSR PC+$Addr</TD><TD> |
SUB $1,SP<BR> |
MOV $3+PC,R0<BR> |
STO R0,1(SP)<BR> |
MOV $Addr+PC,PC<br> |
ADD $1,SP</TD><TD>Jump to Subroutine.</TD></TR> |
<TR><TD>MOV $3+PC,R12<BR>MOV $addr+PC,PC</TD><TD>This is the high speed |
version of the call, necessitating a register to hold the last |
PC address. In its favor, this method doesn't suffer the mandatory |
memory access of the other approach.</TD></TR> |
<TR><TD valign=top>JTU</TD><TD>OR $GIE,CC</TD><TD>Also known as a JUMP-To-USER |
space command, also known as IRET.</TD></TR> |
<TR><TD valign=top>JSR PC+$Addr</TD><TD>MOV $3+PC,R12<BR>MOV $addr+PC,PC</TD> |
<TD>Jump to subroutine. |
Note that this high speed version of a JSR call needs a register to |
hold the last PC address. In its favor, it doesn't suffer the mandatory |
memory access of the more traditional approach.</TD></TR> |
<TR><TD valign=top>LDI.l $val,Rx</TD><TD> |
LDIHI HIBITS($val),Rx<BR> |
LDILO LOBITS($val),Rx</TD><TD>Sadly, there's not enough instruction |
455,7 → 467,11
space to load a complete immediate value into any register. |
Therefore, fully loading any register takes two cycles. |
The LDIHI (load immediate high) and LDILO (load immediate low) |
instructions have been created to facilitate this.</TD></TR> |
instructions have been created to facilitate this. |
Further, the assembler will quietly turn any LDI #x,Rx |
instruction into this instruction if either #x doesn't fit |
within the 23--bit immediate operand field, or if the |
instruction is conditional.</TD></TR> |
<TR><TD valign=top>LOD.b $addr,Rx</TD><TD> |
LDI $addr,Ra<BR> |
LDI $addr,Rb<BR> |
486,7 → 502,7
LDIHI.C $8000h,Rz<BR> |
LSR $1,Rx<BR> |
OR Rz,Rx</TD><TD>Logical shift right with carry</TD></TR> |
<TR><TD valign=top>NEG Rx</TD><TD>XOR $-1,Rx<BR>ADD $1,Rx</TD><TD> </TD></TR> |
<TR><TD valign=top>NEG.C Rx</TD><TD>XOR.C $-1,Rx<BR>ADD.C $1,Rx</TD><TD>Negate, may be conditional</TD></TR> |
<TR><TD valign=top>NOOP</TD><TD>NOOP</TD><TD>While there are many |
operations that do nothing, such as MOV Rx,Rx, or OR $0,Rx, these |
operations have consequences in that they might stall the bus if |
493,26 → 509,29
Rx isn't ready yet. For this reason, we have a dedicated NOOP |
instruction.</TD></TR> |
<TR><TD valign=top>NOT Rx</TD><TD>XOR $-1,Rx</TD><TD> </TD></TR> |
<TR><TD valign=top>POP Rx</TD><TD>LOD $-1(SP),Rx<BR>ADD $1,SP</TD><TD>Note |
that for interrupt purposes, one can never depend upon the value at |
(SP). Hence you read from it, then increment it, lest having |
incremented it firost something then comes along and writes to that |
value before you can read the result.</TD></TR> |
<TR><TD valign=top>POP Rx</TD><TD>LOD (SP),Rx<BR>ADD $1,SP</TD> |
<TD rowspan=2>Note |
that for pipelining purposes, it helps to coalesce all the ADD (SUB) |
operations into one after (before) a group of LOD (STO) instructions, |
and then to do the operations in sequential order. This will guarantee |
a pipelined memory operation.</TD></TR> |
<TR><TD valign=top>PUSH Rx</TD><TD> |
SUB $1,SP<BR> |
STO Rx,$1(SP)</TD><TD> </TD></TR> |
<TR><TD valign=top>RESET</TD><TD>STO $1,$watchdog(R12)<BR>NOOP<BR>NOOP</TD><TD> |
This depends upon the peripheral base address being in R12. |
<P>Another opportunity might be to jump to the reset address from within |
supervisor mode. |
SUB 1,SP<BR> |
STO Rx,(SP)</TD></TR> |
<TR><TD valign=top>RESET</TD><TD>LDI 1,R0<BR>STO R0,$watchdog(R12)<BR>NOOP<BR>NOOP</TD><TD> |
This depends upon the peripheral base address already being in R12. |
<P>Another opportunity might be to jump to the reset address from |
within supervisor mode. |
</TD></TR> |
<TR><TD valign=top rowspan=2>RET</TD><TD>LOD $-1(SP),R0<BR> |
MOV $-1+SP,SP<BR> |
MOV R0,PC</TD><TD>An alternative might be to LOD $-1(SP),PC, followed |
by depending upon the calling program to ADD $1,SP.</TD></TR> |
<TR><TD>MOV R12,PC</TD><TD>This is the high(er) speed version, that doesn't |
touch the stack. As such, it doesn't suffer a stall on memory |
read/write to the stack.</TD></TR> |
<TR><TD valign=top>RET</TD><TD>MOV R12,PC</TD><TD> |
Recall that the JSR command left the address to return to in the |
register set. Were that register R12, this returns us back to where |
we came from. Unlike the traditional RETN structure of some other |
architectures, this instruction doesn't suffer a stall on memory |
read from the stack.</TD></TR> |
<TR><TD valign=top>RTU</TD><TD>OR $GIE,CC</TD><TD>Also known as a Return-To-USER |
space command, sometimes known as IRET (interrupt return) in |
other architectures.</TD></TR> |
<TR><TD valign=top>STEP Rr,Rt</TD><TD>LSR $1,Rr<BR>XOR.C Rt,Rr</TD><TD>Step a |
Galois implementation of a Linear Feedback Shift Register, Rr, using |
taps Rt</TD></TR> |
539,19 → 558,12
XOR Rx,Ry<BR> |
XOR Ry,Rx</TD><TD>While no extra registers are needed, this example |
does take 3-clocks.</TD></TR> |
<TR><TD valign=top>TRAP #X</TD><TD>LDILO $x,CC</TD><TD> |
This approach uses the unused bits of the CC register as a TRAP |
address. If these bits are zero, no trap has occurred. Unlike my |
previous approach, which was to use a trap peripheral, this approach |
has no delay associated with it. To work, the supervisor will need |
to clear this register following any trap, and the user will need to |
be careful to only set this register prior to a trap condition. |
Likewise, when setting this value, the user will need to make certain |
that the SLEEP and GIE bits are not set in $x. LDI would also work, |
however using LDILO permits the use of conditional traps. (i.e., |
trap if the zero flag is set.) Should you wish to trap off of a |
register value, you could equivalently load $x into the register and |
then MOV it into the CC register. |
<TR><TD valign=top>TRAP #X</TD><TD valign=top>LDILO $x,R0<BR>AND ~$GIE,CC</TD><TD> |
This approach uses R0 as a TRAP address. It works because anytime |
a user lowers the GIE flag a trap bit is also set within the CC |
register. Therefore, upon entering the supervisor state, the CPU only |
needs to check this bit to know that it got there via a TRAP. The |
trap could be made conditional by making the AND conditional. |
</TD></TR> |
<TR><TD valign=top>TST Rx</TD><TD>TST $-1,Rx</TD><TD valign=top>Set the |
condition codes based upon Rx. Could also do a CMP $0,Rx, |
/src/spec.tex
978,9 → 978,10
signed address offsets.\\\hline |
{\tt BRA.Cond +/-\$Addr} |
& \parbox[t]{1.5in}{\tt LDI \$Addr,Rx \\ ADD.cond Rx,PC} |
& Branch/jump on condition. Works for |
23 bit address offsets, but costs a register, an extra instruction, |
and sets the flags. \\\hline |
& Branch/jump on condition. Works for 23 bit address offsets, but |
costs a register and an extra instruction. With LDIHI and LDILO |
this can be made to work anywhere in the 32-bit address space, but yet |
cost an additional instruction still. \\\hline |
{\tt BNC PC+\$Addr} |
& \parbox[t]{1.5in}{\tt Test \$Carry,CC \\ MOV.Z PC+\$Addr,PC} |
& Example of a branch on an unsupported |