\ifhtml\section*{Contents}
\tableofcontents
\fi
\section{SPARC instruction-set specification}
This section specifies the SPARC instruction set.
It uses two specification techniques not needed in the
simpler MIPS specification.
Operands of some SPARC instructions contain more than one field; we
use {\em typed constructors} to specify them.
We also use the extended pattern declaration
\begin{quote}
{\em p} [[is any of []] $p_0$ $p_1$ $\ldots$ $p_n$ [[], which is]] {\em generating expression},
\end{quote}
which not only defines patterns $p_0$ through $p_n$, but also defines
$p$ to be their disjunction.
We can factor
the SPARC instruction in much the same
way as we did the MIPS;
instructions with identical assembly syntax are grouped using
disjunction and defined in one constructor declaration.
The SPARC assembly language contains overloaded instructions, the
encodings of which depend on the number and types of the operands.
Overloading is easy to handle in a textual assembler because
a parser can use information about operands to resolve overloaded names.
The toolkit, however, generates encoding procedures written in~C,
which does not permit users to overload procedures.
For that reason, the toolkit does not permit overloading of
constructor names; the specification writer must choose a distinct name
for each variant of an overloaded instruction.
It's also possible to use constructor types to play games with
overloaded instructions; we show an example in
Section~\ref{overloading-trick}.
\subsection{Fields}
The SPARC is a RISC architecture and thus uses
a single token class for all of its fields.
<>=
fields of instruction (32) <>
<<[[fieldinfo]] specifications>>
<>
@
Information about instruction formats and fields is taken from
Chapter~5 of the SPARC architecture manual.
<>=
inst 0:31 op 30:31 disp30 0:29 rd 25:29 op2 22:24 imm22 0:21 a 29:29 cond 25:28
disp22 0:21 op3 19:24 rs1 14:18 i 13:13 asi 5:12 rs2 0:4 simm13 0:12 opf 5:13
@
\subsection{Opcodes}
The following opcode tables are derived from the tables in Appendix~F
of the SPARC manual~\cite{sparc:architecture}.
Where an entry in a table refers to another table, we define a pattern
with the name of that table (e.g., [[TABLE_F2]]).
That pattern is not useful by itself, but is used to define more
opcodes in a pattern-binding statement that resembles the eponymous
table.
These strange ``opcodes'' actually play the same role as the
``[[special]]'' and ``[[bcond]]'' opcodes on the MIPS architecture,
but the SPARC people have a different way of naming such things.
The SPARC opcode tables are organized hierarchically; the first table
in Appendix~F is at the top of the hierarchy, and it has four entries
corresponding to the four possible values of the (two-bit) [[op]]
field.
Only one of these entries ([[CALL]]) is an opcode; the others refer
the reader to subsequent tables.
<>=
patterns
[ TABLE_F2 CALL TABLE_F3 TABLE_F4 ] is op = {0 to 3}
@
Table F-2 is short, but it presents an oddity: an opcode with two names.
[[SETHI]] means [[NOP]] when [[rd]] and [[imm22]] are zero.
On the MIPS, no-ops were treated as synthetic instructions, but here
we define [[NOP]] as a separate opcode, reflecting
the presentation in the manual.
<>=
patterns
[ UNIMP Bicc SETHI FBfcc CBccc ] is TABLE_F2 & op2 = [0 2 4 6 7]
NOP is SETHI & rd = 0 & imm22 = 0
@
Table~F-3 includes most of the arithmetic and logical opcodes.
It must be specified slightly differently from the MIPS tables because
the values of the [[op3]] field are
``counted down'' instead of ``counted across.''
That is, the codes corresponding to \hbox{[[op = 0, 1, 2, ...]]}
are [[ADD, AND, OR, ...]], not [[ADD, ADDcc, TADDcc, ...]].
To get the proper numbering, we use the generating expression
\hbox{[[{0 to 63 columns 4}]]}, which generates the integers from
0~to~63 in the order $(0, 16, 32, 48, 1, \ldots, 63)$.
<>=
patterns
[ ADD ADDcc TADDcc WRxxx
AND ANDcc TSUBcc WRPSR
OR ORcc TADDccTV WRWIM
XOR XORcc TSUBccTV WRTBR
SUB SUBcc MULScc FPop1
ANDN ANDNcc SLL FPop2
ORN ORNcc SRL CPop1
XNOR XNORcc SRA CPop2
ADDX ADDXcc RDxxx JMPL
_ _ RDPSR RETT
UMUL UMULcc RDWIM Ticc
SMUL SMULcc RDTBR FLUSH
SUBX SUBXcc _ SAVE
_ _ _ RESTORE
UDIV UDIVcc _ _
SDIV SDIVcc _ _ ] is TABLE_F3 & op3 = {0 to 63 columns 4}
@ We have used [[WRxxx]] and [[RDxxx]] to stand for the groups of
opcodes that appear in the corresponding positions in Table~F-3.
These opcodes define variants of the
[[wr]] and [[rd]] instructions, which are overloaded.
The overloading is resolved by looking at the values of operands, as
shown by the footnotes to Table~F-3.
It probably would have been simpler to specify these purely as
synthetic instructions, but we've chosen to be slaves to the SPARC
manual.
<>=
patterns
WRASR is WRxxx & rd != 0 # should be rdi != 0
WRY is WRxxx & rd = 0
RDASR is RDxxx & rs1 != 0 # should be rs1i != 0
RDY is RDxxx & rs1 = 0
STBAR is RDxxx & rs1 = 15 & rd = 0
@ These patterns show a use of the inequality operator to specify
constraints on a field value.
The inequality constraint is a crock that just happens to work in
these examples.
The toolkit can't represent an inequality constraint directly, so
[[f != n]] is syntactic sugar for:
\begin{quote}
$\mathtt 0 \le f < n$ [[|]] ${\mathtt n < f} \le {\mathtt f}_{max}$,
\end{quote}
where ${\mathtt f}_{max}$ is the largest value the field can hold.
Since a disjunction almost never makes sense as an opcode, this is
asking for trouble. Luckily, in these cases [[n]] is either 0 or
${\mathtt f}_{max}$, so at most one of the disjuncts ever matches
anything, and what is left is equivalent to a real inequality
constraint.
We hope one day to remove this ugly wart from the toolkit.
@
Table F-4 includes the load and store opcodes.
<>=
patterns
[ LD LDA LDF LDC
LDUB LDUBA LDFSR LDCSR
LDUH LDUHA _ _
LDD LDDA LDDF LDDC
ST STA STF STC
STB STBA STFSR STCSR
STH STHA STDFQ STDCQ
STD STDA STDF STDC
_ _ _ _
LDSB LDSBA _ _
LDSH LDSHA _ _
_ _ _ _
_ _ _ _
LDSTUB LDSTUBA _ _
_ _ _ _
SWAP. SWAPA _ _ ] is TABLE_F4 & op3 = {0 to 63 columns 4}
@
Table~F-5 includes the floating-point arithmetic and conversion opcodes.
Following Table~F-5, we list all the opcodes with their corresponding
names, instead of using a complete table.
We've also chosen to divide the opcodes into two groups:
two-operand and three-operand instructions.
We further divide the opcodes based on their operand types.
This division makes it easy to use the names [[float2]], [[float3s]], etc.
to refer to the groups, without having to re-enumerate the members of
each group; these names are used later in the specification to specify
complete instructions.
<>=
patterns
float2 is any of [ FMOVs FNEGs FABSs FSQRTs FSQRTd FSQRTq
FiTOs FdTOs FqTOs FiTOd FsTOd FqTOd
FiTOq FsTOq FdTOq FsTOi FdTOi FqTOi ],
which is FPop1 & opf =
[ 0x1 0x5 0x9 0x29 0x2a 0x2b
0xc4 0xc6 0xc7 0xc8 0xc9 0xcb
0xcc 0xcd 0xce 0xd1 0xd2 0xd3 ]
float2s is FMOVs | FNEGs | FABSs | FSQRTs
FTOs is FiTOs | FsTOi
FTOd is FiTOd | FsTOd
FTOq is FiTOq | FsTOq
FdTO is FdTOi | FdTOs
FqTO is FqTOs | FqTOi
float3 is any of [ FADDs FADDd FADDq FSUBs FSUBd FSUBq FMULs
FMULd FMULq FDIVs FDIVd FDIVq FsMULd FdMULq ],
which is FPop1 & opf =
[ 0x41 0x42 0x43 0x45 0x46 0x47 0x49
0x4a 0x4b 0x4d 0x4e 0x4f 0x69 0x6e ]
float3s is FADDs | FSUBs | FMULs | FDIVs
float3d is FADDd | FSUBd | FMULd | FDIVd
float3q is FADDq | FSUBq | FMULq | FDIVq
@
\iffalse
These declarations illustrate the use of a
syntactic short hand for specifying groups of related opcodes.
\begin{quote}
{\em p} [[is any of []] {\em p0 p1 ... pn} [[], which is]] {\em generating expression}
\end{quote}
is a short hand for the declarations
\begin{quote}
[[[]]{\em p0 p1 ... pn} [[]]] is {\em generating expression}\\
{\em p} [[is]] {\em p0 $|$ p1 $|$ ... pn}
\end{quote}
We provide this syntactic shorthand because it eliminates
duplication of patterns that are both defined
and used in a single grouping.
\fi
This syntactic shorthand, which defines patterns and disjoins them at
one blow, reduces the possibility
of errors due to miscopying.
We didn't need this idiom to describe the MIPS because it uses just a
few tables, and the grouping of MIPS instructions doesn't correspond
to the organization of the tables.
We'll see it again, however, in specifying the rest of the SPARC, and
also on the Pentium and the Alpha.
@
Table F-6 includes the floating-point comparison opcodes.
Again, we write down the codes rather than use a table.
<>=
patterns
fcompares is any of [ FCMPs FCMPEs ],
which is FPop2 & opf = [ 0x51 0x55 ]
fcompared is any of [ FCMPd FCMPEd ],
which is FPop2 & opf = [ 0x52 0x56 ]
fcompareq is any of [ FCMPq FCMPEq ],
which is FPop2 & opf = [ 0x53 0x57 ]
@
Table~F-7 includes the branch and trap opcodes.
It is strange for a different reason; it is actually four tables in
one.
The rows of each table vary with the values of the [[cond]] field, but
the columns are described by four different patterns.
We can't create such a single table with the toolkit, nor would we
want to---we just split it into the four underlying tables, which
correspond to three kinds of conditional branches and one of
conditional traps.
<>=
patterns
ibranch is any of [ BN BE BLE BL BLEU BCS BNEG BVS
BA BNE BG BGE BGU BCC BPOS BVC ],
which is Bicc & cond = {0 to 15}
fbranch is any of [ FBN FBNE FBLG FBUL FBL FBUG FBG FBU
FBA FBE FBUE FBGE FBUGE FBLE FBULE FBO ],
which is FBfcc & cond = {0 to 15}
cbranch is any of [ CBN CB123 CB12 CB13 CB1 CB23 CB2 CB3
CBA CB0 CB03 CB02 CB023 CB01 CB013 CB012 ],
which is CBccc & cond = {0 to 15}
trap is any of [ TN TE TLE TL TLEU TCS TNEG TVS
TA TNE TG TGE TGU TCC TPOS TVC ],
which is Ticc & cond = {0 to 15}
branch is ibranch | fbranch | cbranch
@ We group the three kinds of branches into the pattern [[branch]].
People can never agree on the names of conditional branch
instructions.
We include a few of the most common synonyms, which are used in the
definition of
synthetic instructions.
<>=
patterns
B is BA
BGEU is BCC
BLU is BCS
BNZ is BNE
branch.synonyms is B | BGEU | BLU | BNZ
@
\subsection{Structured operands and typed constructors}
Unlike the MIPS, the SPARC has instructions whose
operands are not simple integers or fields.
For example,
the integer-arithmetic instructions take an operand that may be a register
or an immediate value,
and
the load and store instructions take an operand that computes an address.
The formats for these operands appear on page~84 in Appendix A
of the SPARC manual.
We specify such operands by creating a constructor type for them, giving
a constructor for each format.
We use the ``operand syntax'' name in the SPARC manual as the name of
the type; for example,
the constructors for a ``register or immediate'' operand are:
<>=
constructors
imode simm13! : reg_or_imm is i = 1 & simm13
rmode rs2 : reg_or_imm is i = 0 & rs2
@ The type [[reg_or_imm]] is {\em defined} by these declarations.
Used elsewhere, an operand of type [[reg_or_imm]] always denotes a
pattern created by the application of one of these two constructors.
Unlike the encoding procedures for ordinary untyped constructors,
the encoding procedures generated for these typed constructors
have no side effects;
they simply return values that can be passed to other constructors
requiring an operand of type [[reg_or_imm]].
Such constructors, notably the arithmetic constructors, appear
below.
@
Specifying addresses is a bit problematic because it's not clear what
convention to follow.
The underlying general mechanism is that a register is added to a
value of type [[reg_or_imm]], but there are many useful
abbreviations:%
\footnote{As far as {\tt lcc} goes, we could revert to the original mechanism}
<>=
constructors
generalA rs1 + reg_or_imm : address is rs1 & reg_or_imm
dispA rs1 + simm13! : address is generalA(rs1, imode(simm13!))
absoluteA simm13! : address is generalA(0, imode(simm13!))
indexA rs1 + rs2 : address is generalA(rs1, rmode(rs2))
indirectA rs1 : address is generalA(rs1, rmode(0))
@ Unfortunately We can't call the type [[address]]
because [[address]] is reserved for the toolkit
to describe the treatment of addresses in decoding specifications.
Another ugly wart.
@
\subsection{Load and store, read and write}
We group the load and store opcodes by their assembly syntax.
These groupings reflect the information provided on pages~90 and 92
for the load instructions and pages~95 and 97 for the stores.
Each group uses a different set of names for their register operands.
Those names are defined below.
<>=
patterns
loadg is LDSB | LDSH | LDUB | LDUH | LD | LDSTUB | SWAP.
loada is LDSBA | LDSHA | LDUBA | LDUHA | LDA | LDSTUBA | SWAPA
storeg is STB | STH | ST
storea is STBA | STHA | STA
@
The constructors for the load and store instructions illustrate
the use of the typed constructor [[address]] as an operand.
Addresses are bracketed, as in SPARC assembly language.
Because the constructors' output patterns are the
conjunctions of the opcodes and operands, they can be omitted.
Loads and stores of double words require even-odd register
pairs for the destination and source registers; their equations
specify that constraint.
For performance reasons, these equations don't appear in an ordinary
spec, but we want them when we validate the spec, so I have arranged
for the command \mbox{[[sed 's/# {/{/']]} to uncomment them
<>=
constructors
loadg [address], rd
LDD [address], rd # { rd = 2 * _ }
LDF [address], fd
LDDF [address], fd # { fd = 2 * _ }
LDC [address], cd
LDDC [address], cd # { cd = 2 * _ }
storeg rd, [address]
STD rd, [address] # { rd = 2 * _ }
STF fd, [address]
STDF fd, [address] # { fd = 2 * _ }
STC cd, [address]
STDC cd, [address] # { cd = 2 * _ }
@ We use the synonyms [[fd]] and [[cd]] for the destination register
[[rd]] when the affected register is a floating-point or
coprocessor register; same trick applies to [[fs1]] and [[fs2]].
This trick enables us to use different names for different registers,
which is helpful in generating a disassembler from these specifications.
<>=
fd 25:29 cd 25:29 fs1 14:18 fs2 0:4
@
The [[loada]] and [[storea]] only accept address operands constructed
from registers.
As in the SPARC manual, we introduce the constructor type [[regaddr]]
to describe this
operand.\footnote{In fact, [[address]] is a subtype of [[regaddr]].
The constructors [[indexA]] and [[indirectA]] are equivalent to
[[indexR]] and [[indirectR]]. We could specify these addresses by
adding a constructor to create an [[address]] from a [[regaddr]],
but that pollutes the name space.
It would be better to have subtypes.}
<>=
constructors
indexR rs1 + rs2 : regaddr is i = 0 & rs1 & rs2
indirectR rs1 : regaddr is i = 0 & rs2 = 0 & rs1
loada [regaddr]asi, rd
LDDA [regaddr]asi, rd # { rd = 2 * _ }
storea rd, [regaddr]asi
STDA rd, [regaddr]asi # { rd = 2 * _ }
@
Here are the names associated with the different registers.
They have to be quoted because the toolkit doesn't think the [[%]] character
can be part of an identifier.
<>=
names [ "%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
"%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7" ]
<>=
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" ]
<>=
names [ "%c0" "%c1" "%c2" "%c3" "%c4" "%c5" "%c6" "%c7"
"%c8" "%c9" "%c10" "%c11" "%c12" "%c13" "%c14" "%c15"
"%c16" "%c17" "%c18" "%c19" "%c20" "%c21" "%c22" "%c23"
"%c24" "%c25" "%c26" "%c27" "%c28" "%c29" "%c30" "%c31" ]
<<[[fieldinfo]] specifications>>=
fieldinfo
[ rd rs1 rs2 ] is [ <> ]
[ fd fs1 fs2 ] is [ <> ]
cd is [ <> ]
@
The SPARC also has several specialized load and store instructions.
The registers loaded and stored are implicit in the opcodes,
but we put them into the specifications as ``assembly-language
syntax.''
This technique helps us generate a disassembler, but more
importantly, it makes the specification easier to read and understand.
<>=
constructors
LDFSR [address], "%fsr"
LDCSR [address], "%csr"
STFSR "%fsr", [address]
STCSR "%csr", [address]
STDFQ "%fq", [address]
STDCQ "%cq", [address]
@
A similar group of instructions modify a different set of registers.
Perhaps because they move information between special-purpose
registers and general-purpose registers, instead of special-purpose
registers and memory, they are called ``read'' and ``write''
instructions instead of ``load'' and ``store'' instructions.
<>=
constructors
RDY "%y", rd
RDPSR "%psr", rd
RDWIM "%wim", rd
RDTBR "%tbr", rd
WRY rs1, reg_or_imm, "%y"
WRPSR rs1, reg_or_imm, "%psr"
WRWIM rs1, reg_or_imm, "%wim"
WRTBR rs1, reg_or_imm, "%tbr"
@
Finally, the instructions that read and write the ancillary state
register ([[asr]]) have their own special syntax.
<>=
constructors
RDASR "%asr"rs1i, rd
WRASR rs1, reg_or_imm, "%asr"rdi
STBAR
@ The registers [[rs1i]] and [[rdi]] are versions of [[rs1]] and [[rd]] that print
as integers.
<>=
rs1i 14:18 rdi 25:29
@
\subsection{Shift, logic, and arithmetic}
The logical, shift, and arithmetic
instructions share identical assembly language syntax,
so we can get away with only a single constructor declaration.
Including the shift instructions with the logical and arithmetic
instructions is a cheat,
but it's a cheat that works because the immediate field, if used, must be zero
in the high-order 8 bits.
<>=
patterns
logical is AND | ANDcc | ANDN | ANDNcc | OR | ORcc | ORN | ORNcc |
XOR | XORcc | XNOR | XNORcc
shift is SLL | SRL | SRA
arith is ADD | ADDcc | ADDX | ADDXcc | TADDcc | TADDccTV |
SUB | SUBcc | SUBX | SUBXcc | TSUBcc | TSUBccTV |
MULScc | UMUL | SMUL | UMULcc | SMULcc |
UDIV | SDIV | UDIVcc | SDIVcc |
SAVE | RESTORE
alu is logical | shift | arith
constructors
alu rs1, reg_or_imm, rd
@
\subsection{Branches and call}
As on the MIPS, a placeholder pattern must be specified before
the declaration of any constructor that refers to relocatable
addresses;
such a constructor may emit a placeholder in lieu of the relocated instruction.
We choose the [[UNIMP]] instruction because it causes an
illegal-instruction trap if executed.
<>=
placeholder for instruction is UNIMP & imm22 = 0xbad
@
Branch instructions come in two variants depending on the setting of the
annul ([[a]]) bit.
In the assembly language, the [[a]]~bit is notated with the suffix
[[,a]] when set, and with no suffix when clear.
We can work this notation into the toolkit specification by making
these suffixes the names of the values of the [[a]] bit:
<<[[fieldinfo]] specifications>>=
fieldinfo a is [ names [ "" ",a" ] ]
@ We then use [[a]] as a suffix to the branch instruction:
<>=
relocatable target raddr
constructors
branch^a target { target = L + 4 * disp22! } is L: branch & a & disp22
@ This declaration creates 96~constructors, two for each disjunct of
the [[branch]] pattern.
@
As on the MIPS, all of the branch instructions take a relocatable
address and emit a PC-relative displacement
in the output pattern.
To relate them,
we have simply used the equation that appears
on page~120 of the SPARC manual.
@
The [[call]] instruction is like the branches, except it uses a
30-bit displacement, and there is no annul bit.
<>=
constructors
call target { target = L + 4 * disp30! } is L: CALL & disp30
@ We write the constructor name with two trailing underscores because
we play overloading games below.
@
\subsection{Floating point}
Floating-point arithmetic instructions include two-operand
and three-operand variants.
Their output patterns are the implicit conjunctions of their opcodes
and operands so the output pattern is omitted.
Equations enforce that the register specified for a
double-word operand is even-numbered (i.e., specifies the first
member of an even-odd pair) and that the register for a quad-word operand
is a multiple of four (i.e., specifies the first in a four-register set).
As usual, those equations are commented out for speed.
<>=
constructors
float2s fs2, fd
FSQRTd fs2, fd # { fs2 = 2 * _, fd = 2 * _ }
FSQRTq fs2, fd # { fs2 = 4 * _, fd = 4 * _ }
FTOs fs2, fd
FTOd fs2, fd # { fd = 2 * _ }
FTOq fs2, fd # { fd = 4 * _ }
FdTO fs2, fd # { fs2 = 2 * _ }
FqTO fs2, fd # { fs2 = 4 * _ }
FqTOd fs2, fd # { fs2 = 4 * _, fd = 2 * _ }
FdTOq fs2, fd # { fs2 = 2 * _, fd = 4 * _ }
float3s fs1, fs2, fd
float3d fs1, fs2, fd # { fs1 = 2 * _, fs2 = 2 * _, fd = 2 * _ }
float3q fs1, fs2, fd # { fs1 = 4 * _, fs2 = 4 * _, fd = 4 * _ }
FsMULd fs1, fs2, fd # { fd = 4 * _ }
FdMULq fs1, fs2, fd # { fs1 = 2 * _, fs2 = 2 * _, fd = 4 * _ }
fcompares fs1, fs2
fcompared fs1, fs2 # { fs1 = 2 * _, fs2 = 2 * _ }
fcompareq fs1, fs2 # { fs1 = 4 * _, fs2 = 4 * _ }
@
\subsection{Miscellany}
The remaining instructions don't belong to any particular grouping.
<>=
constructors
NOP
FLUSH address
JMPL address, rd
RETT address
trap address
UNIMP imm22
@
The SPARC architecture manual defines [[sethi]] such that
it destroys the least significant ten bits on encoding.
Therefore, no single bi-directional defintion of [[sethi]]
can be written without loss of information.
Our solution is to provide two constructors:
[[sethi]] and [[decode_sethi]].
[[sethi]] encodes a [[SETHI]] instruction by ignoring the
10 low-order bits of [[val]]; [[sethi]] should be used for encoding.
The toolkit requires that all bits in a pattern be
constrained; [[decode_sethi]] constrains the 10 low-order
bits of [[val]] and should be used for decoding.
<>=
constructors
sethi "%hi("n")", rd is SETHI & rd & imm22 = n@[10:31]
decode_sethi "%hi("n")", rd { n@[0:9] = 0 } is SETHI & rd & imm22 = n@[10:31]
@
\subsection{Synthetic instructions}
\label{sec:sparc-synth}
The synthetic instructions are defined on pages~84--85 in the SPARC
manual; their definitions appear below.
When dealing with overloaded
instructions like [[call]], [[mov]], and [[clr]], we've reserved the
standard name (e.g., [[call]]) for the most common variant, using
either semi-mnemonic names (e.g., [[movr]] fopr move-register or
[[clrw]] for clear-word, [[calla]] for call-address) or names with trailing underscores (e.g.,
[[???_]]) for other variants.
<>=
constructors
jmp address is JMPL (address, "%g0")
calla address is JMPL (address, "%o7")
tst rs2 is ORcc ("%g0", rmode(rs2), "%g0")
ret is JMPL (dispA("%i7",8), "%g0")
retl is JMPL (dispA("%o7",8), "%g0")
restore_ is RESTORE ("%g0", rmode("%g0"), "%g0")
save_ is SAVE("%g0", rmode("%g0"), "%g0")
not rd is XNOR(rd, rmode("%g0"), rd)
not2 rs1, rd is XNOR(rs1, rmode("%g0"), rd)
neg rd is SUB ("%g0", rmode(rd), rd)
neg2 rs2, rd is SUB ("%g0", rmode(rs2), rd)
inc val, rd is ADD (rd, imode(val), rd)
inccc val, rd is ADDcc (rd, imode(val), rd)
dec val, rd is SUB (rd, imode(val), rd)
deccc val, rd is SUBcc (rd, imode(val), rd)
cmp rs1, reg_or_imm is SUBcc(rs1, reg_or_imm, "%g0") # must follow dec
btst reg_or_imm, rs1 is ANDcc(rs1, reg_or_imm, "%g0")
bset reg_or_imm, rd is OR (rd, reg_or_imm, rd)
bclr reg_or_imm, rd is ANDN(rd, reg_or_imm, rd)
btog reg_or_imm, rd is XOR (rd, reg_or_imm, rd)
mov reg_or_imm, rd is OR ("%g0", reg_or_imm, rd)
movr rs2, rd is OR ("%g0", rmode(rs2), rd)
clr rd is OR ("%g0", rmode("%g0"), rd)
clrw [address] is ST ("%g0", address)
clrb [address] is STB ("%g0", address)
clrh [address] is STH ("%g0", address)
@ Some of the constructors applied in
the output patterns use [[reg_or_imm]] or [[address]]
operands.
When such a value is a literal constant (e.g., register~[[%g0]]), we
apply either the [[imode]] or [[rmode]] constructor to it to get a
value of type [[reg_or_imm]] (e.g., [[rmode("%g0")]]).
@
The SPARC has only one conditionally assembled instruction.
The [[set]] instruction has three ways to load
an immediate value [[val]] into the register [[rd]].
If the low-order 10 bits of [[val]] are zero,
use [[sethi]] to load the high-order 20 bits.
If [[val]] fits in 13 signed bits,
[[OR]] it with register [[%g0]], which
is always zero.
In the general case, use [[sethi]] to load the high-order bits
into [[rd]] and [[OR]] to or in the low-order bits.
<>=
constructors
set val, rd
when { val@[0:9] = 0 } is sethi(val, rd)
otherwise is OR("%g0", imode(val), rd)
otherwise is sethi(val, rd); OR(rd, imode(val@[0:9]), rd)
@
Again, because [[set]] loses information, we must specify
[[decode_set]] for use in matching statements.
This is really gross. Can anything be done?
Having tried to use it in a SPARC disassembler, NR is now convinced
that this constructor is always useless, and he has deleted it from
the spec.
<>=
constructors
decode_set val, rd
when { val@[0:9] = 0 } is decode_sethi(val, rd)
when { val = val@[0:12]! } is OR("%g0", imode(val), rd)
otherwise is decode_sethi(val, rd); OR(rd, imode(val@[0:9]), rd)
@
\subsection{Application-specific specifications for the {\tt lcc} compiler}
@
[[lcc]] uses set, load, and store constructors that operate on
relocatable addresses instead of SPARC operands of type [[address]].
<>=
constructors
setr raddr, rd is set(raddr, rd)
# ldr raddr, rd is sethi(raddr, "%g1"); ld(dispA("%g1", raddr@[0:9]), rd)
# str rd, raddr is sethi(raddr, "%g1"); st(rd, dispA("%g1", raddr@[0:9]))
@
{\tt lcc} also supports a synthetic doubleword load and store
operating on base-displacement addresses only.
<>=
constructors
ld2f [rs1+disp!], fd is ldf(dispA(rs1, disp), fd); ldf(dispA(rs1, disp+4), fd+1)
st2f fd, [rs1+disp!] is stf(fd, dispA(rs1, disp)); stf(fd+1, dispA(rs1, disp+4))
@
The following constructor is used to emit relocatable addresses.
It is the same as that defined for the MIPS.
<>=
fields of addrtoken (32) addr32 0:31
placeholder for addrtoken is addr32 = 7
constructors
emit_raddr raddr is addr32 = raddr
@
As on the MIPS, {\tt mld} doesn't want to pay the overhead of checking
register numbers:
<>=
fieldinfo [ rs1 rs2 rd fd fs1 fs2 cd ] is [ guaranteed ]
@
\subsection{Application-specific specifications for the {\tt mld} linker}
@
[[mld]], defines set, load, and store constructors that operate on
relocatable addresses instead of SPARC operands of type [[address]].
<>=
constructors
setr raddr, rd is set(raddr, rd)
ldr raddr, rd is sethi(raddr, "%o2"); ld(dispA("%o2", raddr@[0:9]), rd)
str rd, raddr is sethi(raddr, "%o2"); st(rd, dispA("%o2", raddr@[0:9]))
@
{\tt mld} uses the synonyms we've defined for the branch instructions.
<>=
constructors
branch.synonyms^a target { target = L + 4 * disp22! } is
L: branch.synonyms & a & disp22
@
\label{overloading-trick}
Like the load and store instructions,
the SPARC call instruction is overloaded;
it accepts either a relocatable address or an SPARC-style [[address]].
The first style, which we've named [[call]], uses the real [[CALL]]
instruction, the second, which we've named [[calla]], uses [[JMPL]].
Because {\tt mld} generates code using a bottom-up tree walk,
it decides which kind of call instruction it
wants before it's actually ready to emit the call.
{\tt mld} wants to make up a cookie identifying the call, but doesn't
emit the call until the cookie is eaten.
The toolkit supports this trick using typed constructors; the cookie
is a value of type [[Function]].
<>=
constructors
relocfun target : Function is call(target)
addrfun address : Function is calla(address)
@ [[relocfun]] and [[addrfun]] create the cookies.
It looks like these constructors emit the calls, but actually they
don't have any side effects; the just return patterns representing the
instructions to be emitted.
Actually emitting such an instruction is the job of the [[_call]]
constructor:
<>=
constructors
_call Function is Function
@
The following constructor is used to emit relocatable addresses.
It is the same as that defined for the MIPS.
<>=
fields of addrtoken (32) addr32 0:31
placeholder for addrtoken is addr32 = 7
constructors
emit_raddr raddr is addr32 = raddr
@
As on the MIPS, {\tt mld} doesn't want to pay the overhead of checking
register numbers:
<>=
fieldinfo [ rs1 rs2 rd fd fs1 fs2 cd ] is [ guaranteed ]
@
\subsection{Validating against the SPARC assembler}
As on the MIPS, the same assembly name is used for integer and floating-point
variants of an instruction. The assembler uses the operand names
to disambiguate.
<>=
assembly component
decode_{*} is $1
{LDF,LDFSR,LDC,LDCSR} is LD
{LDDF,LDDC} is LDD
{STF,STFSR,STC,STCSR} is ST
{STDF,STDFQ,STDC,STDCQ} is STD
{RDY,RDASR,RDPSR,RDWIM,RDTBR} is RD
{WRY,WRASR,WRPSR,WRWIM,WRTBR} is WR
{not,neg}2 is $1
{set,ld,st,mov}r is $1
{ld2,st2}f is $1
{call}a is $1
SWAP. is SWAP
{*}{_,__} is $1
_{*} is $1
@ We need the extra syntax so that unbracketed [[address]] operands
are accepted by the assembler.
<>=
assembly syntax
absoluteA "%g0 + " simm13!
@
The suggested assembly syntax for
several SPARC instructions is not recognized by the
SunOS assembler, so those instructions are discarded.
[[emit_raddr]], [[ldr]], and [[str]] are application-specific
and are not in the SPARC assembly language.
<>=
discard FLUSH RDASR WRASR STBAR RETT emit_raddr ldr str decode_sethi
@
We don't have to put any special headers in assembly source used by
the checker.
<>=
@