323 lines
15 KiB
TeX
323 lines
15 KiB
TeX
\ExplSyntaxOn
|
|
|
|
\int_new:N \l_options_count
|
|
\int_new:N \l_options_loop_count
|
|
% Opcode, Opcode Name, Description, Flags Affected, Options
|
|
% Maybe have an optional argument to relabel the operands Source and Destination
|
|
\NewDocumentCommand{\createoptabletwoparam}{ m m m m m }{
|
|
\int_set:Nn \l_options_loop_count {1}
|
|
\clist_clear_new:N \l_options
|
|
|
|
\clist_set:Nn \l_options {#3}
|
|
|
|
\int_set:Nn \l_options_count { \clist_count:N \l_options }
|
|
|
|
\__start_op_table:
|
|
|
|
\clist_map_inline:Nn \l_options {
|
|
|
|
\str_case:nnF{##1} {
|
|
{0}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~r,~r & r & r \\ }
|
|
}{1}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~r,~[r] & r & [r] \\ }
|
|
}{2}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~[r],~r & [r] & r \\ }
|
|
}{5}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~r,~[imm] & r & [imm] \\ }
|
|
}{8}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~imm,~r & imm & r \\ }
|
|
}{9}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2 ~imm,~[r] & imm & [r] \\ }
|
|
}{A}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~[imm],~r & imm & r \\ }
|
|
}{C}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~imm,~imm & imm & imm \\ }
|
|
}{D}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1~##1\_ & #2~imm,~[imm] & imm & [imm] \\ }
|
|
}
|
|
}{ \tl_put_right:Nn \l_tmpa_seq {#1~##1\_ & INVALID & -- & -- \\ } }
|
|
|
|
\int_compare:nT { \l_options_loop_count < \l_options_count }
|
|
{
|
|
\tl_put_right:Nn \l_tmpa_seq { \midrule }
|
|
}
|
|
|
|
\int_incr:N \l_options_loop_count
|
|
}
|
|
|
|
\__end_op_table:nn {#5} {#4}
|
|
|
|
\tl_use:N \l_tmpa_seq
|
|
}
|
|
|
|
\NewDocumentCommand{\createoptableoneparam}{ m m m m m}{
|
|
\__start_op_table:
|
|
|
|
\str_case:nnF{#3} {
|
|
{imm}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1 & #2~imm & imm & None \\ }
|
|
}{reg}{
|
|
\tl_put_right:Nn \l_tmpa_seq { #1 & #2~r & r & None \\ }
|
|
}
|
|
}{ \tl_put_right:Nn \l_tmpa_seq {#1 & INVALID & -- & -- \\ } }
|
|
|
|
\__end_op_table:nn {#5} {#4}
|
|
|
|
\tl_use:N \l_tmpa_seq
|
|
}
|
|
|
|
\NewDocumentCommand{\createoptablenoparam}{ m m m m }{
|
|
|
|
\__start_op_table:
|
|
|
|
\tl_put_right:Nn \l_tmpa_seq { #1 & #2 & None & None \\ }
|
|
|
|
\__end_op_table:nn {#4} {#3}
|
|
|
|
\tl_use:N \l_tmpa_seq
|
|
}
|
|
|
|
\cs_new:Nn \__start_op_table: {
|
|
\seq_clear:N \l_tmpa_seq
|
|
|
|
\tl_set:Nn \l_tmpa_seq { \begin{tabular}{ l l l l } \toprule }
|
|
|
|
\tl_put_right:Nn \l_tmpa_seq { Opcode & Instruction & Operand~One & Operand~Two \\ \midrule }
|
|
}
|
|
|
|
\cs_new:Npn \__end_op_table:nn #1 #2 {
|
|
\tl_put_right:Nn \l_tmpa_seq { \bottomrule }
|
|
\tl_put_right:Nn \l_tmpa_seq { \end{tabular} }
|
|
\tl_put_right:Nn \l_tmpa_seq { \paragraph{Description} #1 }
|
|
\tl_put_right:Nn \l_tmpa_seq { \paragraph{Flags Affected} #2 }
|
|
}
|
|
|
|
\ExplSyntaxOff
|
|
|
|
\chapter{Instruction Set Architecture}
|
|
In general instructions are variable length depending on the number of arguments and their width. The first byte of an instruction is the \textit{opcode} which tells the machine what operation is to be performed. If one or more arguments are required, then the next byte is the \textit{options} byte which describes the type and width of the argument(s). The exact meaning of all the bits in the options byte are shown in Figure \ref{fig:encodingphysicallayout}.
|
|
|
|
\section{Instruction Layout}
|
|
The logical ordering of the arguments follows the AT\&T syntax, meaning the left hand argument is the source and the right hand argument is the destination. This means to move the literal integer of, say 40, into the \textit{r1} register one would write this instruction as follows:
|
|
\begin{verbatim}
|
|
mov 40, r1
|
|
\end{verbatim}
|
|
This is in contrast with how the data is laid out physically in memory, following the conventions described in section \ref{sec:conventions}~\nameref{sec:conventions}. Figure \ref{fig:encodingphysicallayout} shows how an instruction would be laid out. The operands can be of varying sizes based on the low nibble of the Options byte or, depending on the instruction, may only consist of an Opcode byte. The Source and Destination may have any one of the following three widths, in any combination:
|
|
\begin{verbatim}
|
|
byte, short, or word
|
|
\end{verbatim}
|
|
For the exact definition of these data types please refer to section \ref{sec:conventions} as mentioned above.
|
|
%Because this machine is little endian, the opcode byte is physically located on the right hand-side of a word.
|
|
% Placement info here: https://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions#Figures
|
|
% Paths: https://tikz.dev/tikz-paths
|
|
\begin{figure}[ht]
|
|
\begin{tikzpicture}
|
|
%\draw[help lines] (-8,-5) grid (8,5);
|
|
\node [draw, fit={(- 8.00, 0.00) (-12.00, 0.75)}, inner sep=0, label=center:Destination] (argtwo) {};
|
|
\node [draw, fit={(- 4.00, 0.00) (- 8.00, 0.75)}, inner sep=0, label=center:Source] (argone) {};
|
|
\node [draw, fit={(- 2.00, 0.00) (- 4.00, 0.75)}, inner sep=0, label=center:Options] (options) {};
|
|
\node [draw, fit={( 0.00, 0.00) (- 2.00, 0.75)}, inner sep=0, label=center:Opcode] (opcode) {};
|
|
\node [draw, fit={( 0.00, 1.50) (- 4.00, 2.25)}, inner sep=0, label=center:Offset] (offset) {};
|
|
|
|
\node at (argtwo.north)[above] {(if required)};
|
|
\node at (argtwo.north west)[above] {31};
|
|
\node at (argone.north)[above] {(if required)};
|
|
\node at (argone.north west)[above] {24 23};
|
|
\node at (options.north west)[above] {16 15};
|
|
\node at (opcode.north west)[above] {8 7};
|
|
\node at (options.south)[below] {(if required)};
|
|
\node at (opcode.north east)[above] {0};
|
|
|
|
\node at (offset.north east)[above] {32};
|
|
\node at (offset.north west)[above] {39};
|
|
\node at (offset.north)[above] {(if required)};
|
|
% Use the calc library to calculate the center of two points.
|
|
% Reference: https://tex.stackexchange.com/a/71479
|
|
%\node at ($(highestbit.north)!0.5!(lowestbit.north)$)[above] {Physical Layout};
|
|
\end{tikzpicture}
|
|
\caption{Physical Layout}
|
|
\label{fig:encodingphysicallayout} % https://www.overleaf.com/learn/latex/Referencing_Figures
|
|
\end{figure}
|
|
|
|
\subsection{Options Bit}
|
|
The Options byte makes use of all 8 bits to encode something about the instruction that precedes it. Reading the byte from left to right, we have the following properties:
|
|
\begin{itemize}
|
|
\item Operand Type
|
|
\item Operand as Pointer
|
|
\item Destination Offset
|
|
\item Source Width.
|
|
\end{itemize}
|
|
|
|
Starting with the high nibble we have two \quotes{columns}, \textit{Operand Type} and \textit{Operand as Pointer}, both spanning 2 bits for a total of 4 bits. The first two bits describe the type of operand we're expecting, zero (0) for \textit{register} and one (1) for an \textit{immediate} value. Bit 7 is for the source operand and bit 6 for the destination operand. Following this same layout (source then destination) we have two bits that say whether or not the operand should be treated as a pointer, zero (0) for no and one (1) for yes. For register type arguments this means to read the contents of whatever register is specified and treat that value as a full width pointer. If the argument is an immediate value, then we simply read one word and treat that word as a pointer.
|
|
|
|
The lower nibble consists of two \quotes{columns}, the same width as the previous two, that describe what kind of offset, if any, to apply to the destination operand and how many bytes are to be read from the source operand. Starting with bit 3 and ending on bit 2 we have the number of bytes to read for an offset. Bits 1 and 0 say how many bytes should be read from the source, which could be a register, an immediate value, or a pointer.
|
|
\begin{figure}[ht]
|
|
\begin{tabular}{cccccccc}
|
|
\toprule
|
|
%\multicolumn{8}{c}{Bit Position} \\
|
|
\multicolumn{2}{c}{Type} & \multicolumn{2}{c}{Pointer} & \multicolumn{2}{c}{ } & \multicolumn{2}{c}{ } \\
|
|
7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\
|
|
\midrule
|
|
Source & Destination & Source & Destination & \multicolumn{2}{c}{Offset} & \multicolumn{2}{c}{Source Width} \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{Options Bit Physical Layout}
|
|
\label{fig:optionsbitlayout}
|
|
\end{figure}
|
|
|
|
\section{Instructions}
|
|
Following is a complete listing of all supported instructions where the first two hexadecimal digits (starting from the left most digit in the Opcode column) represents the actual opcode byte that would be expected in object code. If the instruction expects an options byte then the next hexadecimal digit denotes the operand mode for the instruction. An underscore (\_) denotes that the low nibble of the options byte is to be set based on the instruction.
|
|
|
|
The Instruction column shows the assembly syntax that represents the opcode, with the letter \textit{r} representing any register such as \textit{r32} and \textit{imm} for any numeric literal. This numeric literal could be a memory address or a number to start a counter, the semantics don't matter in this instance. The last two columns simply provide at a glance the operands, in the order they appear in the assembly sample, Source and Destination respectively.
|
|
\subsection{Add}
|
|
\createoptabletwoparam{01}{add}{0, 8}{ OF and ZF. }
|
|
{
|
|
Adds two unsigned values together, the source (operand one) and the destination (operand two), storing the result in destination. The overflow flag (OF) is set if the result is less than the source and the zero flag (ZF) is set when the result of addition is zero.
|
|
}
|
|
\subsection{Sub}
|
|
\createoptabletwoparam{02}{sub}{0, 8}{ UF and ZF. }
|
|
{
|
|
Subtracts two unsigned values, the source (operand one) and the destination (operand two), storing the result in destination. The underflow flag (UF) is set if the result is greater than the source and the zero flag (ZF) is set when the result of subtraction is zero.
|
|
}
|
|
\subsection{Mul}
|
|
\createoptabletwoparam{03}{mul}{0, 8}{ OF and ZF. }
|
|
{
|
|
Multiplies two unsigned values together, the source (operand one) and the destination (operand two), storing the result in destination. The overflow flag (OF) is set if the result is less than the source and the zero flag (ZF) is set when the result of addition is zero.
|
|
}
|
|
\subsection{Div}
|
|
\createoptabletwoparam{04}{div}{0, 8}{ UF and ZF. }
|
|
{
|
|
Divides two unsigned values, the source (operand one) and the destination (operand two), storing the result in destination. The underflow flag (UF) is set if the result is greater than the source and the zero flag (ZF) is set when the result of subtraction is zero.
|
|
}
|
|
\subsection{Mov}\label{sec:mov}
|
|
\createoptabletwoparam{05}{mov}{0, 1, 2, 5, 8, 9, A, D}{ None. }
|
|
{
|
|
Copies the source (operand one) value to the destination (operand two).
|
|
}
|
|
\subsection{AND}
|
|
\createoptabletwoparam{06}{and}{0, 8}{ ZF. }
|
|
{
|
|
Bitwise AND's the source (operand one) with the destination (operand two) storing the result in the destination. If the result of the operation is zero then the Zero Flag (ZF) is set.
|
|
}
|
|
\subsection{OR}
|
|
\createoptabletwoparam{07}{or}{0, 8}{ ZF. }
|
|
{
|
|
Bitwise OR's the source (operand one) with the destination (operand two) storing the result in the destination. If the result of the operation is zero then the Zero Flag (ZF) is set.
|
|
}
|
|
\subsection{XOR}
|
|
\createoptabletwoparam{08}{xor}{0, 8}{ ZF. }
|
|
{
|
|
Bitwise exclusive OR's (XOR) the source (operand one) with the destination (operand two) storing the result in the destination. If the result of the operation is zero then the Zero Flag (ZF) is set.
|
|
}
|
|
\subsection{NOT}
|
|
\createoptableoneparam{09}{not}{reg}{ None. }
|
|
{
|
|
Bit-wise NOT's the source (operand one) in place.
|
|
}
|
|
\subsection{SHL}
|
|
\createoptabletwoparam{0A}{shl}{8}{ OF and ZF. }
|
|
{
|
|
Shifts the destination (operand two) left \textit{operand one} times in place. If the source is smaller than before the operation the overflow flag (OF) is set. If the result of the operation is zero than the zero flag (ZF) is set.
|
|
}
|
|
\subsection{SHR}
|
|
\createoptabletwoparam{0B}{shr}{8}{ UF and ZF. }
|
|
{
|
|
Shifts the destination (operand two) right \textit{operand one} times in place. If the source is larger than before the operation the underflow flag (UF) is set. If the result of the operation is zero than the zero flag (ZF) is set.
|
|
}
|
|
\subsection{NOP}
|
|
\createoptablenoparam{0C}{nop}{ None. }
|
|
{
|
|
Performs no operation except for incrementing the program counter by one.
|
|
}
|
|
\subsection{CMP}
|
|
\createoptabletwoparam{0D}{cmp}{0, 8}{ OF, UF and ZF. }
|
|
{
|
|
Compares \textit{operand one} to \textit{operand two} by subtracting \textit{operand one} from \textit{operand two}, updating the status register with the results. If \textit{operand one} is larger than the result, and the result is not zero, the overflow flag (OF) is set. If \textit{operand one} is smaller than the result, and the result is not zero, the underflow flag (UF) is set. And if the result of the subtraction is zero the zero flag (ZF) is set.
|
|
}
|
|
\subsection{JMP}\label{sec:jmp}
|
|
\createoptableoneparam{0E}{jmp}{imm}{ None. }
|
|
{
|
|
Jumps unconditionally to the absolute memory address specified in \textit{operand one}.
|
|
}
|
|
\subsection{JZ}
|
|
\createoptableoneparam{0F}{jz}{imm}{ None. }
|
|
{
|
|
Jumps to the absolute memory address specified in \textit{operand one} if the zero flag (ZF) is zet.
|
|
}
|
|
\subsection{JG}
|
|
\createoptableoneparam{10}{jg}{imm}{ None. }
|
|
{
|
|
Jumps to the absolute memory address specified in \textit{operand one} if the overflow flag (OF) is zet.
|
|
}
|
|
\subsection{JL}
|
|
\createoptableoneparam{11}{jl}{imm}{ None. }
|
|
{
|
|
Jumps to the absolute memory address specified in \textit{operand one} if the underflow flag (UF) is zet.
|
|
}
|
|
%Maybe these in/out instructions could have a mode setting for choosing the width of the data written to the port.
|
|
\subsection{Outb}
|
|
\createoptabletwoparam{12}{outb}{C}{ None. }
|
|
{
|
|
Writes a byte of data to the port number specified in the destination (operand two).
|
|
}
|
|
\subsection{Inb}
|
|
\createoptabletwoparam{13}{inb}{8}{ None. }
|
|
{
|
|
Reads a byte of data from the port number in source (operand one) to the destination (operand two) register.
|
|
}
|
|
\subsection{HLT}
|
|
\createoptablenoparam{14}{hlt}{ None. }
|
|
{
|
|
Halts the processor preventing it from executing the next instruction until an interrupt is received.
|
|
}
|
|
\subsection{CLI}\label{sec:cli}
|
|
\createoptablenoparam{15}{cli}{ None. }
|
|
{
|
|
Clears interrupts, preventing the processor from responding to interrupts.
|
|
}
|
|
\subsection{ENI}\label{sec:eni}
|
|
\createoptablenoparam{16}{eni}{ None. }
|
|
{
|
|
Enables interrupts, allowing the processor to respond to interrupts.
|
|
}
|
|
\subsection{INT}\label{sec:int}
|
|
\createoptableoneparam{17}{int}{imm}{ None. }
|
|
{
|
|
Triggers a software interrupt of type \textit{operand one} causing the flow of execution to jump to the registered subroutine in the Interrupt Vector Table at index \textit{operand one}.
|
|
}
|
|
\subsection{LIVT}\label{sec:livt}
|
|
\createoptableoneparam{18}{livt}{imm}{ None. }
|
|
{
|
|
Registers a 1024 byte block of memory starting at \textit{operand one} as the Interrupt Vector Table.
|
|
}
|
|
\subsection{PUSHA}
|
|
\createoptablenoparam{19}{pusha}{ None. }
|
|
{
|
|
Pushes all general purpose registers to the stack in order starting from \textit{r1} to \textit{r32}.
|
|
}
|
|
\subsection{POPA}
|
|
\createoptablenoparam{20}{popa}{ None. }
|
|
{
|
|
Pops all general purpose registers from the stack, restoring them, in the reverse order of \textit{r32} to \textit{r1}.
|
|
}
|
|
\subsection{CALL}\label{sec:call}
|
|
\createoptableoneparam{21}{call}{imm}{ None. }
|
|
{
|
|
Calls a subroutine pushing the Program Counter (PC), plus one to return execution to the next opcode, to the stack.
|
|
}
|
|
\subsection{RET}
|
|
\createoptablenoparam{22}{ret}{ None. }
|
|
{
|
|
Returns from the subroutine, popping the stack to restore the return address into the Program Counter (PC).
|
|
}
|
|
\subsection{PUSH}
|
|
\createoptableoneparam{23}{push}{reg}{ None. }
|
|
{
|
|
Pushes the contents of register \textit{Operand One} onto the top of the stack.
|
|
}
|
|
\subsection{POP}
|
|
\createoptableoneparam{24}{pop}{reg}{ None. }
|
|
{
|
|
Pops one word from the top of the stack into the register \textit{Operand One}.
|
|
} |