188 lines
9.1 KiB
TeX
188 lines
9.1 KiB
TeX
\documentclass[a4paper,12pt]{book}
|
||
\usepackage{tikz}
|
||
\usepackage{hyperref}
|
||
\hypersetup{
|
||
linktoc=all
|
||
}
|
||
|
||
\title{Unnamed Machine}
|
||
\author{A Very Terrible 16-bit Machine}
|
||
|
||
\newcommand{\OpcodeTable}[5] {
|
||
\begin{tabular}{ c c c c c }
|
||
\hline
|
||
Opcode & Bit Pattern & Mnemonic & Operand 1 & Operand 2 \\
|
||
\hline\hline
|
||
#1 & #2 & #3 & #4 & #5 \\
|
||
\hline
|
||
\end{tabular}
|
||
}
|
||
|
||
\begin{document}
|
||
\maketitle
|
||
\tableofcontents
|
||
\chapter{Overview}
|
||
\section{Introduction}
|
||
This is a very poorly thought out 16-bit machine, but you've got to start somewhere. Currently debating between a CPU status register, 80x86 style, or just placing arithmetic results into a predetermined register. This is more of a load–store architecture to try and keep the instruction set simple. The machine will be big-endian.
|
||
\section{Registers}
|
||
The following are the general purpose registers that can be used.
|
||
\begin{itemize}
|
||
\item[] R1
|
||
\item[] ...
|
||
\item[] R8
|
||
\end{itemize}
|
||
Additionally, there will be a special status register that will be a signed 16 bit register that the compare and jump instructions will read or write to when determining what action, if any, they'll take.
|
||
\section{Memory Model}
|
||
Memory will be implicitly mapped I/O. The bottom 3201 bytes of memory will be reserved for the keyboard input and graphics.
|
||
A single byte is reserved for the keyboard's input. The current key will be stored in byte 0xF37E, with the most significant bit being a flag indicating that the keyboard
|
||
is ready to be read from. This means that the character encoding is actually 7 bits.
|
||
Video memory starts at 0xF37F (62335 decimal), and every byte represents an ASCII character in monochrome.
|
||
\begin{figure}[!htb]
|
||
\centering
|
||
\begin{tikzpicture}
|
||
\fill[gray!5] (0,0)rectangle(5,10);
|
||
%\draw (0,10) .. controls (-2,6) and (-2,4) .. (0,1);
|
||
%\draw (0,10) arc (0:180:3cm);
|
||
\draw (0,10) -- (5,10);
|
||
\draw (0,1) -- node[above] {Video 0xF37F} (5,1);
|
||
\draw (0,0) -- (5,0);
|
||
\node[label=right:Top 0x0000] at (5,10) {};
|
||
\node[label=right:Bottom 0xFFFF] at (5,0) {};
|
||
\end{tikzpicture}
|
||
\caption{Memory Layout}
|
||
\end{figure}
|
||
\chapter{Instruction Set Architecture}
|
||
\section{Instruction Encoding}
|
||
The instruction encoding is fixed width to exactly 8 bites wide.
|
||
The encoding for the instructions will differ depending on if the opcode requires a register as its first operand.
|
||
For instructions that require, as their first argument, a register the encoding format will be as shown in Figure \ref{fig:WithRegister}.
|
||
The lower 3 bits may be any bit pattern as long as at least one bit is set in the upper 5 bits.
|
||
%https://tex.stackexchange.com/questions/32598/force-latex-image-to-appear-in-the-section-in-which-its-declared
|
||
\begin{figure}[!htb]
|
||
\centering
|
||
\begin{tabular}{ c c }
|
||
Instruction & Register \\
|
||
\hline
|
||
XXXX X & 000 \\
|
||
\hline
|
||
\end{tabular}
|
||
\caption{Encoding Layout, Register Required}
|
||
\label{fig:WithRegister}
|
||
\end{figure}
|
||
|
||
Figure \ref{fig:NoRegisterEncoding} shows how encoding will look for instructions that lack arguments or do not require a register.
|
||
In contrast with the previous encoding scheme the upper 5 bits MUST be zero, allowing 7 possible instructions to use this format.
|
||
All zeroes is not considered a legal instruction.
|
||
|
||
\begin{figure}[!htb]
|
||
\centering
|
||
\begin{tabular}{ c c }
|
||
Must Be Zero & Instruction \\
|
||
\hline
|
||
0000 0 & XXX \\
|
||
\hline
|
||
\end{tabular}
|
||
\caption{Encoding Layout, No Register Required}
|
||
\label{fig:NoRegisterEncoding}
|
||
\end{figure}
|
||
|
||
\section{Notes}
|
||
For the opcodes that load or store data at the assembly language level we could have the mnemonics
|
||
"store" and "load" and have the assembler pick the opcode based on the inclusion of the word "byte"
|
||
or "word" for two bytes. That would make the assembly easier to read but put a bit more work on the
|
||
assembler. The Stack Pointer will start 2 bytes above the video memory start.
|
||
\section{COPY (Copy Word from Address)}
|
||
\OpcodeTable{0x08}{0000 1000}{copya}{Register}{Address}\\[6pt]
|
||
Copy a machine word from Operand 2 into Operand 1.
|
||
\section{COPY BYTE (Copy Byte from Address)}
|
||
\OpcodeTable{0x10}{0001 0000}{copyab}{Register}{Address}\\[6pt]
|
||
Copy a byte (8 bits) from Operand 2 into Operand 1, clearing the setting the most significant bits to zero.
|
||
\section{COPY (Copy Word Indirect Address)}
|
||
\OpcodeTable{0x18}{0001 1000}{copyra}{Register}{[Register]}\\[6pt]
|
||
Copy a machine word from the address stored in Operand 2 into Operand 1.
|
||
\section{COPY BYTE (Copy Byte Indirect Address)}
|
||
\OpcodeTable{0x20}{0010 0000}{copyrab}{Register}{[Register]}\\[6pt]
|
||
Copy a byte (8 bits) from the address stored in Operand 2 into Operand 1.
|
||
\section{COPY (Copy)}
|
||
\OpcodeTable{0x28}{0010 1000}{copyrara}{[Register]}{[Register]}\\[6pt]
|
||
Copy a machine word from the address stored in Operand 2 into the address stored in Operand 1.
|
||
\section{COPY BYTE (Copy Byte)}
|
||
\OpcodeTable{0x30}{0011 0000}{copyrarab}{[Register]}{[Register]}\\[6pt]
|
||
Copy a byte (8 bits) from the address stored in Operand 2 into the address stored in Operand 1.
|
||
\section{COPY (Copy)}
|
||
\OpcodeTable{0x38}{0011 1000}{copy}{Register}{Register}\\[6pt]
|
||
Copy a machine word from Operand 2 into Operand 1.
|
||
\section{COPY (Copy Immediate)}
|
||
\OpcodeTable{0xC0}{1100 0000}{copyi}{Register}{Constant}\\[6pt]
|
||
Copy a machine word from Operand 2 into Operand 1.
|
||
\section{COPY BYTE (Copy Byte)}
|
||
\OpcodeTable{0x40}{0100 0000}{copyb}{Register}{Constant}\\[6pt]
|
||
Copy a byte (8 bits) from Operand 2 into Operand 1.
|
||
\section{CMP (Compare)}
|
||
\OpcodeTable{0x48}{0100 1000}{cmp}{Register}{Register}\\[6pt]
|
||
Compares two registers and somewhere sets a result in the status register.
|
||
\section{CMPI (Compare Immediate)}
|
||
\OpcodeTable{0x50}{0101 0000}{cmpi}{Register}{Constant}\\[6pt]
|
||
Compares an immediate 2 byte value to the contents of a register setting the status register accordingly.
|
||
\section{ADD (Add)}
|
||
\OpcodeTable{0x58}{0101 1000}{add}{Register}{Register}\\[6pt]
|
||
Performs addition on a register with a value from another (or the same) register.
|
||
\section{SUB (Subtract)}
|
||
\OpcodeTable{0x60}{0110 0000}{sub}{Register}{Register}\\[6pt]
|
||
Performs subtraction on a register with a value from another (or the same) register.
|
||
\section{AND (Logical AND)}
|
||
\OpcodeTable{0x68}{0110 1000}{and}{Register}{Register}\\[6pt]
|
||
Logical ANDs the two registers together storing the result in operand 1.
|
||
\section{XOR (Logical Exclusive OR)}
|
||
\OpcodeTable{0x70}{0111 0000}{xor}{Register}{Register}\\[6pt]
|
||
Logical XORs the two registers together storing the result in operand 1.
|
||
\section{OR (Logical OR)}
|
||
\OpcodeTable{0x78}{0111 1000}{or}{Register}{Register}\\[6pt]
|
||
Logical ORs the two registers together storing the result in operand 1.
|
||
\section{NOT (Logical Negation)}
|
||
\OpcodeTable{0x80}{1000 0000}{not}{Register}{None}\\[6pt]
|
||
Inverts the bits of the target register.
|
||
\section{SHR (Shift Right)}
|
||
\OpcodeTable{0x88}{1000 1000}{shr}{Register}{Constant}\\[6pt]
|
||
Bit-wise shifts the contents of the register right Constant number of times.
|
||
\section{SHL (Shift Left)}
|
||
\OpcodeTable{0x90}{1001 0000}{shl}{Register}{Constant}\\[6pt]
|
||
Bit-wise shifts the contents of the register left Constant number of times.
|
||
\section{INC (Increment)}
|
||
\OpcodeTable{0x98}{1001 1000}{inc}{Register}{None}\\[6pt]
|
||
Increments the contents of the register by one. Over-flows will not be reported.
|
||
\section{DEC (Decrement)}
|
||
\OpcodeTable{0xA0}{1010 0000}{dec}{Register}{None}\\[6pt]
|
||
Decrements the contents of the register by one. Under-flows will not be reported.
|
||
\section{Push}
|
||
\OpcodeTable{0xA8}{1010 1000}{push}{Register}{None}
|
||
Pushes the value of Register onto the stack, decrementing the Stack Pointer by 2.
|
||
\section{Pop}
|
||
\OpcodeTable{0xB0}{1011 0000}{pop}{Register}{None}
|
||
Pops the top of the stack into Register, incrementing the Stack Pointer by 2.
|
||
\section{JMPI (Jump Indirect)}
|
||
\OpcodeTable{0xB8}{1011 1000}{jmpi}{Register}{None}\\[6pt]
|
||
Jumps unconditionally to a memory address stored in Operand 1. Sets the Program Counter to Operand 1.
|
||
\section{JMP (Jump)}
|
||
\OpcodeTable{0x02}{0000 0010}{jmp}{Address}{None}\\[6pt]
|
||
Jumps unconditionally to a memory address. Sets the Program Counter to Address.
|
||
\section{JZ (Jump if Zero)}
|
||
\OpcodeTable{0x03}{0000 0011}{jz}{Address}{None}\\[6pt]
|
||
Jumps to a memory address if the status flag is zero. Sets the Program Counter to Address.
|
||
\section{JG (Jump if Greater Than)}
|
||
\OpcodeTable{0x04}{0000 0100}{jg}{Address}{None}\\[6pt]
|
||
Jump to the Address if the status flag is greater than zero. Sets the Program Counter to Address.
|
||
\section{JL (Jump if Less Than)}
|
||
\OpcodeTable{0x05}{0000 0101}{jl}{Address}{None}\\[6pt]
|
||
Jumps to the address if the status flag is less than zero. Sets the Program Counter to Address.
|
||
\section{NOP (No Operation)}
|
||
\OpcodeTable{0x01}{0000 0001}{nop}{None}{None}\\[6pt]
|
||
Skips a clock cycle, incrementing the program counter.
|
||
\section{CALL (Call Subroutine)}
|
||
\OpcodeTable{0x06}{0000 0110}{call}{Address}{None}\\[6pt]
|
||
Pushes the base address to the stack and sets the Program Counter to Address.
|
||
\section{RET (Return from Subroutine)}
|
||
\OpcodeTable{0x07}{0000 0111}{ret}{None}{None}\\[6pt]
|
||
Pops the stack and sets the Program Counter to that value.
|
||
\end{document}
|