\chapter{Instruction Set Architecture} Instructions are variable width with most instructions' width being determined by the \textit{mode} byte that follows immediately after the opcode byte. The \textit{mode} byte is split into four parts, with the upper nibble describing what the types of source and destination operands the instruction is to deal with. Following those four bits is two reserved bits and finally the final two bits in the least significant half of the lower nibble, the \textit{source width}. Depending on the \textit{source type} bits, the next number of bytes to be read for the source operand can be 8-, 16- or 32-bits and the same applies to the \textit{destination type} bits. A more visual layout of this may be found in Figure \ref{fig:opencoding}. \newcommand{\OpcodeTable}[5] { \noindent \begin{minipage}{\textwidth} \begin{tabularx}{\textwidth}{ | X | X | X | X | } \hline Opcode Hex & Instruction & Operand 1 & Operand 2 \\ \hline #1 & #2 & #3 & #4 \\ \hline \end{tabularx} \paragraph{Description} #5 \end{minipage} } \section{Instruction Layout} % 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] {5}; \draw[dashed] (-4, 3) -- (-4, 4) node[above] {4}; \draw[dashed] (-3.5, 3) -- (-3.5, 4) node[above] {1}; \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 %\paragraph{Note} Figure \ref{fig:ModeSettingEncodingFigure} shows the options for the \textit{Mode} byte. \end{figure} \def\registerType{00}\def\registerValueType{01} \def\immediateType{10}\def\addressType{11} \def\noWidth{00}\def\eightBitWidth{01}\def\sixteenBitWidth{10}\def\thirtyBitWidth{11} \def\registerBit{0}\def\registerBitA{8} \def\eightBit{1}\def\eightBitA{9} \def\sixteenBit{2}\def\sixteenBitA{A} \def\thirtyBit{4}\def\thirtyBitA{C} \def\none{F} \begin{figure} \begin{tabularx}{\textwidth}{ | c | c | X | } \hline Type & Pattern & Description \\ \hline Register & \registerType & Operand is a register \\ \&Register & \registerValueType & Operand is a 32-bit address stored in a register \\ Immediate & \immediateType & Operand is an 8-, 16- or 32-bit value \\ Address & \addressType & Operand is a 32-bit address \\ \hline \multicolumn{3}{ | X | }{Source Operand Width Patterns} \\ \hline Invalid & \noWidth & Source must have a width \\ 8-bit & \eightBitWidth & 8-bit wide source \\ 16-bit & \sixteenBitWidth & 16-bit wide source \\ 32-bit & \thirtyBitWidth & 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 \registerBit\registerBit & add /r, /r & /r & /r \\ 01 \eightBit\registerBit & add /imm8, /r & /imm8 & /r \\ 01 \sixteenBit\registerBit & add /imm16, /r & /imm16 & /r \\ 01 \thirtyBit\registerBit & add /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 \registerBit\registerBit & sub /r, /r & /r & /r \\ 02 \eightBit\registerBit & sub /imm8, /r & /imm8 & /r \\ 02 \sixteenBit\registerBit & sub /imm16, /r & /imm16 & /r \\ 02 \thirtyBit\registerBit & sub /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 \registerBit\registerBit & mul /r, /r & /r & /r \\ 03 \eightBit\registerBit & mul /imm8, /r & /imm8 & /r \\ 03 \sixteenBit\registerBit & mul /imm16, /r & /imm16 & /r \\ 03 \thirtyBit\registerBit & mul /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 \registerBit\registerBit & div /r, /r & /r & /r \\ 04 \eightBit\registerBit & div /imm8, /r & /imm8 & /r \\ 04 \sixteenBit\registerBit & div /imm16, /r & /imm16 & /r \\ 04 \thirtyBit\registerBit & div /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} \begin{tabularx}{\textwidth}{ | c | X | c | c | } \hline Opcode & Instruction & Operand One & Operand Two \\ \hline 05 \registerBit\registerBit & mov /r, /r & /r & /r \\ 05 \registerBit\eightBitA & mov byte /r, /addr & /r & /addr \\ 05 \registerBit\sixteenBitA & mov short /r, /addr & /r & /addr \\ 05 \registerBit\thirtyBitA & mov (int) /r, /addr & /r & /addr \\ 05 \registerBitA\registerBit & mov [/r], /r & [/r] & /r \\ 05 \registerBitA\registerBitA & mov (int) [/r], [/r] & [/r] & [/r] \\ 05 \registerBitA\eightBitA & mov byte [/r], /addr & [/r] & /addr \\ 05 \registerBitA\sixteenBitA & mov short [/r], /addr & [/r] & /addr \\ 05 \registerBitA\thirtyBitA & mov (int) [/r], /addr & [/r] & /addr \\ 05 \eightBitA\registerBit & mov byte /addr, /r & /addr & /r \\ 05 \sixteenBitA\registerBit & mov short /addr, /r & /addr & /r \\ 05 \thirtyBitA\registerBit & mov (int) /addr, /r & /addr & /r \\ 05 \eightBit\registerBit & mov byte /imm8, /r & /imm8 & /r \\ 05 \eightBit\registerBitA & mov byte /imm8, [/r] & /imm8 & [/r] \\ 05 \eightBit\eightBitA & mov byte /imm8, /addr & /imm8 & /addr \\ 05 \sixteenBit\registerBit & mov short /imm16, /r & /imm16 & /r \\ 05 \sixteenBit\registerBitA & mov short /imm16, [/r] & /imm16 & [/r] \\ 05 \sixteenBit\sixteenBitA & mov short /imm16, /addr & /imm16 & /addr \\ 05 \thirtyBit\registerBit & mov (int) /imm32, /r & /imm32 & /r \\ 05 \thirtyBit\registerBitA & mov (int) /imm32, [/r] & /imm32 & [/r] \\ 05 \thirtyBit\thirtyBitA & mov (int) /imm32, /addr & /imm32 & /addr \\ \hline \end{tabularx} \paragraph{Description} Copies the source (operand one) value to the destination (operand two). \paragraph{Flags Affected} None. \subsection{AND} \OpcodeTable{01 /r /r}{and /r, /r}{Register}{Register}{Bit-wise ANDs \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{OR} \OpcodeTable{01 /r /r}{or /r, /r}{Register}{Register}{Bit-wise ORs \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{XOR} \OpcodeTable{01 /r /r}{xor /r, /r}{Register}{Register}{Bit-wise exclusive ORs \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{NOT} \OpcodeTable{01 /r}{not /r}{Register}{None}{Bit-wise negates \textit{Operand 1} placing the result into \textit{Operand 1}.} \subsection{SHL} \OpcodeTable{01 /r /i8}{shl /r, /i8}{Register}{Immediate}{Shifts the bits of \textit{Operand 1} left \textit{Operand 2} times.} \subsection{SHR} \OpcodeTable{01 /r /i8}{shr /r, /i8}{Register}{Immediate}{Shifts the bits of \textit{Operand 1} right \textit{Operand 2} times.} \subsection{NOP} \OpcodeTable{01}{nop}{None}{None}{No operation, increments the Program Counter by one.} %Oh this control flow will be interesting, juggling flags is not something I'm used to. \subsection{CMP} \OpcodeTable{01 /mod /r /r}{cmp /r, /r}{Register}{Register}{Subtracts \textit{Operand 2} from \textit{Operand 1} setting the Zero Flag if the result is zero. If \textit{Operand 2} is larger then the Sign Flag is set, otherwise the Sign Flag will be cleared.} \subsection{JMP} \OpcodeTable{01 /mod /i32}{jmp /i32}{Immediate}{None}{Unconditionally jumps to address \textit{Operand 1}.} \subsection{JZ} \OpcodeTable{01 /i32}{jz /i32}{Immediate}{None}{Jumps to address \textit{Operand 1} if the Zero Flag is set.} \subsection{JG} \OpcodeTable{01 /mod /i32}{jg /i32}{Immediate}{None}{Jumps to address \textit{Operand 1} if the Sign Flag is set.} \subsection{JL} \OpcodeTable{01 /mod /i32}{jl /i32}{Immediate}{None}{Jumps to address \textit{Operand 1} if the Sign Flag is not set.} %Maybe these in/out instructions could have a mode setting for choosing the width of the data written to the port. \subsection{Outb} \OpcodeTable{01 /r /r}{add /r, /r}{8-Bit}{Register}{Writes an 8-bit value from \textit{Operand 2} into port number \textit{Operand 1}.} \subsection{Inb} \OpcodeTable{01 /r /r}{inb /r, /r}{Register}{8-Bit}{Reads an 8-bit byte from the port number \textit{Operand 2}, writing it into \textit{Operand 1}.} \subsection{HLT} \OpcodeTable{01}{hlt}{None}{None}{Halts the processor until a new interrupt is received.} \subsection{CLI}\label{sec:cli} \OpcodeTable{01}{cli}{None}{None}{Clears the interrupt flag preventing the processor from receiving interrupts.} \subsection{ENI}\label{sec:eni} \OpcodeTable{01}{eni}{None}{None}{Sets the interrupt flag allowing the processor to receive interrupts.} \subsection{INT}\label{sec:int} \OpcodeTable{01 /i8}{int /i8}{Immediate}{None}{Triggers software interrupt number \textit{Operand 1}.} \subsection{LIVT}\label{sec:livt} \OpcodeTable{00 /mod /i32}{livt /i32}{Immediate}{None}{Installs the Interrupt Vector Table located at memory address \textit{Operand 1}.}