\ifhtml\section*{Contents}
\tableofcontents
\fi
\section{Alpha instruction-set specification}
The Alpha lies somewhere between the MIPS and SPARC in complexity.
It has one structured operand, which
can be either an immediate or register value.
The Alpha is a 64-bit architecture, but
all instructions are 32 bits wide.
Readers shouldn't rely completely on this specification, because
validation identified discrepancies in the assembler's treatment of the
following instructions:
\begin{quote}
\ttfamily jmp jsr ldf ldg lds
\end{quote}
The hint seems off in the jump instructions, and the assembler is
expanding these floating-point loads into two-instruction sequences.
We haven't yet resolved these discrepancies.
\subsection{Fields}
As usual for RISC, we have a single token, and the core specification
has the normal structure.
<>=
fields of instruction (32) <>
<<[[fieldinfo]] specifications>>
<>
@
According to page 1-4 of the manual \cite{sites:alpha},%
\footnote{References to the manual are a bit confused because MFF had
the second edition and NR had the first edition}
the Alpha has four basic formats, which we show here in the order
opposite to that in the manual:
\begin{quote}
\newcommand\smallstrut{\vrule height0pt depth 2pt width 0pt\relax}
\renewcommand\.[2]{\multicolumn{1}{c}{\smallstrut\tiny \kern-5pt #1\hfill#2\kern -5pt}}
\newcommand\bigstrut{\vrule height 10.5pt depth 3.5pt width 0pt\relax}
\begin{tabular}{|c|c|c|c|c|l}
\.{31}{26}&\.{25}{21}&\.{20}{16}&\.{15}{5}&\.{4}{0}\\
\cline{1-5}
\bigstrut Opcode&RA&RB&Function&RC&Operate format\\
\cline{1-5}
\bigstrut Opcode&RA&RB&\multicolumn{2}{c|}{Memory displacement}&Memory format\\
\cline{1-5}
\bigstrut Opcode&RA&\multicolumn{3}{c|}{Branch displacement}&Branch format\\
\cline{1-5}
\bigstrut Opcode&\multicolumn{4}{c|}{Number or PAL function}&PALcode format\\
\cline{1-5}
\end{tabular}
\end{quote}
The operate format comes in both integer and floating-point flavors,
and the two flavors use different register sets.
We use one token to specify all formats, and as usual, the real story
is a bit more complicated---in particular, the area from
bits~0--20 can be broken up in a variety of ways.
These field specifications should be suggestive:
<>=
opcode_ 26:31 ra 21:25 rb 16:20 sbz 13:15 opfmt 12:12 func 5:11 rc 0:4
imm 13:20
fa 21:25 fb 16:20 fpfunc 5:15 fc 0:4
mdisp 0:15
mop 14:15 mhint 0:13
bdisp 0:20
palfunc 0:25
@ Our spec%
\footnote{Unfortunately [[opcode]] is a reserved word, so we use
``[[opcode_]]''.}
uses a couple of combinations not shown in the table.
The ``function'' code for integers is split into [[func]] for
functions, and [[opfmt]] to distinguish register from immediate
operands.
Immediate operands live in [[imm]], and when register operands are
used [[sbz]] Should Be Zero.
The jump instructions split [[mdisp]] into an operation code and a hint.
@
It's easier to specify the integer and floating-point function
codes by splitting them into two parts.
<>=
flo 5:8 fhi 9:11 fplo 5:10 fphi 11:15
@
The registers have two sets of names; we've chosen the ones that
obviously correspond to register numbers.
<<[[fieldinfo]] specifications>>=
fieldinfo
[ ra rb rc ] is [ <> ]
[ fa fb fc ] is [ <> ]
<>=
names [ r0 r1 r2 r3 r4 r5 r6 r7
r8 r9 r10 r11 r12 r13 r14 r15
r16 r17 r18 r19 r20 r21 r22 r23
r24 r25 r26 r27 r28 r29 r30 r31 ]
<>=
names [ f0 f1 f2 f3 f4 f5 f6 f7
f8 f9 f10 f11 f12 f13 f14 f15
f16 f17 f18 f19 f20 f21 f22 f23
f24 f25 f26 f27 f28 f29 f30 f31 ]
@
\subsection{Integer opcodes}
The opcodes are specified in in Appendix~C \cite{sites:alpha}.
Table C-5 includes all the load, store and branch opcodes.
<>=
patterns
[ call_pal _ _ _ _ _ _ _
lda ldah _ ldq_u _ _ _ stq_u
inta intl ints intm _ fltv flti fltl
misc pal19 jsrs pal1b _ pal1d pal1e pal1f
ldf ldg lds ldt stf stg sts stt
ldl ldq ldl_l ldq_l stl stq stl_c stq_c
br fbeq fblt fble bsr fbne fbge fbgt
blbc beq blt ble blbs bne bge bgt ]
is opcode_ = { 0 to 63 }
@ (In NR's edition, the transpose of this table appears as C-9.)
@
We group by assembly syntax and encoding semantics.
<>=
patterns
ldst is lda | ldah | ldl | ldq | ldq_u | ldl_l | ldq_l
| stl | stq | stl_c | stq_c | stq_u
fldst is ldf | ldg | lds | ldt | stf | stg | sts | stt
branch is br | bsr | blbc | beq | blt | ble | blbs | bne | bge | bgt
fbranch is fbeq | fblt | fble | fbne | fbge | fbgt
[ jmp jsr ret jsr_co ] is jsrs & mop = {0 to 3}
jump_hint is jmp | jsr
jump_predict is ret | jsr_co
@
If transcribed directly, the opcode table C-7 (C-5 in NR's edition)
is sparse and confusing,
so we separate it into sub-tables of related opcodes and use the
[[flo]]/[[fhi]] trick.
<>=
patterns
arith is any of
[ addl s4addl subl s4subl _ cmpbge
_ s8addl _ s8subl cmpult _
addq s4addq subq s4subq cmpeq _
_ s8addq _ s8subq cmpule _
addlv _ sublv _ cmplt _
addqv _ subqv _ cmple _ ],
which is opcode_ = 0x10 &
fhi = [ 0 1 2 3 4 6 ] & flo = [ 0x0 0x2 0x9 0xb 0xd 0xf ]
logical is any of
[ and _ _ bic
_ cmovlbs cmovlbc _
bis cmoveq cmovne ornot
xor cmovlt cmovge eqv
_ cmovle cmovgt _ ],
which is opcode_ = 0x11 &
fhi = [ 0 1 2 4 6 ] & flo = [ 0x0 0x4 0x6 0x8 ]
byteops is any of
[ _ _ mskbl _ extbl _ _ _ insbl _
_ _ mskwl _ extwl _ _ _ inswl _
_ _ mskll _ extll _ _ _ insll _
zap zapnot mskql srl extql _ sll _ insql sra
_ _ mskwh _ _ inswh _ extwh _ _
_ _ msklh _ _ inslh _ extlh _ _
_ _ mskqh _ _ insqh _ extqh _ _ ],
which is opcode_ = 0x12 &
fhi = [ 0 1 2 3 5 6 7 ] & flo = [ 0 1 2 4 6 7 9 10 11 12 ]
mulops is any of [ mull mullv mulq mulqv umulh ],
which is intm & func = [ 0x00 0x40 0x20 0x60 0x30 ]
@
\subsection{Structured operands}
Integer register-to-register instructions have two operand formats,
in which one of the source operands is an integer literal or
a register.
The encoding is very much like the SPARC, except instead of unused
bits the Alpha has an [[sbz]] field, which should be zero.
Since the Alpha doesn't seem to have a special terminology for these
operands, we reuse the SPARC terminology.
<>=
constructors
imode imm : reg_or_imm is opfmt = 1 & imm
rmode rb : reg_or_imm is opfmt = 0 & sbz = 0 & rb
@
\subsection{Integer instructions}
The integer load/store instructions appear first~\cite[p4-4]{sites:alpha}.
<>=
constructors
ldst ra, mdisp!(rb)
@
The control instructions begin on page~4-16~\cite{sites:alpha}.
The [[branch]] instructions are simliar
to the MIPS branch instructions.
The [[jmp]] and [[jsr]] instructions take a 14-bit ``hint%
\footnote{We're having a problem with the coding of these hints, as
noted above.}'',
which is used
to compute the predicted target of the jump as $\mathit{PC} +
4\times\mathit{hint}$.%
\footnote{The $\mathit{PC}$ is the updated $\mathit{PC}$.}%
The [[ret]] and [[jsr_co]] instructions ignore the hint and
use a prediction implementation stack, if there is one.
In that case the hint is reserved for use by software and is required
to be 0~or~1 (page 4-21).
We could specify these two pairs separately, but we follow
the manual, which defines them together.
<>=
relocatable target
placeholder for instruction is call_pal & palfunc = 0 # halt (privileged)
constructors
branch ra, target { target = L + 4 * bdisp! } is branch & ra & bdisp; L: epsilon
jump_hint ra, (rb), mhint
proc "0" : Return is mhint = 0
nonproc "1" : Return is mhint = 1
jump_predict ra, (rb), Return
@ We provide alternate versions that take an address and encode the hint:
<>=
constructors
jump_hint^"*" ra, (rb), target { target = L + 4 * mhint }
is L: jump_hint & ra & rb & mhint
@ It's not clear whether these are useful.
@
The integer arithmetic instructions begin on page 4-24 (4-22 in NR's edition)
and can be specified in one line. Hurray for orthogonality!
<>=
patterns alu is arith | logical | byteops | mulops
constructors
alu ra, reg_or_imm, rc
@
\subsection{Floating-point opcodes}
The floating-point opcodes are specified in Table
C-7 of NR's edition.
Many floating point instructions take suffixes,
called ``qualifiers'', which specify a variety of
rounding and exception modes.
The suffixes are described beginning on page~4-61.
We've aggressively factored the table on page~C-4.
First we attack the row labels, then the column labels.
For the row labels, we look at column /C, where the column code is
zero, and for the row labels, we look at row ADDS, where the row code
is zero.
For the row labels, we have to slice manually (or shift right 6 bits).
In a better world, that operation would be in our specification language.
<>=
patterns [ adds addt cmpteq cmptlt cmptle cmptun
cvtqs cvtqt cvtts divs divt muls mult subs subt cvttq ]
is flti & fplo = [ 0x00 0x20 0x25 0x26 0x27 0x24
0x3c 0x3e 0x2c 0x03 0x23 0x02 0x22 0x01 0x21 0x2f ]
fpqual is any of
[ none c m d u uc um ud
su suc sum sud sui suic suim suid ],
which is flti & fphi = [ 0x02 0x00 0x01 0x03 0x06 0x04 0x05 0x07
0x16 0x14 0x15 0x17 0x1e 0x1c 0x1d 0x1f ]
@ Having done this, we now group both qualifiers and opcodes according
to the rows of the tables that have the same columns filled in.
<>=
patterns
cmpqual is none | su
cvtqual is none | c | m | d | sui | suic | suim | suid
fpop is adds | addt | divs | divt | muls | mult | subs | subt
cmpop is cmpteq | cmptlt | cmptle | cmptun
cvtop is cvtqs | cvtqt
qqqual is any of [ qq qqc qqm qqd v vc vm vd
sv svc svm svd svi svic svim svid ],
which is flti & fphi = [ 0x02 0x00 0x01 0x03 0x06 0x04 0x05 0x07
0x16 0x14 0x15 0x17 0x1e 0x1c 0x1d 0x1f ]
@ The qualifiers for [[cvttq]] mostly have different names.
The [[qq]] trick enables us to avoid collisions with names of
qualifiers used in [[fpqual]].
@
\subsection{Floating-point instructions}
The floating-point load/store and branch instructions are
similar to the integer instructions.
<>=
constructors
fldst fa, mdisp(rb)
fbranch fa, target { target = L + 4 * bdisp! }
is fbranch & fa & bdisp; L: epsilon
@
We use compound opcodes to define instructions that take qualifiers.
<>=
constructors
fpop^fpqual fa, fb, fc
cvtts^fpqual fb, fc
cvtop^cvtqual fb, fc
cmpop^cmpqual fa, fb, fc
cvttq^qqqual fb, fc
@
\subsection{PAL instructions}
The Privileged Access Library provides a large set of
hardware and firmware control functions that can be used under
the OpenVMS, DEC OSF/1, and Windows NT operating systems.
We define only those PAL functions that must be recognized
by all implementations.
<<[[fieldinfo]] specifications>>=
fieldinfo palfunc is
[ sparse
[ halt = 0, draina = 2, cserve = 0xa, swppal = 0xb,
bpt = 0x80, bugchk = 0x81, imb = 0x86,
rdunique = 0x9e, wrunique = 0x9f, gentrap = 0xaa ] ]
<>=
constructors
call_pal palfunc
@
\subsection{Synthetics}
Section C.7 of the DEC OSF/1 Assembly Language Programmer's Guide
lists some of the expansions of synthetic instructions, but not all of
them. Being lazy, we define just a handful.
<>=
constructors
andnot ra, rb, rc is bic(ra, rmode(rb), rc)
clr rc is bis(r31, rmode(r31), rc)
mov reg_or_imm, rc is bis(r31, reg_or_imm, rc)
nop is bis(r31, rmode(r31), r31)
not rb, rc is ornot(r31, rmode(rb), rc)
or ra, reg_or_imm, rc is bis(ra, reg_or_imm, rc)
@
\subsection{Span-dependent branches}
Dirty-trick central.
First, opposite branches:
<>=
patterns xbranch is any of
[ xbeq xbne xble xblt xbge xbgt xblbc xblbs ], which is
[ bne beq bgt bge blt ble blbs blbc ]
constructors
xbranch ra, target { target = L + 4 * bdisp! } is xbranch & ra & bdisp; L: epsilon
constructors
"span"^branch ra, target
where { } is branch ra, target
otherwise is
"x"^branch ra, L;
bis(r31, imode(target@[0:7]), 1); # bogus -- must set 64 bits
jmp(r31, 1, 0);
L: epsilon
@
\subsection{Checking against the Digital OSF/1 Assembler}
Apparently, unlike in the manual, qualifiers in OSF/1 assembler are not
preceded by a slash, so all we need to do is fix a couple of names.
<>=
assembly component
none* is ""
qq{*} is $1
jsr_co is "jsr_coroutine"
@ The OSF assembler uses the usual DEC conventions about register
names:
<>=
assembly operand
[ ra rb rc ] is "$%d"
[ fa fb fc ] is "$%s"
@
There's a bug in the toolkit that prevents us from checking [[call_pal]].
<>=
discard call_pal
discard jump_hint^"*" # not really in the assembly language
discard mov nop # OSF/1 assembler uses different synthetics
@
When assembling code for checking,
we might use [[$at]], we don't want instructions out of
order, and we want screaming and shouting when the assembler expands
something into a multi-instruction sequence.
<>=
.set noat
.set noreorder
.set nomacro
@
The result of the checking is OK except for the discrepancies noted
above.
The other oddity is that the assembler expands multiplication by
constants into a sequence of add and subtract operations.
@
\subsection{Guaranteeing registers}
Most applications will want to make the usual assumptions about the
values of register operands.
<>=
fieldinfo [ra rb rc fa fb fc] is [guaranteed]