\section{Machine opcodes}
\label{sec:machine-opcodes}

In general, a machine opcode value uniquely identifies a
particular operation on a particular machine.  On different machines,
a specific value will (most-likely) correspond to different
operations.  In other words, an opcode value does not encode any
target information beyond the target-relative operation.  You must
interpret the opcode value in the context of a particular target.  The
same interpretation rules apply for Machine-SUIF opcodes.  

In Machine SUIF, an [[opcode]] is an integer.  When you define an
opcode for a machine instruction, you must use the opcode enumeration
appropriate for your current target.  Each target architecture defines
its own extensible opcode [[enum]] in an [[opcodes.h]] file.  All
targets of the same architecture family use the same opcode [[enum]].
We provide an OPI function, called [[target_implements]], that allows
you to determine if an opcode is supported on your current target.

<<opcode OPI>>=
bool target_implements(int opcode);
@

In Machine SUIF, an opcode has an associated \emph{name}.  It is the string
by which the current target's assembler recognizes the opcode.  The
opcode-to-name mapping is one-to-many since an opcode's name may vary from
one vender-OS to another.  We provide an OPI function, called
[[opcode_name]], that you can use to get an opcode's target-appropriate
name.

<<opcode OPI>>=

char* opcode_name(int opcode);
@

Given an opcode [[enum]], if you know that you want to generate
SUIFvm instructions, you can write:

\begin{verbatim}
    Instr *mi = new_instr_alm(d_opnd, MOV, s_opnd);
\end{verbatim}

Or, if you know that you want to generate an Alpha integer move
instruction, you can write:

\begin{verbatim}
    Instr *mi = new_instr_alm(d_opnd, MOV, s_opnd);
\end{verbatim}

In general, having knowledge of an architecture's opcode [[enum]] is
sufficient to write a target-specific pass or function, but not very useful
for the development of parameterized passes.  To create an instruction that
is specific to a target without having to know the target at
pass-development time, the OPI provides some target-specific opcode
generators.

For example, [[opcode_move]] returns the move opcode appropriate for
your current target:

\begin{verbatim}
    Instr *mi = new_instr_alm(d_opnd, opcode_move(d_type), s_opnd);
\end{verbatim}

This generator is called a typed opcode generator because you must
provide a type to get a type-appropriate opcode.  In other words,
[[opcode_move]] uses the [[d_type]] parameter to determine if it should
generate an integer or floating-point move opcode.  

The OPI calls for provides three typed opcode generators:

<<opcode OPI>>=

int opcode_move(TypeId);
int opcode_load(TypeId);
int opcode_store(TypeId);
@

where

\begin{itemize}
  \item [[opcode_move]]: generates a type- and target-appropriate move opcode;
  \item [[opcode_load]]: generates a type- and target-appropriate load opcode;
  \item [[opcode_store]]: generates a type- and target-appropriate store opcode;
\end{itemize}

and the following untyped opcode generators:

<<opcode OPI>>=

int opcode_line();
int opcode_ubr();
@

where

\begin{itemize}
  \item [[opcode_line]]: generates a target-appropriate line pseudo-op opcode.
  \item [[opcode_ubr]]: generates   a target-appropriate unconditional branch
        opcode. 
\end{itemize}

The OPI also provides the function [[opcode_cbr_inverse]] which takes a
conditional branch opcode and returns the opcode checking the opposite
condition.

<<opcode OPI>>=

int opcode_cbr_inverse(int opcode);
@

Finally, there are two global opcodes, which are the same across all
architectures:

<<opcode OPI>>=

const int opcode_null = 0;
const int opcode_label = 1;
@

Since these are considered part of each architecture's opcode space, the
first target-specific opcode in each opcode [[enum]] should start with
value 2.

%%  FIXME: describe handling of opcode extensions



\subsection{Header file for module [[opcodes.h]]}

The interface file has the following layout:

<<opcodes.h>>=
/* file "machine/opcodes.h" */

<<Machine-SUIF copyright>>

#ifndef MACHINE_OPCODES_H
#define MACHINE_OPCODES_H

#include <machine/copyright.h>

#ifndef SUPPRESS_PRAGMA_INTERFACE
#pragma interface "machine/opcodes.h"
#endif

#include <machine/substrate.h>

<<opcode OPI>>

#endif /* MACHINE_OPCODES_H */
@
