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

908 lines
56 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>damn_simple_architecture</title>
<meta name="robots" content="noindex">
<!-- 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="introduction"><a class="header" href="#introduction">Introduction</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="the-damn-simple-architecture"><a class="header" href="#the-damn-simple-architecture">The Damn Simple Architecture</a></h1>
<div style="break-before: page; page-break-before: always;"></div><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><div style="break-before: page; page-break-before: always;"></div><h1 id="dsa-assembly-language-instruction-reference"><a class="header" href="#dsa-assembly-language-instruction-reference">DSA Assembly Language Instruction Reference</a></h1>
<h2 id="overview-1"><a class="header" href="#overview-1">Overview</a></h2>
<p>This document provides a comprehensive reference for the DSA (Damn Simple Architecture) assembly language, including all hardware instructions and pseudo-instructions with their syntax variations and usage examples.</p>
<h2 id="table-of-contents"><a class="header" href="#table-of-contents">Table of Contents</a></h2>
<ul>
<li><a href="instructions.html">Instructions</a></li>
<li><a href="tooling.html">Tooling</a></li>
<li><a href="imports.html">Imports</a></li>
<li><a href="cconv.html">Calling Convention</a></li>
<li><a href="examples.html">Examples</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="instructions-1"><a class="header" href="#instructions-1">Instructions</a></h1>
<p>This section is a complete overview of the assembly language and instructions. It includes both the hardware instructions that translate directly to machine code as well as pseudo instructions and directives that are translated to hardware instructions or directives by the assembler.</p>
<h3 id="instruction-types"><a class="header" href="#instruction-types">Instruction Types</a></h3>
<ul>
<li><a href="dsa/hardware.html">Hardware Instructions</a></li>
<li><a href="dsa/pseudo.html">Pseudo Instructions</a></li>
<li><a href="dsa/directives.html">Directives</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="hardware-instructions-1"><a class="header" href="#hardware-instructions-1">Hardware Instructions</a></h1>
<h3 id="data-movement-instructions"><a class="header" href="#data-movement-instructions">Data Movement Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>MOV</strong></td><td><code>src_reg, dest_reg</code></td><td>Copy value from source to destination register</td></tr>
<tr><td><strong>MOVS</strong></td><td><code>src_reg, dest_reg</code></td><td>Copy with sign extension</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">mov rg0, rg1 ; Copy rg0 to rg1
movs rg0, rg1 ; Copy rg0 to rg1 with sign extension
</code></pre>
<h3 id="memory-access-instructions"><a class="header" href="#memory-access-instructions">Memory Access Instructions</a></h3>
<h4 id="load-instructions"><a class="header" href="#load-instructions">Load Instructions</a></h4>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>LDB</strong></td><td><code>base_reg, dest_reg [, offset]</code><br><code>label, dest_reg [, offset]</code></td><td>Load byte from memory</td></tr>
<tr><td><strong>LDBS</strong></td><td><code>base_reg, dest_reg [, offset]</code><br><code>label, dest_reg [, offset]</code></td><td>Load byte with sign extension</td></tr>
<tr><td><strong>LDH</strong></td><td><code>base_reg, dest_reg [, offset]</code><br><code>label, dest_reg [, offset]</code></td><td>Load half-word (16-bit)</td></tr>
<tr><td><strong>LDHS</strong></td><td><code>base_reg, dest_reg [, offset]</code><br><code>label, dest_reg [, offset]</code></td><td>Load half-word with sign extension</td></tr>
<tr><td><strong>LDW</strong></td><td><code>base_reg, dest_reg [, offset]</code><br><code>label, dest_reg [, offset]</code></td><td>Load word (32-bit)</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">; Direct register addressing
ldb rg0, rg1 ; Load byte from address in rg0
ldw rg0, rg1, 8 ; Load word from (rg0 + 8)
; Label addressing
ldb buffer, rg2 ; Load byte from label 'buffer'
ldw stack, bpr ; Load stack address into base pointer
</code></pre>
<p><strong>Label Expansions:</strong></p>
<pre><code class="language-dsa">; ldb buffer, rg2 expands to:
lli buffer, rg2 ; Load lower 16 bits of buffer address
lui buffer, rg2 ; Load upper 16 bits of buffer address
ldb rg2, rg2 ; Load byte from address in rg2
; ldw stack, bpr expands to:
lli stack, bpr ; Load lower 16 bits of stack address
lui stack, bpr ; Load upper 16 bits of stack address
ldw bpr, bpr ; Load word from address in bpr
</code></pre>
<h4 id="store-instructions"><a class="header" href="#store-instructions">Store Instructions</a></h4>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>STB</strong></td><td><code>src_reg, base_reg [, offset]</code><br><code>src_reg, label [, offset]</code></td><td>Store byte to memory</td></tr>
<tr><td><strong>STH</strong></td><td><code>src_reg, base_reg [, offset]</code><br><code>src_reg, label [, offset]</code></td><td>Store half-word to memory</td></tr>
<tr><td><strong>STW</strong></td><td><code>src_reg, base_reg [, offset]</code><br><code>src_reg, label [, offset]</code></td><td>Store word to memory</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">; Direct register addressing
stb rg0, rg1 ; Store byte from rg0 to address in rg1
stw rg0, rg1, 12 ; Store word to (rg1 + 12)
; Label addressing
stb acc, buffer ; Store byte from accumulator to 'buffer'
stw rg1, current ; Store word to 'current' variable
</code></pre>
<p><strong>Label Expansions:</strong></p>
<pre><code class="language-dsa">; stb acc, buffer expands to:
lli buffer, rgf ; Load lower 16 bits of buffer address
lui buffer, rgf ; Load upper 16 bits of buffer address
stb acc, rgf ; Store byte from acc to address in rgf
; stw rg1, current expands to:
lli current, rgf ; Load lower 16 bits of current address
lui current, rgf ; Load upper 16 bits of current address
stw rg1, rgf ; Store word from rg1 to address in rgf
</code></pre>
<h3 id="immediate-load-instructions"><a class="header" href="#immediate-load-instructions">Immediate Load Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>LLI</strong></td><td><code>imm, dest_reg</code></td><td>Load 16-bit immediate into lower 16 bits<br/><strong>Clears upper 16 bits!</strong></td></tr>
<tr><td><strong>LUI</strong></td><td><code>imm, dest_reg</code></td><td>Load 16-bit immediate into upper 16 bits</td></tr>
</tbody></table>
</div>
<p><strong>Usage</strong></p>
<p>ensure that you always run <strong>Lli</strong> before <strong>Lui</strong> as <strong>Lli</strong> clears the upper 16 bits.</p>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">lli 0x1234, rg0 ; Load 0x1234 into lower 16 bits of rg0
lui 0xABCD, rg0 ; Load 0xABCD into upper 16 bits of rg0
</code></pre>
<h3 id="jump-instructions"><a class="header" href="#jump-instructions">Jump Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>JMP</strong></td><td><code>addr [, offset_reg]</code><br><code>imm, offset_reg</code></td><td>Unconditional jump</td></tr>
<tr><td><strong>JEQ</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if equal flag set</td></tr>
<tr><td><strong>JNE</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if not equal flag set</td></tr>
<tr><td><strong>JGT</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if greater than flag set</td></tr>
<tr><td><strong>JGE</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if greater or equal flags set</td></tr>
<tr><td><strong>JLT</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if less than flag set</td></tr>
<tr><td><strong>JLE</strong></td><td><code>addr [, offset_reg]</code></td><td>Jump if less or equal flags set</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">jmp start ; Jump to label 'start'
jmp 4, ret ; Jump to address (4 + ret register)
jeq end ; Jump to 'end' if equal flag set
jgt loop ; Jump to 'loop' if greater than flag set
</code></pre>
<h3 id="arithmetic-instructions"><a class="header" href="#arithmetic-instructions">Arithmetic Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>ADD</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Addition</td></tr>
<tr><td><strong>SUB</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Subtraction</td></tr>
<tr><td><strong>IADD</strong></td><td><code>src_reg, imm [, dest_reg]</code></td><td>Immediate addition</td></tr>
<tr><td><strong>ISUB</strong></td><td><code>src_reg, imm [, dest_reg]</code></td><td>Immediate subtraction</td></tr>
<tr><td><strong>INC</strong></td><td><code>reg</code></td><td>Increment register by 1</td></tr>
<tr><td><strong>DEC</strong></td><td><code>reg</code></td><td>Decrement register by 1</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">add rg0, rg1, rg2 ; rg2 = rg0 + rg1
sub rg0, rg1, rg2 ; rg2 = rg0 - rg1
iadd rg0, 10 ; rg0 = rg0 + 10
// or using alternate syntax
addi rg0, 1 ; rg0 = rg0 + 1
inc rg0 ; rg0 = rg0 + 1
</code></pre>
<h3 id="bitwise-operations"><a class="header" href="#bitwise-operations">Bitwise Operations</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>AND</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise AND</td></tr>
<tr><td><strong>OR</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise OR</td></tr>
<tr><td><strong>XOR</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise XOR</td></tr>
<tr><td><strong>NOT</strong></td><td><code>src_reg, dest_reg</code></td><td>Bitwise NOT</td></tr>
<tr><td><strong>NAND</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise NAND</td></tr>
<tr><td><strong>NOR</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise NOR</td></tr>
<tr><td><strong>XNOR</strong></td><td><code>src1_reg, src2_reg, dest_reg</code></td><td>Bitwise XNOR</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">and rg0, rg1, rg2 ; rg2 = rg0 &amp; rg1
not rg0, rg1 ; rg1 = ~rg0
</code></pre>
<h3 id="shift-operations"><a class="header" href="#shift-operations">Shift Operations</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>SHL</strong></td><td><code>reg, shift_amount</code></td><td>Shift left</td></tr>
<tr><td><strong>SHR</strong></td><td><code>reg, shift_amount</code></td><td>Shift right</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">shl rg0, 2 ; Shift rg0 left by 2 bits
shr rg0, 3 ; Shift rg0 right by 3 bits
</code></pre>
<h3 id="comparison-and-control"><a class="header" href="#comparison-and-control">Comparison and Control</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>CMP</strong></td><td><code>reg1, reg2</code></td><td>Compare registers and set flags</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">cmp rg0, zero ; Compare rg0 with zero register
cmp rg1, rg2 ; Compare rg1 with rg2
</code></pre>
<h3 id="system-instructions"><a class="header" href="#system-instructions">System Instructions</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>HLT</strong></td><td>-</td><td>Halt processor execution</td></tr>
<tr><td><strong>NOP</strong></td><td>-</td><td>No operation</td></tr>
<tr><td><strong>INT</strong></td><td><code>interrupt_code</code></td><td>Trigger interrupt</td></tr>
<tr><td><strong>IRT</strong></td><td>-</td><td>Return from interrupt</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">hlt ; Stop processor execution
int 0x21 ; Trigger interrupt 0x21
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="pseudo-instructions"><a class="header" href="#pseudo-instructions">Pseudo Instructions</a></h1>
<h3 id="stack-operations"><a class="header" href="#stack-operations">Stack Operations</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>PUSH</strong></td><td><code>reg</code></td><td>Push register value onto stack</td></tr>
<tr><td><strong>POP</strong></td><td><code>reg</code></td><td>Pop stack value into register</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">push rg0 ; Push rg0 value onto stack
pop ret ; Pop return address
</code></pre>
<h3 id="memory-access-shortcuts"><a class="header" href="#memory-access-shortcuts">Memory Access Shortcuts</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>LWI</strong></td><td><code>name, reg</code></td><td>Load address into register</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">lwi string, rg1 ; Load address of 'string' into rg1
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="data-directives"><a class="header" href="#data-directives">Data Directives</a></h1>
<h3 id="data-definition"><a class="header" href="#data-definition">Data Definition</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Syntax</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>DB</strong></td><td><code>name: value1 [, value2, ...]</code></td><td>Define bytes</br><em>(byte aligned)</em></td></tr>
<tr><td><strong>DH</strong></td><td><code>name: value1 [, value2, ...]</code></td><td>Define half-words</br><em>(2 byte aligned)</em></td></tr>
<tr><td><strong>DW</strong></td><td><code>name: value1 [, value2, ...]</code></td><td>Define words</br><em>(4 byte aligned)</em></td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">db message: "Hello World", 0, 0x20, 231
dh numbers: 1000, 2000, 3000
dw stack: 0x10000
</code></pre>
<p><strong>Notes:</strong></p>
<ul>
<li>All string literals are automatically <em>null-terminated</em></li>
<li></li>
</ul>
<h3 id="memory-reservation"><a class="header" href="#memory-reservation">Memory Reservation</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Syntax</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>RESB</strong></td><td><code>name: size</code></td><td>Reserve bytes</td></tr>
<tr><td><strong>RESH</strong></td><td><code>name: size</code></td><td>Reserve half-words</td></tr>
<tr><td><strong>RESW</strong></td><td><code>name: size</code></td><td>Reserve words</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">resb buffer: 256 ; Reserve 256 bytes
resh array: 100 ; Reserve space for 100 half-words
resw heap: 1024 ; Reserve space for 1024 words
</code></pre>
<h3 id="imports"><a class="header" href="#imports">Imports</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Syntax</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>INCLUDE</strong></td><td><code>module_name "path"</code></td><td>Include module symbols</td></tr>
<tr><td><a href="dsa/instructions/../imports.html">More details on the module System</a></td><td></td><td></td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="usable-registers"><a class="header" href="#usable-registers">Usable Registers</a></h1>
<div class="table-wrapper"><table><thead><tr><th>Register</th><th>Type</th><th>Description</th></tr></thead><tbody>
<tr><td><code>rg0-rgf</code></td><td>General Purpose</td><td>General-purpose registers.</td></tr>
<tr><td><code>acc</code></td><td>Special</td><td>Accumulator for calculations and temporary storage - don't use this for variables as pseudo instructions may overwrite this implicitly!</td></tr>
<tr><td><code>spr</code></td><td>Special</td><td>Stack pointer</td></tr>
<tr><td><code>bpr</code></td><td>Special</td><td>Base pointer for stack frames</td></tr>
<tr><td><code>ret</code></td><td>Special</td><td>Return address register</td></tr>
<tr><td><code>idr</code></td><td>Privileged</td><td>Interrupt descriptor table address<br/><strong>on-read/write: protection fault (unless in kernel mode)</strong></td></tr>
<tr><td><code>mmr</code></td><td>Privileged</td><td>Hardware memory map table address<br/><strong>on-read/write: protection fault (unless in kernel mode)</strong></td></tr>
<tr><td><code>zero</code></td><td>Read-only</td><td>Always contains zero<br/><strong>on-read: always returns zero</strong><br/><strong>on-write: value is voided</strong></td></tr>
<tr><td><code>pcx</code></td><td>Read-only</td><td>Program counter<br/><strong>on-write: protection fault</strong></td></tr>
<tr><td><code>noreg</code></td><td>Placeholder</td><td>Indicates absence of register argument<br/><strong>on-read/write: illegal instruction fault</strong></td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="imports-1"><a class="header" href="#imports-1">Imports</a></h1>
<h2 id="module-system"><a class="header" href="#module-system">Module System</a></h2>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Syntax</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>INCLUDE</strong></td><td><code>alias[:] "path"</code></td><td>Include module symbols</td></tr>
</tbody></table>
</div>
<h2 id="import-precedence"><a class="header" href="#import-precedence">Import Precedence</a></h2>
<p><strong>Notes:</strong></p>
<ul>
<li>The order of imports may affect the order in which dependencies are placed into the output binary.</li>
<li>Circular dependencies are allowed and fully supported.</li>
<li>The module name is caller-defined and can be used to create aliases for libraries within the scope of the calling file. This makes namespacing easy.</li>
</ul>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">include print "./lib/print.dsa"
include maths "./lib/maths.dsa"
</code></pre>
<h2 id="external-symbol-access-convention"><a class="header" href="#external-symbol-access-convention">External Symbol Access Convention</a></h2>
<p>External symbols are accessed using the <code>::</code> operator.</p>
<p><strong>Examples:</strong></p>
<pre><code class="language-dsa">include print "./lib/print.dsa"
init:
// ensure we have a stack setup so we can call functions properly
db string: "Hello world!"
start:
// load the address of the string into rg1.
lwi string, rg1
// push the string address argument
push rg1
// call the print function
call print::print
// clean up the stack
pop zero
hlt
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="calling-convention"><a class="header" href="#calling-convention">Calling Convention</a></h1>
<h2 id="calling-convention-1"><a class="header" href="#calling-convention-1">Calling Convention</a></h2>
<div class="table-wrapper"><table><thead><tr><th>Step</th><th>Responsibility</th><th>Action</th><th>Description</th></tr></thead><tbody>
<tr><td>0</td><td><strong>Caller</strong></td><td>Save Current State</td><td>Ensure that any registers with important data in are pushed to the stack so that they can be restored later.</td></tr>
<tr><td>1</td><td><strong>Caller</strong></td><td>Push arguments</td><td>Push exactly n arguments to the stack </br>(in order, last argument pushed first)</td></tr>
<tr><td>2</td><td><strong>Caller</strong></td><td>Call function</td><td>Execute <code>call namespace::function</code></br>this automatically pushes the return address (pcx) and jumps to the function</td></tr>
<tr><td>3</td><td><strong>Function</strong></td><td>Set up stack frame</td><td>Execute <code>push bpr; mov spr, bpr</code> to establish new stack frame</td></tr>
<tr><td>4</td><td><strong>Function</strong></td><td>Access arguments</td><td>Read arguments starting at <code>spr+8</code> </br>(first 3 args at offsets 8, 12, 16)</td></tr>
<tr><td>5</td><td><strong>Function</strong></td><td>Execute function</td><td>Perform the function's operations using the arguments</td></tr>
<tr><td>6</td><td><strong>Function</strong></td><td>Store return value</td><td>Write return value (if any) to <code>spr+8</code></td></tr>
<tr><td>7</td><td><strong>Function</strong></td><td>Restore stack frame</td><td>Execute <code>mov bpr, spr; pop bpr</code> to restore previous stack frame</td></tr>
<tr><td>8</td><td><strong>Function</strong></td><td>Return</td><td>Execute <code>return</code> pseudo-instruction to return to caller</td></tr>
<tr><td>9</td><td><strong>Caller</strong></td><td>Clean up stack</td><td>Pop exactly n arguments from the stack to clean up</td></tr>
<tr><td>10</td><td><strong>Caller</strong></td><td>Handle unused values</td><td>Use <code>pop zero</code> to discard any unused stack values if needed</td></tr>
<tr><td>11</td><td><strong>Caller</strong></td><td>Restore State</td><td>Pop any registers that were pushed in step 0 </br>(or <code>pop zero</code> if no longer needed)</td></tr>
</tbody></table>
</div>
<p><strong>Notes:</strong></p>
<ul>
<li>The namespace in step 2 is the name assigned in the <code>include</code> statement</li>
<li>The <code>call</code> pseudo-instruction automatically handles return address management so long as the callee does not mess with the stack</li>
<li>Arguments are accessed by the callee using offsets from the base pointer (bpr)</li>
</ul>
<h3 id="function-control"><a class="header" href="#function-control">Function Control</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Mnemonic</th><th>Operands</th><th>Description</th></tr></thead><tbody>
<tr><td><strong>CALL</strong></td><td><code>namespace::function</code></td><td>Call a function with automatic return address management</td></tr>
<tr><td><strong>RETURN</strong></td><td>-</td><td>Return from a function to the caller</td></tr>
</tbody></table>
</div>
<p><strong>Examples:</strong></p>
<p><code>call-local.dsa</code></p>
<pre><code class="language-dsa">// ensure the stack is set up first!
caller:
push rg0
push rg1
call callee // make call to a local function
pop rg0 // put result in rg0
pop zero // void second return val
callee:
// setup new stack frame
push bpr
mov spr, bpr
// function body
// restore the stack frame
mov bpr, spr
pop bpr
return ; Return from the current function
</code></pre>
<p><code>call-external.dsa</code></p>
<pre><code class="language-dsa">include external "./external.dsa"
// ensure the stack is set up first!
db string: "Hello, world!"
caller:
// push args
lwi string, rg0
push rg0
call external::callee // do something with the string
pop zero
</code></pre>
<p><code>external.dsa</code></p>
<pre><code class="language-dsa">callee:
// set up the stack
push bpr
mov spr, bpr
// function body
// restore the stack frame
mov bpr, spr
pop bpr
return ; Return from the current function
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="examples"><a class="header" href="#examples">Examples</a></h1>
<h2 id="library-examples"><a class="header" href="#library-examples">Library Examples</a></h2>
<h3 id="multiplication-library-multiplydsa"><a class="header" href="#multiplication-library-multiplydsa">Multiplication Library (multiply.dsa)</a></h3>
<pre><code class="language-dsa">// multiply.dsa
// usage:
//
// include multiply "&lt;relative path&gt;"
//
// usage for multiply:
// push (arg1)
// push (arg0)
// call multiply::multiply
// pop (arg0)
// pop (arg1)
multiply:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load op 1
ldw bpr, rg1, 12 // load op 2
lli 0, acc // initialize accumulator
start:
add acc, rg0, acc
dec rg1
cmp rg1, zero
jgt start
end:
stw acc, bpr, 8 // store result for caller
mov bpr, spr
pop bpr
return
</code></pre>
<h3 id="print-library-printdsa"><a class="header" href="#print-library-printdsa">Print Library (print.dsa)</a></h3>
<pre><code class="language-dsa">// print.dsa
// usage:
//
// include print "&lt;relative path&gt;"
//
// usage for print:
// push (register containing address of string)
// call print::print
// pop zero
//
// usage for reset:
// call print::reset
dw display: 0x20000
dw current: 0x20000
// prints the given text to the screen.
print:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // get string address argument
ldw current, rg1 // get current display position
print_loop:
ldb rg0, acc
stb acc, rg1
iadd rg0, 1
iadd rg1, 1
cmp acc, zero
jne print_loop
jmp end
// return
end:
stw rg1, current
mov bpr, spr
pop bpr
return
// resets the cursor position on the screen
reset:
push bpr
mov spr, bpr
ldw display, rg1
stw rg1, current
mov bpr, spr
pop bpr
return
</code></pre>
<h3 id="example-program-maindsa"><a class="header" href="#example-program-maindsa">Example Program (main.dsa)</a></h3>
<pre><code class="language-dsa">include print "./print.dsa"
dw stack: 0x10000
db string: "'To confuse your enemy, you must first confuse yourself' - Probably Sun Tzu."
init:
// set up a stack.
ldw stack, bpr
mov bpr, spr
start:
lwi string, rg1
// push string address argument
push rg1
// call print function
call print::print
// clean up stack
pop rg1
hlt
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="tooling"><a class="header" href="#tooling">Tooling</a></h1>
<h2 id="tooling-options"><a class="header" href="#tooling-options">Tooling Options</a></h2>
<h3 id="assembler"><a class="header" href="#assembler">Assembler</a></h3>
<ul>
<li>The assembler is the program that translates assembly code into machine code.</li>
<li>It is the only tool required to build DSA assembly language programs.</li>
<li>The assembler also works as a library that can be called from applications such as the emulator</li>
</ul>
<h3 id="our-tooling"><a class="header" href="#our-tooling">Our Tooling:</a></h3>
<ul>
<li><a href="dsa/assembler.html">Assembler</a></li>
<li><a href="dsa/syntax_tooling.html">Syntax Tooling</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="assembler-1"><a class="header" href="#assembler-1">Assembler</a></h1>
<h2 id="building-the-assembler"><a class="header" href="#building-the-assembler">Building the Assembler</a></h2>
<h3 id="clone-the-repository"><a class="header" href="#clone-the-repository">Clone the repository</a></h3>
<pre><code class="language-bash">git clone https://git.zxq5.dev/LowLevelDevs/damn_simple_architecture.git
cd damn_simple_architecture
</code></pre>
<h3 id="build-the-assembler"><a class="header" href="#build-the-assembler">Build the assembler</a></h3>
<pre><code class="language-bash">cd assembler
cargo build --release
</code></pre>
<h2 id="usage"><a class="header" href="#usage">Usage</a></h2>
<pre><code class="language-bash">&lt;binary&gt; -i &lt;input_file.dsa&gt; -o &lt;output_file.dsb&gt;
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="syntax-tooling"><a class="header" href="#syntax-tooling">Syntax tooling</a></h1>
<h2 id="syntax-highlighting"><a class="header" href="#syntax-highlighting">Syntax Highlighting</a></h2>
<h3 id="emulator"><a class="header" href="#emulator">Emulator</a></h3>
<ul>
<li>our custom Emulator has built-in syntax highlighting for the DSA assembly language. all files with the .dsa extension have the syntax applies</li>
</ul>
<h3 id="vscode"><a class="header" href="#vscode">VSCode</a></h3>
<ul>
<li>install our custom VSCode extension from the marketplace
<a href="https://marketplace.visualstudio.com/items?itemName=dsa-tooling.dsa-language-support">dsa-tooling.dsa-language-support</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="dsa-emulator"><a class="header" href="#dsa-emulator">DSA Emulator</a></h1>
<h1 id="dsa-emulator-1"><a class="header" href="#dsa-emulator-1">DSA Emulator</a></h1>
<p>The DSA Emulator is a visual emulator that allows you to debug and test your programs in a controlled environment. It is composed of a control panel, memory inspector, and a built in editor.</p>
<p>The control panel lets you view all of the registers, step through the instructions, and view the current instruction counter.</p>
<p>The memory inspector lets you view any region of memory in the emulator.</p>
<p>The editor contains a built in assembler instance, so you can edit and assemble your code from the comfort of the emulator.</p>
<p>The loader is responsible for loading your code into memory so that the emulator can run it.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="building-the-emulator"><a class="header" href="#building-the-emulator">Building the Emulator</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="features"><a class="header" href="#features">Features</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="control-panel"><a class="header" href="#control-panel">Control Panel</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="memory-inspector"><a class="header" href="#memory-inspector">Memory Inspector</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="stack-inspector"><a class="header" href="#stack-inspector">Stack Inspector</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="editor"><a class="header" href="#editor">Editor</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="loader"><a class="header" href="#loader">Loader</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="display"><a class="header" href="#display">Display</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="instruction-history"><a class="header" href="#instruction-history">Instruction History</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="dsc---damn-simple-code"><a class="header" href="#dsc---damn-simple-code">DSC - Damn Simple Code</a></h1>
<h1 id="this-document-is-a-work-in-progress"><a class="header" href="#this-document-is-a-work-in-progress">This document is a work in progress!</a></h1>
<h1 id="nothing-is-final"><a class="header" href="#nothing-is-final">Nothing is final!</a></h1>
<h2 id="syntax"><a class="header" href="#syntax">Syntax</a></h2>
<ul>
<li>we aim to make the syntax simple and easy to understand, this has the following benefits
<ul>
<li>easy to write</li>
<li>easy to parse</li>
<li>little variation in syntax means we have to handle less cases in semantic analysis, meaning we will be able to create a working compiler quicker.</li>
</ul>
</li>
</ul>
<h2 id="types"><a class="header" href="#types">Types</a></h2>
<ul>
<li>we should support the following types
<ul>
<li>unsigned integer types (U8, U16, U32)</li>
<li>signed integer types (I8, I16, I32)</li>
<li>boolean type (Bool)</li>
<li>struct types (Struct)</li>
<li>dynamic types *(Dyn)</li>
<li></li>
</ul>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="functions"><a class="header" href="#functions">Functions</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="other-language-support"><a class="header" href="#other-language-support">Other Language Support</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="brainf"><a class="header" href="#brainf">Brainf*</a></h1>
<h2 id="language-overview"><a class="header" href="#language-overview">Language overview</a></h2>
<ul>
<li>Brainf* instructions are as follows:</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th>Instruction</th><th>Description</th></tr></thead><tbody>
<tr><td><code>+</code></td><td>Increment the current memory cell</td></tr>
<tr><td><code>-</code></td><td>Decrement the current memory cell</td></tr>
<tr><td><code>&lt;</code></td><td>Move the data pointer to the left</td></tr>
<tr><td><code>&gt;</code></td><td>Move the data pointer to the right</td></tr>
<tr><td><code>.</code></td><td>Output the value of the current memory cell as a character</td></tr>
<tr><td><code>,</code></td><td>Input a character and store its value in the current memory cell</td></tr>
<tr><td><code>[</code></td><td>Jump to the instruction after the matching <code>]</code> if the value in the current memory cell is zero</td></tr>
<tr><td><code>]</code></td><td>Jump to the instruction after the matching <code>[</code> if the value in the current memory cell is non-zero</td></tr>
</tbody></table>
</div>
<h2 id="implementations"><a class="header" href="#implementations">Implementations</a></h2>
<p>we currently have two implementations of the brainf* esoteric programming language:</p>
<h3 id="compiler"><a class="header" href="#compiler">Compiler</a></h3>
<ul>
<li>this is the most efficient way to run brainf* programs on the DSA architecture, but of course, still terribly inefficient due to the nature of the language.</li>
<li>compiling allows us to calculate the jump addresses at compile time, therefore making each brainf* instruction take at maximum three DSA instructions to execute</li>
</ul>
<h3 id="interpreter"><a class="header" href="#interpreter">Interpreter</a></h3>
<ul>
<li>this method is much slower, with even jumping to the start of a loop having an O(n) time complexity, which depending on the complexity of the program can up to double the running time.</li>
<li>additionally, interpreting the language means much more logic is required at runtime relative to compiling.</li>
<li>from our testing on a few example programs such as a fibonacci sequence generator, the interpreter is several orders of magnitude slower, with the fibonacci generator beingabout 10 times slower than it's compiled equivalent, at around 3.8 million instructions to generate and pretty-print the first 16 fibonacci numbers, compared to around 350,000 for the compiled version, which we estimate is about as efficient as brainf* can be on our architecture without writing an optimiser.</li>
</ul>
<h2 id="usage-1"><a class="header" href="#usage-1">Usage</a></h2>
<h3 id="compiling"><a class="header" href="#compiling">Compiling</a></h3>
<ul>
<li>currently <a href="misc_languages/../dsa/tooling/assembler.html">The DSA Assembler</a> supports compiling brainf* programs, with the following command:</li>
</ul>
<pre><code class="language-bash">&lt;assembler binary name&gt; -brainf
</code></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</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 -->
<script>
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</div>
</body>
</html>