\chapter{Instruction Set Architecture} Instructions are variable width with their total length being determined by the mode setting byte that immediately follows the opcode byte. A break down of what a nibble means in the mode setting byte can be found in Figure \ref{fig:ModeSettingEncodingFigure}. Figure \ref{fig:opencoding} shows the layout of an instruction with the mode setting byte split down the middle to indicate the top nibble defines what \textit{Operand One} is meant to be interpreted as, followed by the lower nibble for \textit{Operand Two}. Depending on what mode is set for each operand there may be no bytes to follow the instruction (like in the case of nop) or there may be 8 bytes to follow (like in the case of mov [address], [address], assuming absolute addresses). \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} } \def\gap{0.25pt} \def\minX{0}\def\maxX{\textwidth} \def\minY{-0.25}\def\maxY{0.25} \def\lnWidth{\textwidth / 4} \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}[h] \begin{tikzpicture} %Opcode Byte \draw (\minX, 0) -- (\lnWidth, 0) node[midway, below=1em] {Opcode}; \draw (\minX, \minY) node[below] {7} -- (\minX, \maxY); \draw (\lnWidth, \minY) -- (\lnWidth, \maxY) node[above] {7}; %Mode setting byte \draw (\lnWidth, 0) -- (\lnWidth * 2, 0) node[midway, above=1em] (ModeSettingByteLabel) {Mode}; \draw node[above of=ModeSettingByteLabel] {(if required)}; \draw (\lnWidth, \minY) node[below] {0} -- (\lnWidth, \maxY); \draw (\lnWidth * 2, \minY) node[below] {0} -- (\lnWidth * 2, \maxY); \draw (\lnWidth + \lnWidth / 2, \minY) node[below] (ModeByteMiddleLabel) {4 3} -- (\lnWidth + \lnWidth / 2, \maxY); %Operand One \draw (\lnWidth * 2, 0) -- (\lnWidth * 3, 0) node[midway, below=1em] (OperOneLabel) {Operand One}; \draw (\lnWidth * 2, \minY) -- (\lnWidth * 2, \maxY) node[above] {31/15/7}; \draw (\lnWidth * 3, \minY) node[below] {0} -- (\lnWidth * 3, \maxY); \draw node[below of=OperOneLabel] {(if required)}; %Operand Two \draw (\lnWidth * 3, 0) -- (\lnWidth * 4, 0) node[midway, below=1em] (OperTwoLabel) {Operand Two}; \draw (\lnWidth * 3, \minY) -- (\lnWidth * 3, \maxY) node[above] {31/15/7} node[above=1.5em] {Operand Widths Based on Mode}; \draw (\lnWidth * 4, \minY) node[below] {0} -- (\lnWidth * 4, \maxY); \draw node[below of=OperTwoLabel] {(if required)}; \end{tikzpicture} \caption{Encoding} \label{fig:opencoding} % https://www.overleaf.com/learn/latex/Referencing_Figures \paragraph{Note} The \textit{Mode} byte is split into an upper nibble and a lower nibble which will contain any of the values shown in Figure \ref{fig:ModeSettingEncodingFigure}. \end{figure} \def\register{0000}\def\registerA{1000} \def\eightBit{0001}\def\eightBitA{1001} \def\sixteenBit{0010}\def\sixteenBitA{1010} \def\thirtyBit{0100}\def\thirtyBitA{1100} \def\none{1111} \begin{figure} \begin{tabularx}{\textwidth}{ | X | X | X | } \hline Operand & Immediate Value & Value As Address \\ \hline Register & \register & 1000 \\ 8-Bit & 0001 & 1001 \\ 16-Bit & 0010 & 1010 \\ 32-Bit & 0100 & 1100 \\ None & 1111 & 1111 \\ \hline \end{tabularx} \caption{Operand Modes Bit Pattern} \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. /iX is for the immediate data type, where \textit{X} defines the width, which are 8, 16, or 32 bits. \subsection{Add} \OpcodeTable{01 /m /r /r}{add /r, /r}{Register}{Register}{Sums \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 2}.} \subsection{Sub} \OpcodeTable{01 /r /r}{sub /r, /r}{Register}{Register}{Subtracts \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{Mul} \OpcodeTable{01 /r /r}{mul /r, /r}{Register}{Register}{Multiplies \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{Div} \OpcodeTable{01 /r /r}{div /r, /r}{Register}{Register}{Divides \textit{Operand 1} and \textit{Operand 2} placing the result into \textit{Operand 1}.} \subsection{Mov} \OpcodeTable{04 /mod /r /r}{mov /mod /r, /r}{Register}{Register}{Copies the 32-bit value from \textit{Operand 2} to \textit{Operand 1}.} \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} \OpcodeTable{01}{cli}{None}{None}{Clears the interrupt flag preventing the processor from receiving interrupts.} \subsection{ENI} \OpcodeTable{01}{eni}{None}{None}{Sets the interrupt flag allowing the processor to receive interrupts.} \subsection{INT}\label{int} \OpcodeTable{01 /i8}{int /i8}{Immediate}{None}{Triggers software interrupt number \textit{Operand 1}.} \subsection{LIVT}\label{livt} \OpcodeTable{00 /mod /i32}{livt /i32}{Immediate}{None}{Installs the Interrupt Vector Table located at memory address \textit{Operand 1}.}