Files
damn_simple_architecture/book/dsa-arch/instruction_set.html
T
2025-06-27 18:30:26 +01:00

318 lines
21 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Instruction Set - damn_simple_architecture</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "../";
const default_light_theme = "light";
const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">damn_simple_architecture</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="instruction-set"><a class="header" href="#instruction-set">Instruction Set</a></h1>
<h1 id="instruction-set-1"><a class="header" href="#instruction-set-1">Instruction Set</a></h1>
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
<p>Below is an overview of the instruction set and the various operands. This table is non-exhaustive and may be updated as the design changes. <em>Please note that the table spans multiple pages.</em></p>
<p>Also note that immediate (constant/literal) arguments are 16-bits long in I (immediate argument) typed instructions. For more information on this, refer to instruction encoding.</p>
<div class="table-wrapper"><table><thead><tr><th>Type</th><th>Description</th></tr></thead><tbody>
<tr><td>R</td><td>Used when an instruction takes one or more register arguments, but no immediates. This type is also used by shift and rotation operations, as it contains a 5 bit shift amount field.</td></tr>
<tr><td>I</td><td>Used when an instruction takes at most two register arguments as well as a halfword immediate argument. This is typically used by immediate arithmetic operations e.g. addi, as well as loads and stores (where a base register and immediate offset are passed). Also used by branching instructions. The operand is a signed offset from the current value of PCX.</td></tr>
<tr><td>J</td><td>Used by jumps excluding jr, which uses a register as its argument. Jumps are absolute addresses, but there is a 256MB region around PCX since the argument is 26 bits. Since arguments are always word aligned, we bitshift left twice and set the upper 4 bits to match that of the value in PCX. This then forms a valid word-sized address.</td></tr>
</tbody></table>
</div>
<p><strong>Note:</strong>
J-type instructions are currently unused.</p>
<h3 id="r-type-instruction-encoding"><a class="header" href="#r-type-instruction-encoding">R-type Instruction Encoding</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Bits 31-26</th><th>Bits 25-21</th><th>Bits 20-16</th><th>Bits 15-11</th><th>Bits 10-6</th><th>Bits 5-0</th></tr></thead><tbody>
<tr><td>Opcode</td><td>Source Reg 1</td><td>Source Reg 2</td><td>Destination Reg</td><td>Shift Amount</td><td>Unused</td></tr>
</tbody></table>
</div>
<p>The shift amount must be 0 when the opcode does not match a shift instruction or else the CPU will assert an Illegal Instruction exception.</p>
<p>If any register field is not used, it should be set to the special value NOREG, defined in the Registers section of this document. Failure to do so may result in an Illegal Instruction exception as this is undefined for an instruction that does not expect this argument to be provided.</p>
<h3 id="i-type-instruction-encoding"><a class="header" href="#i-type-instruction-encoding">I-type Instruction Encoding</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Bits 31-26</th><th>Bits 25-21</th><th>Bits 20-16</th><th>Bits 15-0</th></tr></thead><tbody>
<tr><td>Opcode</td><td>Source Reg</td><td>Dest Reg</td><td>16-bit immediate</td></tr>
</tbody></table>
</div>
<p>I-type instructions are used when 16-bit immediate arguments are desired. This could be for
immediate arithmetic instructions (like adding 10 to the value in ACC), or loads and stores, where we may want to access the ith index of an array using an offset.</p>
<h3 id="j-type-instruction-encoding"><a class="header" href="#j-type-instruction-encoding">J-type Instruction Encoding</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Bits 31-26</th><th>Bits 25-0</th></tr></thead><tbody>
<tr><td>Opcode</td><td>Address</td></tr>
</tbody></table>
</div>
<p>J-type instructions are used for absolute jumps.</p>
<p>The 26-bit address is converted to a 32-bit address by:
The 26-bit address field is shifted left by 2 bits (due to word alignment we ignore the 2 least significant bits).
Combined with the upper 4 bits of the PC to form a 32-bit address (bitwise OR).</p>
<p>The jump range: 256MB region around current PC. For longer jumps than this, see jr (Jump to word address in register).</p>
<p>To compute this address, the linker should find the address of the label, cut off the top 4 bits, then rightward shift twice. The CPU will then convert this to the actual 32-bit address following the steps outlined above.</p>
<h2 id="instructions"><a class="header" href="#instructions">Instructions</a></h2>
<h3 id="hardware-instructions"><a class="header" href="#hardware-instructions">Hardware Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Hex</th><th>Type</th><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td>0x00</td><td>R</td><td>NOP</td><td>n/a</td><td>No operation - a blank line.</td></tr>
<tr><td>0x01</td><td>R</td><td>MOV</td><td>SrcReg, DestReg</td><td>Copies from SrcReg to DestReg.</td></tr>
<tr><td>0x02</td><td>R</td><td>MOVS</td><td>SrcReg, DestReg</td><td>Copies from SrcReg to DestReg, sign extending the value to take up a full word.</td></tr>
<tr><td>0x03</td><td>I</td><td>LDB</td><td>BaseReg, Offset, DestReg</td><td>Loads a byte from memory address (base + offset) into DestReg. The effective address must be byte-aligned.</td></tr>
<tr><td>0x04</td><td>I</td><td>LDBS</td><td>BaseReg, Offset, DestReg</td><td>Loads a sign-extended byte from memory address (base + offset) into DestReg. The effective address must be byte-aligned.</td></tr>
<tr><td>0x05</td><td>I</td><td>LDH</td><td>BaseReg, Offset, DestReg</td><td>Loads a half-word from memory address (base + offset) into DestReg. The effective address must be 2-byte-aligned.</td></tr>
<tr><td>0x06</td><td>I</td><td>LDHS</td><td>BaseReg, Offset, DestReg</td><td>Loads a sign-extended half-word from memory address (base + offset) into DestReg. The effective address must be 2-byte-aligned.</td></tr>
<tr><td>0x07</td><td>I</td><td>LDW</td><td>BaseReg, Offset, DestReg</td><td>Loads a word from memory address (base + offset) into DestReg. The effective address must be 4-byte-aligned.</td></tr>
<tr><td>0x08</td><td>I</td><td>STB</td><td>SrcReg, BaseReg, Offset</td><td>Stores a byte from SrcReg in memory address (base + offset). The effective address must be byte-aligned.</td></tr>
<tr><td>0x09</td><td>I</td><td>STH</td><td>SrcReg, BaseReg, Offset</td><td>Stores a half-word from SrcReg in memory address (base + offset). The effective address must be 2-byte-aligned.</td></tr>
<tr><td>0x0A</td><td>I</td><td>STW</td><td>SrcReg, BaseReg, Offset</td><td>Stores a word from SrcReg in memory address (base + offset). The effective address must be 4-byte-aligned.</td></tr>
<tr><td>0x0B</td><td>I</td><td>LLI</td><td>DstReg, Value</td><td>Loads a 16-bit literal value into reg, setting the bottom 16 bits of the word. To populate the upper 16 bits, see LUI.</td></tr>
<tr><td>0x0C</td><td>I</td><td>LUI</td><td>DstReg, Value</td><td>Loads a 16-bit literal value into reg, setting the top 16 bits of the word. To populate the lower 16 bits, see LLI.</td></tr>
<tr><td>0x0D</td><td>I</td><td>JMP</td><td>DestReg, Offset | Address</td><td>Unconditionally jumps to the calculated address or direct address.</td></tr>
<tr><td>0x0E</td><td>I</td><td>JEQ</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if equal flag set.</td></tr>
<tr><td>0x0F</td><td>I</td><td>JNE</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if the equal flag is not set.</td></tr>
<tr><td>0x10</td><td>I</td><td>JGT</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if greater than flag set.</td></tr>
<tr><td>0x11</td><td>I</td><td>JGE</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if greater than flag or equal flag set.</td></tr>
<tr><td>0x12</td><td>I</td><td>JLT</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if less than flag set.</td></tr>
<tr><td>0x13</td><td>I</td><td>JLE</td><td>DestReg, Offset | Address</td><td>Jumps to the calculated address or direct address if less than flag or equal flag set.</td></tr>
<tr><td>0x14</td><td>R</td><td>CMP</td><td>Reg1, Reg2</td><td>Compares the value of Reg1 to the value in Reg2. The results of the comparisons are set in the Status register.</td></tr>
<tr><td>0x15</td><td>R</td><td>INC</td><td>Reg</td><td>Increments the value in the given register.</td></tr>
<tr><td>0x16</td><td>R</td><td>DEC</td><td>Reg</td><td>Decrements the value in the given register.</td></tr>
<tr><td>0x17</td><td>R</td><td>SHL</td><td>Reg, Literal | ValReg</td><td>Left shifts the value in Reg by the given amount (either a register, or a literal value).</td></tr>
<tr><td>0x18</td><td>R</td><td>SHR</td><td>Reg, Literal | ValReg</td><td>Right shifts the value in Reg by the given amount (either a register, or a literal value).</td></tr>
<tr><td>0x19</td><td>R</td><td>ADD</td><td>Src1, Src2, Dest</td><td>Adds the value of Src2 to Src1 and writes the result to Dest.</td></tr>
<tr><td>0x1A</td><td>R</td><td>SUB</td><td>Src1, Src2, Dest</td><td>Subtracts the value of Src2 from Src1 and writes the result to Dest.</td></tr>
<tr><td>0x1B</td><td>R</td><td>AND</td><td>Src1, Src2, Dest</td><td>Performs bitwise AND on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x1C</td><td>R</td><td>OR</td><td>Src1, Src2, Dest</td><td>Performs bitwise OR on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x1D</td><td>R</td><td>NOT</td><td>Src, Dest</td><td>Performs bitwise NOT on Src storing the result in Dest.</td></tr>
<tr><td>0x1E</td><td>R</td><td>XOR</td><td>Src1, Src2, Dest</td><td>Performs bitwise XOR on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x1F</td><td>R</td><td>NAND</td><td>Src1, Src2, Dest</td><td>Performs bitwise NAND on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x20</td><td>R</td><td>NOR</td><td>Src1, Src2, Dest</td><td>Performs bitwise NOR on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x21</td><td>R</td><td>XNOR</td><td>Src1, Src2, Dest</td><td>Performs bitwise XNOR on Src1 and Src2 storing the result in Dest.</td></tr>
<tr><td>0x22</td><td>I</td><td>INT</td><td>Literal</td><td>Initiates an interrupt with the given 8 bit interrupt code. Triggering an interrupt invokes the following behaviour: The return address is saved to the RET register. The stack base ptr is set to the kernel stack.</td></tr>
<tr><td>0x23</td><td>R</td><td>IRT</td><td>n/a</td><td>Returns from an interrupt.</td></tr>
<tr><td>0x24</td><td>R</td><td>HLT</td><td>n/a</td><td>Halts the processor.</td></tr>
<tr><td>0x25</td><td>I</td><td>IADD</td><td>Src1, Literal, Dest</td><td>An immediate version of addition taking a 16-bit immediate value.</td></tr>
<tr><td>0x26</td><td>I</td><td>ISUB</td><td>Src1, Literal, Dest</td><td>An immediate version of subtraction taking a 16-bit immediate value.</td></tr>
</tbody></table>
</div>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../dsa-arch.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dsa.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../dsa-arch.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../dsa.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>