\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 \textit{options} byte are shown in Figure \ref{fig:opencoding}. The order of the arguments follows the AT\&T syntax, meaning the left hand argument is the \textit{source} and the right hand argument is the \textit{destination}. \section{Instruction Layout} %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); \draw (-8, 4) node[above] {7} rectangle (-6, 3) node[above = 1] {0}; \node at (-7, 2.5) {Opcode}; \draw (-5, 4) node[above] {7} rectangle (-3, 3) node[above = 1] {0}; \draw[dashed] (-4.5, 3) -- (-4.5, 4) node[above] {6}; \draw[dashed] (-4, 3) -- (-4, 4) node[above] {4}; \draw[dashed] (-3.5, 3) -- (-3.5, 4) node[above] {2}; \node at (-4, 2.5) {Mode}; \node (A) at (-4, 2.0) {(If required)}; %Operand One \draw (-2, 4) node[above] {31} rectangle (2, 3) node[above = 1] {0}; \draw[dashed] (1, 3) -- (1, 4) node[above] {7}; \draw[dashed] (0, 3) -- (0, 4) node[above] {15}; \node at (0, 2.5) {Source (Variable)}; \node at (0, 2.0) {(If required)}; %Operand Two \draw (3, 4) node[above] {31} rectangle (7, 3) node[above = 1] {0}; \draw[dashed] (6, 3) -- (6, 4) node[above] {7}; \draw[dashed] (5, 3) -- (5, 4) node[above] {15}; \node at (5, 2.5) {Destination (Variable)}; \node at (5, 2.0) {(If required)}; %Mode / argument break down. %Fanout \draw (A.west) -- (-8, 0); \draw (A.east) -- (3, 0); %Operand One Type \draw (-8, 0) node[above] {7} rectangle (-6, -1) node[above = 1] {6}; \node at (-7, -1.5) {Source Type}; %Operand Two Type \draw (-5, 0) node[above] {5} rectangle (-3, -1) node[above = 1] {4}; \node at (-4, -1.5) {Destination Type}; %Reserved \draw (-2, 0) node[above] {3} rectangle (0, -1) node[above = 1] {2}; \node at (-1, -1.5) {Reserved}; %Width Descriptor \draw (1, 0) node[above] {1} rectangle (3, -1) node[above = 1] {0}; \node at (2, -1.5) {Source Width}; \end{tikzpicture} \caption{Encoding} \label{fig:opencoding} % https://www.overleaf.com/learn/latex/Referencing_Figures \end{figure} %Argument options % Register first \newcommand{\rRArgH}{0}\newcommand{\rRaArgH}{1}\newcommand{\rAArgH}{3} % Register contains address first \newcommand{\raRArgH}{4}\newcommand{\raRaArgH}{5}\newcommand{\raAArgH}{7} % Immediate first \newcommand{\immRArgH}{8}\newcommand{\immRaArgH}{9}\newcommand{\immAArgH}{B} % Address first \newcommand{\aRArgH}{C}\newcommand{\aRaArgH}{D}\newcommand{\aAArgH}{F} %Width hex codes \newcommand{\byteWidthH}{1}\newcommand{\shortWidthH}{2}\newcommand{\intWidthH}{3} \begin{figure} \begin{tabularx}{\textwidth}{ | c | c | X | } \hline Type & Pattern & Description \\ \hline Register & 00 & Operand is a register \\ {[Register]} & 01 & Operand is a 32-bit address stored in a register \\ Immediate & 10 & Operand is an 8-, 16- or 32-bit value \\ {[Immediate]} & 11 & Operand is treated as a 32-bit address \\ \hline \multicolumn{3}{ | X | }{Source Operand Width Patterns} \\ \hline Invalid & 00 & Source must have a width \\ 8-bit & 01 & 8-bit wide source \\ 16-bit & 10 & 16-bit wide source \\ 32-bit & 11 & 32-bit wide source \\ \hline \end{tabularx} \caption{Operand Type and Width Bit Patterns} \label{fig:ModeSettingEncodingFigure} % https://www.overleaf.com/learn/latex/Referencing_Figures \end{figure} \clearpage \section{Instructions} The /r represents a byte that specifies a register. /immX is for the immediate data type, where \textit{X} defines the width, which are 8, 16, or 32 bits. An address is defined as /addrX with the \textit{X} denoting the size of the data that will be written which can be 8, 16 or 32 bits, with the address itself always being 32-bits wide. \subsection{Add} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 01 \rRArgH\byteWidthH & add byte /r, /r & /r & /r \\ 01 \rRArgH\shortWidthH & add short /r, /r & /r & /r \\ 01 \rRArgH\intWidthH & add (int) /r, /r & /r & /r \\ 01 \immRArgH\byteWidthH & add byte /imm8, /r & /imm8 & /r \\ 01 \immRArgH\shortWidthH & add short /imm16, /r & /imm16 & /r \\ 01 \immRArgH\intWidthH & add (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} OF and ZF. \subsection{Sub} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 02 \rRArgH\byteWidthH & sub byte /r, /r & /r & /r \\ 02 \rRArgH\shortWidthH & sub short /r, /r & /r & /r \\ 02 \rRArgH\intWidthH & sub (int) /r, /r & /r & /r \\ 02 \immRArgH\byteWidthH & sub byte /imm8, /r & /imm8 & /r \\ 02 \immRArgH\shortWidthH & sub short /imm16, /r & /imm16 & /r \\ 02 \immRArgH\intWidthH & sub (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} UF and ZF. \subsection{Mul} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 03 \rRArgH\byteWidthH & mul byte /r, /r & /r & /r \\ 03 \rRArgH\shortWidthH & mul short /r, /r & /r & /r \\ 03 \rRArgH\intWidthH & mul (int) /r, /r & /r & /r \\ 03 \immRArgH\byteWidthH & mul byte /imm8, /r & /imm8 & /r \\ 03 \immRArgH\shortWidthH & mul short /imm16, /r & /imm16 & /r \\ 03 \immRArgH\intWidthH & mul (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} OF and ZF. \subsection{Div} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 04 \rRArgH\byteWidthH & div byte /r, /r & /r & /r \\ 04 \rRArgH\shortWidthH & div short /r, /r & /r & /r \\ 04 \rRArgH\intWidthH & div (int) /r, /r & /r & /r \\ 04 \immRArgH\byteWidthH & div byte /imm8, /r & /imm8 & /r \\ 04 \immRArgH\shortWidthH & div short /imm16, /r & /imm16 & /r \\ 04 \immRArgH\intWidthH & div (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} UF and ZF. \subsection{Mov}\label{sec:mov} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 05 \rRArgH\byteWidthH & mov byte /r, /r & /r & /r \\ 05 \rRArgH\shortWidthH & mov short /r, /r & /r & /r \\ 05 \rRArgH\intWidthH & mov (int) /r, /r & /r & /r \\ 05 \rRaArgH\byteWidthH & mov byte /r, [/r] & /r & [/r] \\ 05 \rRaArgH\shortWidthH & mov short /r, [/r] & /r & [/r] \\ 05 \rRaArgH\intWidthH & mov (int) /r, [/r] & /r & [/r] \\ 05 \rAArgH\byteWidthH & mov byte /r, [imm32] & /r & [imm32] \\ 05 \rAArgH\shortWidthH & mov short /r, [imm32] & /r & [imm32] \\ 05 \rAArgH\intWidthH & mov (int) /r, [imm32] & /r & [imm32] \\ 05 \raRArgH\byteWidthH & mov byte [/r], /r & [/r] & /r \\ 05 \raRArgH\shortWidthH & mov short [/r], /r & [/r] & /r \\ 05 \raRArgH\intWidthH & mov (int) [/r], /r & [/r] & /r \\ 05 \raRaArgH\byteWidthH & mov byte [/r], [/r] & [/r] & [/r] \\ 05 \raRaArgH\shortWidthH & mov short [/r], [/r] & [/r] & [/r] \\ 05 \raRaArgH\intWidthH & mov (int) [/r], [/r] & [/r] & [/r] \\ 05 \raAArgH\byteWidthH & mov byte [/r], [imm32] & [/r] & [imm32] \\ 05 \raAArgH\shortWidthH & mov short [/r], [imm32] & [/r] & [imm32] \\ 05 \raAArgH\intWidthH & mov (int) [/r], [imm32] & [/r] & [imm32] \\ 05 \immRArgH\byteWidthH & mov byte imm8, /r & imm8 & /r \\ 05 \immRArgH\shortWidthH & mov short imm16, /r & imm16 & /r \\ 05 \immRArgH\intWidthH & mov (int) imm32, /r & imm32 & /r \\ 05 \immRaArgH\byteWidthH & mov byte imm8, [/r] & imm8 & [/r] \\ 05 \immRaArgH\shortWidthH & mov short imm16, [/r] & imm16 & [/r] \\ 05 \immRaArgH\intWidthH & mov (int) imm32, [/r] & imm32 & [/r] \\ 05 \immAArgH\byteWidthH & mov byte imm8, [imm32] & imm8 & [imm32] \\ 05 \immAArgH\shortWidthH & mov short imm16, [imm32] & imm16 & [imm32] \\ 05 \immAArgH\intWidthH & mov (int) imm32, [imm32] & imm32 & [imm32] \\ 05 \aRArgH\byteWidthH & mov byte [imm32], /r & [imm32] & /r \\ 05 \aRArgH\shortWidthH & mov short [imm32], /r & [imm32] & /r \\ 05 \aRArgH\intWidthH & mov (int) [imm32], /r & [imm32] & /r \\ 05 \aRaArgH\byteWidthH & mov byte [imm32], [/r] & [imm32] & [/r] \\ 05 \aRaArgH\shortWidthH & mov short [imm32], [/r] & [imm32] & [/r] \\ 05 \aRaArgH\intWidthH & mov (int) [imm32], [/r] & [imm32] & [/r] \\ 05 \aAArgH\byteWidthH & mov byte [imm32], [imm32] & [imm32] & [imm32] \\ 05 \aAArgH\shortWidthH & mov short [imm32], [imm32] & [imm32] & [imm32] \\ 05 \aAArgH\intWidthH & mov (int) [imm32], [imm32] & [imm32] & [imm32] \\ \hline \end{tabularx} \paragraph{Description} Copies the source (operand one) value to the destination (operand two). \paragraph{Flags Affected} None. \subsection{AND} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 06 \rRArgH\byteWidthH & and byte /r, /r & /r & /r \\ 06 \rRArgH\shortWidthH & and short /r, /r & /r & /r \\ 06 \rRArgH\intWidthH & and (int) /r, /r & /r & /r \\ 06 \immRArgH\byteWidthH & and byte /imm8, /r & /imm8 & /r \\ 06 \immRArgH\shortWidthH & and short /imm16, /r & /imm16 & /r \\ 06 \immRArgH\intWidthH & and (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} ZF. \subsection{OR} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 07 \rRArgH\byteWidthH & or byte /r, /r & /r & /r \\ 07 \rRArgH\shortWidthH & or short /r, /r & /r & /r \\ 07 \rRArgH\intWidthH & or (int) /r, /r & /r & /r \\ 07 \immRArgH\byteWidthH & or byte /imm8, /r & /imm8 & /r \\ 07 \immRArgH\shortWidthH & or short /imm16, /r & /imm16 & /r \\ 07 \immRArgH\intWidthH & or (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} ZF. \subsection{XOR} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 08 \rRArgH\byteWidthH & xor byte /r, /r & /r & /r \\ 08 \rRArgH\shortWidthH & xor short /r, /r & /r & /r \\ 08 \rRArgH\intWidthH & xor (int) /r, /r & /r & /r \\ 08 \immRArgH\byteWidthH & xor byte /imm8, /r & /imm8 & /r \\ 08 \immRArgH\shortWidthH & xor short /imm16, /r & /imm16 & /r \\ 08 \immRArgH\intWidthH & xor (int) /imm32, /r & /imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} ZF. \subsection{NOT} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 09 & xor /r & /r & None \\ \hline \end{tabularx} \paragraph{Description} Bit-wise NOT's the source (operand one) in place. \paragraph{Flags Affected} None. \subsection{SHL} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0A \immRArgH\byteWidthH & shl byte imm8, /r & imm8 & /r \\ 0A \immRArgH\shortWidthH & shl short imm16, /r & imm16 & /r \\ 0A \immRArgH\intWidthH & shl (int) imm32, /r & imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} OF and ZF. \subsection{SHR} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0B \immRArgH\byteWidthH & shr byte imm8, /r & imm8 & /r \\ 0B \immRArgH\shortWidthH & shr short imm16, /r & imm16 & /r \\ 0B \immRArgH\intWidthH & shr (int) imm32, /r & imm32 & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} UF and ZF. \subsection{NOP} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0C & nop & None & None \\ \hline \end{tabularx} \paragraph{Description} Performs no operation except for incrementing the program counter by one. \paragraph{Flags Affected} None. \subsection{CMP} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0D \rRArgH\intWidthH & cmp /r, /r & /r & /r \\ \hline \end{tabularx} \paragraph{Description} 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. \paragraph{Flags Affected} OF, UF and ZF. \subsection{JMP}\label{sec:jmp} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0E & jmp /imm32 & /imm32 & None \\ \hline \end{tabularx} \paragraph{Description} Jumps unconditionally to the absolute memory address specified in \textit{operand one}. \paragraph{Flags Affected} None. \subsection{JZ} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 0F & jz /imm32 & /imm32 & None \\ \hline \end{tabularx} \paragraph{Description} Jumps to the absolute memory address specified in \textit{operand one} if the zero flag (ZF) is zet. \paragraph{Flags Affected} None. \subsection{JG} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 10 & jg /imm32 & /imm32 & None \\ \hline \end{tabularx} \paragraph{Description} Jumps to the absolute memory address specified in \textit{operand one} if the overflow flag (OF) is zet. \paragraph{Flags Affected} None. \subsection{JL} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 11 & jl /imm32 & /imm32 & None \\ \hline \end{tabularx} \paragraph{Description} Jumps to the absolute memory address specified in \textit{operand one} if the underflow flag (UF) is zet. \paragraph{Flags Affected} None. %Maybe these in/out instructions could have a mode setting for choosing the width of the data written to the port. \subsection{Outb} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 12 & outb /imm8, /imm8 & /imm8 & /imm8 \\ \hline \end{tabularx} \paragraph{Description} Writes a byte of data to the port number specified in the destination (operand two). \paragraph{Flags Affected} None. \subsection{Inb} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 13 & inb /imm8, /r & /imm8 & /r \\ \hline \end{tabularx} \paragraph{Description} Reads a byte of data from the port number in source (operand one) to the destination (operand two) register. \paragraph{Flags Affected} None. \subsection{HLT} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 14 & hlt & None & None \\ \hline \end{tabularx} \paragraph{Description} Halts the processor preventing it from executing the next instruction until an interrupt is received. \paragraph{Flags Affected} None. \subsection{CLI}\label{sec:cli} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 15 & cli & None & None \\ \hline \end{tabularx} \paragraph{Description} Clears interrupts, preventing the processor from responding to interrupts. \paragraph{Flags Affected} None. \subsection{ENI}\label{sec:eni} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 16 & eni & None & None \\ \hline \end{tabularx} \paragraph{Description} Enables interrupts, allowing the processor to respond to interrupts. \paragraph{Flags Affected} None. \subsection{INT}\label{sec:int} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 17 & int /imm8 & /imm8 & None \\ \hline \end{tabularx} \paragraph{Description} 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}. \paragraph{Flags Affected} None. \subsection{LIVT}\label{sec:livt} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 18 & livt /imm32 & /imm32 & None \\ \hline \end{tabularx} \paragraph{Description} Registers a 1024 byte block of memory starting at \textit{operand one} as the Interrupt Vector Table. \paragraph{Flags Affected} None. \subsection{PUSHA} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 19 & pusha & None & None \\ \hline \end{tabularx} \paragraph{Description} Pushes all general purpose registers to the stack in order starting from \textit{r1} to \textit{r8}. \paragraph{Flags Affected} None. \subsection{POPA} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 20 & popa & None & None \\ \hline \end{tabularx} \paragraph{Description} Pops all general purpose registers from the stack, restoring them, in the reverse order of \textit{r8} to \textit{r1}. \paragraph{Flags Affected} None. \subsection{CALL}\label{sec:call} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 21 & call & None & None \\ \hline \end{tabularx} \paragraph{Description} Calls a subroutine pushing the Program Counter (PC), plus one to return execution to the next opcode, to the stack. \paragraph{Flags Affected} None. \subsection{RET} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 22 & ret & None & None \\ \hline \end{tabularx} \paragraph{Description} Returns from the subroutine, popping the stack to restore the return address into the Program Counter (PC). \paragraph{Flags Affected} None. \subsection{PUSH} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 23 & push /r & /r & None \\ \hline \end{tabularx} \paragraph{Description} Pushes the contents of register \textit{Operand One} onto the top of the stack. \paragraph{Flags Affected} None. \subsection{POP} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 24 & pop /r & /r & None \\ \hline \end{tabularx} \paragraph{Description} Pops 32-bits from the top of the stack into the register \textit{Operand One}. \paragraph{Flags Affected} None.