<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>Enter the void *</title>
        <link>http://blog.emillon.org</link>
        <description><![CDATA[Yet another random hacker]]></description>
        <atom:link href="http://blog.emillon.org/feeds/lenses.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Thu, 20 Aug 2015 00:00:00 UT</lastBuildDate>
        <item>
    <title>A lens-based ST20 emulator</title>
    <link>http://blog.emillon.org/posts/2015-08-20-a-lens-based-st20-emulator.html</link>
    <description><![CDATA[<p>Every year, as part of the <a href="https://www.sstic.org/">SSTIC conference</a>, there is
a forensics/reverse engineering challenge. I participated in the 2015 edition.
Though I did not manage to complete it, I made an emulator for the exotic ST20
architecture, which is probably worth describing here.</p>
<figure>
<img src="/img/st20/t00f.png" alt="Some programs will loop. It’s OK." />
<figcaption aria-hidden="true">Some programs will loop. It’s OK.</figcaption>
</figure>
<p>Note that this emulator is not really optimized for pure speed. In the actual
challenge I actually had to rewrite it as pure Haskell (i.e., removing the
emulation part) so that it was faster. Instead, the goal of this article is to
show a few techniques to write powerful emulators in Haskell.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE Rank2Types #-}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TemplateHaskell #-}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Applicative</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Concurrent</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.RWS</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens</span> <span class="kw">hiding</span> (imap, op)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Bits</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Int</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Maybe</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Word</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Numeric</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Exit</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.IO</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Printf</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">BS</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">M</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Set</span> <span class="kw">as</span> <span class="dt">S</span></span></code></pre></div>
<h2 id="the-evaluation-monad">The evaluation monad</h2>
<p>This program uses Template Haskell to define lenses, so unfortunately we need to
start with a few type definitions.</p>
<p>The ST20’s memory goes from <code>0x80000000</code> to <code>0x7fffffff</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Address</span> <span class="ot">=</span> <span class="dt">Int32</span></span></code></pre></div>
<p>We’ll represent the memory using a map. The performance is surprisingly close to
that of an array. It is possible to get significantly speeds up memory access by
using an <code>IOUArray</code> but it turns loads and stores become monadic operations and
makes it impossible to use lenses.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Mem</span> <span class="ot">=</span> <span class="dt">M.Map</span> <span class="dt">Address</span> <span class="dt">Word8</span></span></code></pre></div>
<p>As we’ll see, <em>transputers</em> (hardware threads) can communicate together. We’ll
be able to connect it either between them, or to a tty.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">IChannel</span> <span class="ot">=</span> <span class="dt">InChan</span> (<span class="dt">Chan</span> <span class="dt">Word8</span>)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>              <span class="op">|</span> <span class="dt">InHandle</span> <span class="dt">Handle</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">OChannel</span> <span class="ot">=</span> <span class="dt">OutChan</span> (<span class="dt">Chan</span> <span class="dt">Word8</span>)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>              <span class="op">|</span> <span class="dt">OutHandle</span> <span class="dt">Handle</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">IChannelMap</span> <span class="ot">=</span> [(<span class="dt">Int32</span>, <span class="dt">IChannel</span>)]</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">OChannelMap</span> <span class="ot">=</span> [(<span class="dt">Int32</span>, <span class="dt">OChannel</span>)]</span></code></pre></div>
<p>All evaluations take place in a <code>Eval</code> Monad which is a monad transformer stack
with the following capabilities:</p>
<ul>
<li>read and write an <code>EvalState</code> value;</li>
<li>read an <code>EvalEnv</code> value</li>
<li>do some I/O.</li>
</ul>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Eval</span> a <span class="ot">=</span> <span class="dt">Eval</span> (<span class="dt">RWST</span> <span class="dt">EvalEnv</span> () <span class="dt">EvalState</span> <span class="dt">IO</span> a)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> ( <span class="dt">Functor</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>             , <span class="dt">Monad</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>             , <span class="dt">MonadIO</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>             , <span class="dt">MonadReader</span> <span class="dt">EvalEnv</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>             , <span class="dt">MonadState</span> <span class="dt">EvalState</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>             )</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">EvalEnv</span> <span class="ot">=</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">EvalEnv</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>        {<span class="ot"> envInChans ::</span> <span class="dt">IChannelMap</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        ,<span class="ot"> envOutChans ::</span> <span class="dt">OChannelMap</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        }</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">EvalState</span> <span class="ot">=</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">EvalState</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        {<span class="ot"> _iptr ::</span> <span class="op">!</span><span class="dt">Address</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        ,<span class="ot"> _intStack ::</span> [<span class="dt">Int32</span>]</span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>        ,<span class="ot"> _wptr ::</span> <span class="op">!</span><span class="dt">Int32</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>        ,<span class="ot"> _mem ::</span> <span class="op">!</span><span class="dt">Mem</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>        }</span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(makeLenses &#39;<span class="dt">&#39;EvalState</span>)</span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a><span class="ot">runEval ::</span> <span class="dt">Mem</span> <span class="ot">-&gt;</span> <span class="dt">IChannelMap</span> <span class="ot">-&gt;</span> <span class="dt">OChannelMap</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> a</span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>runEval memory imap omap (<span class="dt">Eval</span> m) <span class="ot">=</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fst</span> <span class="op">&lt;$&gt;</span> evalRWST m env st</span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>            env <span class="ot">=</span> <span class="dt">EvalEnv</span> imap omap</span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>            st <span class="ot">=</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a>                 <span class="dt">EvalState</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>                     { _iptr <span class="ot">=</span> memStart</span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a>                     , _intStack <span class="ot">=</span> []</span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a>                     , _wptr <span class="ot">=</span> <span class="bn">0xaaaaaaaa</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>                     , _mem <span class="ot">=</span> memory</span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a>                     }</span></code></pre></div>
<p>The above <code>$(...)</code> is a Template Haskell splice. It creates <em>lenses</em> based on
the record declaration of <code>EvalState</code>. Lenses are a very powerful tool that
makes it possible to compose record reads and updates in a functional way. Here,
it defines a lens for each record field; for example, the splice expands to a
top-level declaration <code>iptr :: Lens' EvalState Address</code>. But we will define our
own lenses too, and everything will remain composable.</p>
<h2 id="memory">Memory</h2>
<p>This is naturally adapted to byte access:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">memByteOpt ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> (<span class="dt">Maybe</span> <span class="dt">Word8</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>memByteOpt addr <span class="ot">=</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  mem <span class="op">.</span> at addr</span></code></pre></div>
<p>See? We composed the <code>mem</code> lens (between an evaluation state and a memory state) with <code>at addr</code>, which is a lens between a memory state and the value at address <code>addr</code>.
Well, not exactly: <code>at</code> actually returns a <code>Maybe Word8</code>. We will assume that
all memory accesses will succeed, so we want a lens that returns a plain
<code>Word8</code>. To achieve this, we can compose with a lens that treats <code>Maybe a</code> as a
container of <code>a</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">maybeLens ::</span> <span class="dt">Lens&#39;</span> (<span class="dt">Maybe</span> a) a</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>maybeLens <span class="ot">=</span> lens fromJust (<span class="fu">const</span> <span class="dt">Just</span>)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ot">memByte ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Word8</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>memByte addr <span class="ot">=</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  memByteOpt addr <span class="op">.</span> maybeLens</span></code></pre></div>
<p>Sometimes we will also need to access memory word by word. To achieve that, we
first define conversion functions.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">bytesToWord ::</span> (<span class="dt">Word8</span>, <span class="dt">Word8</span>, <span class="dt">Word8</span>, <span class="dt">Word8</span>) <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>bytesToWord (b0, b1, b2, b3) <span class="ot">=</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="fu">sum</span> [ <span class="fu">fromIntegral</span> b0</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>        , <span class="fu">fromIntegral</span> b1 <span class="ot">`shiftL`</span> <span class="dv">8</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>        , <span class="fu">fromIntegral</span> b2 <span class="ot">`shiftL`</span> <span class="dv">16</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        , <span class="fu">fromIntegral</span> b3 <span class="ot">`shiftL`</span> <span class="dv">24</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>        ]</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="ot">wordToBytes ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> (<span class="dt">Word8</span>, <span class="dt">Word8</span>, <span class="dt">Word8</span>, <span class="dt">Word8</span>)</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>wordToBytes w <span class="ot">=</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    (b0, b1, b2, b3)</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>            b0 <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> w <span class="op">.&amp;.</span> <span class="bn">0x000000ff</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>            b1 <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> (w <span class="op">.&amp;.</span> <span class="bn">0x0000ff00</span>) <span class="ot">`shiftR`</span> <span class="dv">8</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>            b2 <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> (w <span class="op">.&amp;.</span> <span class="bn">0x00ff0000</span>) <span class="ot">`shiftR`</span> <span class="dv">16</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>            b3 <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> (w <span class="op">.&amp;.</span> <span class="bn">0xff000000</span>) <span class="ot">`shiftR`</span> <span class="dv">24</span></span></code></pre></div>
<p>Then, we can define a lens focusing on a 32-bit value.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">compose ::</span> [a <span class="ot">-&gt;</span> a] <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>compose <span class="ot">=</span> <span class="fu">foldr</span> (<span class="op">.</span>) <span class="fu">id</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ot">get32 ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">EvalState</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>get32 base s <span class="ot">=</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    bytesToWord (b0, b1, b2, b3)</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>            b0 <span class="ot">=</span> s <span class="op">^.</span> memByte base</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>            b1 <span class="ot">=</span> s <span class="op">^.</span> memByte (base <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>            b2 <span class="ot">=</span> s <span class="op">^.</span> memByte (base <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>            b3 <span class="ot">=</span> s <span class="op">^.</span> memByte (base <span class="op">+</span> <span class="dv">3</span>)</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="ot">set32 ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">EvalState</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">EvalState</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>set32 base s v <span class="ot">=</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>   compose</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>       [ set (memByte base) b0</span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>       , set (memByte (base <span class="op">+</span> <span class="dv">1</span>)) b1</span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>       , set (memByte (base <span class="op">+</span> <span class="dv">2</span>)) b2</span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>       , set (memByte (base <span class="op">+</span> <span class="dv">3</span>)) b3</span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>       ] s</span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>            (b0, b1, b2, b3) <span class="ot">=</span> wordToBytes v</span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a><span class="ot">memWord ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Int32</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>memWord addr <span class="ot">=</span> lens (get32 addr) (set32 addr)</span></code></pre></div>
<p>The instruction set reference defines a handy operator to shift an address by a
word offset:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(@@) ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Address</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>a <span class="op">@@</span> n <span class="ot">=</span> a <span class="op">+</span> <span class="dv">4</span> <span class="op">*</span> n</span></code></pre></div>
<p>It will be also handy to access the memory in list chunks:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mem8s ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> [<span class="dt">Word8</span>]</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>mem8s base len <span class="ot">=</span> lens getList setList</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        getList s <span class="ot">=</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>            <span class="fu">map</span> (\ off <span class="ot">-&gt;</span> s <span class="op">^.</span> memByte (base <span class="op">+</span> off)) [<span class="dv">0</span> <span class="op">..</span> len <span class="op">-</span> <span class="dv">1</span>]</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        setList s0 ws <span class="ot">=</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>            compose (<span class="fu">zipWith</span> (\ off w <span class="ot">-&gt;</span> set (memByte (base <span class="op">+</span> off)) w) [<span class="dv">0</span><span class="op">..</span>] ws) s0</span></code></pre></div>
<h2 id="instruction-decoding">Instruction decoding</h2>
<p>Instructions are usually encoded on a single byte: the opcode is in the first
nibble, and a parameter is in the second one. For example this is how a LDC
(load constant) is encoded:</p>
<pre><code>   .--- 0x40 LDC
  |.---          0x5
  ||
0x45         LDC 0x5</code></pre>
<p>This only works for 4-bytes constants. To load bigger constants, there is a
“prefix” operation that will shift the current operand:</p>
<pre><code>   .-------- 0x20 PFX
  |.--------          0x2
  ||
  ||    .--- 0x40 LDC
  ||   |.---          0x5
  ||   ||
0x22 0x45    LDC 0x25</code></pre>
<p>Those are chainable; for example <code>0x21 0x22 0x45</code> encodes <code>LDC 0x125</code>.</p>
<p>Another prefix shifts and complements the current operand value:</p>
<pre><code>   .-------- 0x60 NFX
  |.--------          0x2
  ||
  ||    .--- 0x40 LDC
  ||   |.---          0x5
  ||   ||
0x62 0x45    LDC (~0x25)</code></pre>
<p>The ST20 architecture actually provides two type of instructions:</p>
<ul>
<li>“primary” instructions such as <code>LDC</code>. Their operand is directly encoded.</li>
<li>“secondary” instructions such as <code>MINT</code> (equivalent to <code>LDC 0x80000000</code>).
They do not have operands. On the contrary, they are actually a special case
of the first type, using a special <code>OPR n</code> opcode. For example, <code>MINT</code> is
<code>OPR 0x42</code>, which is encoded using <code>0x24 0xF2</code>.</li>
</ul>
<p>We know enough to draft an instruction decoder.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">PInstr</span> <span class="ot">=</span> <span class="dt">AJW</span>   <span class="op">|</span> <span class="dt">ADC</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">LDC</span>   <span class="op">|</span> <span class="dt">STL</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">LDL</span>   <span class="op">|</span> <span class="dt">LDNL</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">LDLP</span>  <span class="op">|</span> <span class="dt">LDNLP</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">CJ</span>    <span class="op">|</span> <span class="dt">J</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">EQC</span>   <span class="op">|</span> <span class="dt">CALL</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">STNL</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Show</span>)</span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">SInstr</span> <span class="ot">=</span> <span class="dt">PROD</span>  <span class="op">|</span> <span class="dt">MINT</span>   <span class="op">|</span> <span class="dt">GAJW</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">LDPI</span>  <span class="op">|</span> <span class="dt">OUT</span>    <span class="op">|</span> <span class="dt">IN</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">LB</span>    <span class="op">|</span> <span class="dt">XOR</span>    <span class="op">|</span> <span class="dt">SB</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">BSUB</span>  <span class="op">|</span> <span class="dt">SSUB</span>   <span class="op">|</span> <span class="dt">DUP</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">GTx</span>   <span class="op">|</span> <span class="dt">WSUB</span>   <span class="op">|</span> <span class="dt">AND</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">RET</span>   <span class="op">|</span> <span class="dt">GCALL</span>  <span class="op">|</span> <span class="dt">SHR</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> <span class="dt">SHL</span>   <span class="op">|</span> <span class="dt">REM</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Show</span>)</span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Instr</span> <span class="ot">=</span> <span class="dt">Pri</span> <span class="dt">PInstr</span> <span class="dt">Int32</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>           <span class="op">|</span> <span class="dt">Sec</span> <span class="dt">SInstr</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>)</span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Show</span> <span class="dt">Instr</span> <span class="kw">where</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>    <span class="fu">show</span> (<span class="dt">Pri</span> p n) <span class="ot">=</span> <span class="fu">show</span> p <span class="op">++</span> <span class="st">&quot; &quot;</span> <span class="op">++</span> <span class="fu">show</span> n</span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>    <span class="fu">show</span> (<span class="dt">Sec</span> s) <span class="ot">=</span> <span class="fu">show</span> s</span></code></pre></div>
<p>Instruction decoding will need to move within the instruction stream, so it is
part of the evaluation monad.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">decodeInstr ::</span> <span class="dt">Eval</span> <span class="dt">Instr</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>decodeInstr <span class="ot">=</span> decodeInstr_ <span class="dv">0</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="ot">decodeInstr_ ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> <span class="dt">Instr</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>decodeInstr_ acc <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> peekAndIncr</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> acc&#39; <span class="ot">=</span> acc <span class="op">+</span> <span class="fu">fromIntegral</span> (b <span class="op">.&amp;.</span> <span class="bn">0xf</span>)</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> () <span class="kw">of</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x0f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">J</span> acc&#39;</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x1f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">LDLP</span> acc&#39;</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x2f</span> <span class="ot">-&gt;</span> decodeInstr_ <span class="op">$</span> acc&#39; <span class="ot">`shiftL`</span> <span class="dv">4</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x3f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">LDNL</span> acc&#39;</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x4f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">LDC</span> acc&#39;</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x5f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">LDNLP</span> acc&#39;</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x6f</span> <span class="ot">-&gt;</span> decodeInstr_ <span class="op">$</span> complement acc&#39; <span class="ot">`shiftL`</span> <span class="dv">4</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x7f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">LDL</span> acc&#39;</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x8f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">ADC</span> acc&#39;</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0x9f</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">CALL</span> acc&#39;</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0xaf</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">CJ</span> acc&#39;</span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0xbf</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">AJW</span> acc&#39;</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0xcf</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">EQC</span> acc&#39;</span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0xdf</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">STL</span> acc&#39;</span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">|</span> b <span class="op">&lt;=</span> <span class="bn">0xef</span> <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Pri</span> <span class="dt">STNL</span> acc&#39;</span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>        _             <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">$</span> <span class="dt">Sec</span> <span class="op">$</span> parseSecondary acc&#39;</span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a><span class="ot">peekAndIncr ::</span> <span class="dt">Eval</span> <span class="dt">Word8</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>peekAndIncr <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>    addr <span class="ot">&lt;-</span> use iptr</span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> use (memByte addr)</span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> b</span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a><span class="ot">parseSecondary ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">SInstr</span></span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x01</span> <span class="ot">=</span> <span class="dt">LB</span></span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x02</span> <span class="ot">=</span> <span class="dt">BSUB</span></span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x06</span> <span class="ot">=</span> <span class="dt">GCALL</span></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x07</span> <span class="ot">=</span> <span class="dt">IN</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x08</span> <span class="ot">=</span> <span class="dt">PROD</span></span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x09</span> <span class="ot">=</span> <span class="dt">GTx</span></span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x0a</span> <span class="ot">=</span> <span class="dt">WSUB</span></span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x0b</span> <span class="ot">=</span> <span class="dt">OUT</span></span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x1b</span> <span class="ot">=</span> <span class="dt">LDPI</span></span>
<span id="cb16-43"><a href="#cb16-43" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x1f</span> <span class="ot">=</span> <span class="dt">REM</span></span>
<span id="cb16-44"><a href="#cb16-44" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x20</span> <span class="ot">=</span> <span class="dt">RET</span></span>
<span id="cb16-45"><a href="#cb16-45" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x33</span> <span class="ot">=</span> <span class="dt">XOR</span></span>
<span id="cb16-46"><a href="#cb16-46" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x3b</span> <span class="ot">=</span> <span class="dt">SB</span></span>
<span id="cb16-47"><a href="#cb16-47" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x3c</span> <span class="ot">=</span> <span class="dt">GAJW</span></span>
<span id="cb16-48"><a href="#cb16-48" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x40</span> <span class="ot">=</span> <span class="dt">SHR</span></span>
<span id="cb16-49"><a href="#cb16-49" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x41</span> <span class="ot">=</span> <span class="dt">SHL</span></span>
<span id="cb16-50"><a href="#cb16-50" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x42</span> <span class="ot">=</span> <span class="dt">MINT</span></span>
<span id="cb16-51"><a href="#cb16-51" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x46</span> <span class="ot">=</span> <span class="dt">AND</span></span>
<span id="cb16-52"><a href="#cb16-52" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0x5a</span> <span class="ot">=</span> <span class="dt">DUP</span></span>
<span id="cb16-53"><a href="#cb16-53" aria-hidden="true" tabindex="-1"></a>parseSecondary <span class="bn">0xc1</span> <span class="ot">=</span> <span class="dt">SSUB</span></span>
<span id="cb16-54"><a href="#cb16-54" aria-hidden="true" tabindex="-1"></a>parseSecondary b <span class="ot">=</span> <span class="fu">error</span> <span class="op">$</span> <span class="st">&quot;Unknown secondary 0x&quot;</span> <span class="op">++</span> showHex b <span class="st">&quot;&quot;</span></span></code></pre></div>
<h2 id="the-two-stacks">The two stacks</h2>
<p>Data is manipulated using two different mechanisms: the integer stack and the
workspace.</p>
<p>The integer stack is a set of three registers: <code>A</code>, <code>B</code>, and <code>C</code>, which can be
used as a stack using these operations. Actually, it can only be manipulated
through push and pop operations, so we represent this using a list.</p>
<p>The instruction set reference says that an undefined value will be popped if the
stack is empty; here we consider that this will not happen, and allow a partial
pattern matching.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">pushInt ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>pushInt n <span class="ot">=</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    intStack <span class="op">%=</span> (n<span class="op">:</span>)</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="ot">popInt ::</span> <span class="dt">Eval</span> <span class="dt">Int32</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>popInt <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    (h<span class="op">:</span>t) <span class="ot">&lt;-</span> use intStack</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    intStack <span class="op">.=</span> t</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> h</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="ot">popAll ::</span> <span class="dt">Eval</span> (<span class="dt">Int32</span>, <span class="dt">Int32</span>, <span class="dt">Int32</span>)</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>popAll <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> popInt</span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    c <span class="ot">&lt;-</span> popInt</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> (a, b, c)</span></code></pre></div>
<p>Only the head (<code>A</code>) can be directly accessed, so we first define a lens between
a list and its head, and compose it with <code>intStack</code>.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">headLens ::</span> <span class="dt">Lens&#39;</span> [a] a</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>headLens <span class="ot">=</span> lens <span class="fu">head</span> <span class="op">$</span> \ l x <span class="ot">-&gt;</span> x<span class="op">:</span><span class="fu">tail</span> l</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="ot">areg ::</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Int32</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>areg <span class="ot">=</span> intStack <span class="op">.</span> headLens</span></code></pre></div>
<p>The workspace is a place in memory (pointed to by a register <code>wptr</code>) where local
variables can be stored and loaded, a bit like a stack pointer. We first define
push and pop operations.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ot">pushWorkspace ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>pushWorkspace value <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    wptr <span class="op">-=</span> <span class="dv">4</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    var <span class="dv">0</span> <span class="op">.=</span> value</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="ot">popWorkspace ::</span> <span class="dt">Eval</span> <span class="dt">Int32</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>popWorkspace <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>    w <span class="ot">&lt;-</span> use <span class="op">$</span> var <span class="dv">0</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>    wptr <span class="op">+=</span> <span class="dv">4</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> w</span></code></pre></div>
<p>Then we define a lens to focus on a variable.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="ot">var ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Int32</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>var n <span class="ot">=</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    lens getVar setVar</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>            varLens s <span class="ot">=</span> memWord ((s <span class="op">^.</span> wptr) <span class="op">@@</span> n)</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>            getVar s <span class="ot">=</span> s <span class="op">^.</span> varLens s</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>            setVar s v <span class="ot">=</span> set (varLens s) v s</span></code></pre></div>
<h2 id="input-and-output">Input and output</h2>
<p>The main particularity of the ST20 architecture is that it has hardware support
of message channels. They map fairly naturally to <code>Control.Concurrent.Chan</code>
channels. Each ST20 thread will have a map from channel numbers to input or
output channels:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getXChan ::</span> (<span class="dt">EvalEnv</span> <span class="ot">-&gt;</span> [(<span class="dt">Int32</span>, a)]) <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">EvalEnv</span> <span class="ot">-&gt;</span> a</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>getXChan member w st <span class="ot">=</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    fromJust <span class="op">$</span> <span class="fu">lookup</span> w <span class="op">$</span> member st</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="ot">getIChan ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">EvalEnv</span> <span class="ot">-&gt;</span> <span class="dt">IChannel</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>getIChan <span class="ot">=</span> getXChan envInChans</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="ot">getOChan ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">EvalEnv</span> <span class="ot">-&gt;</span> <span class="dt">OChannel</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>getOChan <span class="ot">=</span> getXChan envOutChans</span></code></pre></div>
<p>And these channels can be either a <code>Chan Word8</code> or a plain <code>Handle</code>, to connect
a thread to the process’ standard input and output.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ot">readFromIChan ::</span> <span class="dt">IChannel</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> [<span class="dt">Word8</span>]</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>readFromIChan (<span class="dt">InChan</span> chan) n <span class="ot">=</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="op">$</span> <span class="fu">mapM</span> (\ _ <span class="ot">-&gt;</span> readChan chan) [<span class="dv">1</span><span class="op">..</span>n]</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>readFromIChan (<span class="dt">InHandle</span> h) n <span class="ot">=</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>        bs <span class="ot">&lt;-</span> BS.hGet h <span class="op">$</span> <span class="fu">fromIntegral</span> n</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>        <span class="fu">return</span> <span class="op">$</span> BS.unpack bs</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="ot">writeToOChan ::</span> <span class="dt">OChannel</span> <span class="ot">-&gt;</span> [<span class="dt">Word8</span>] <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>writeToOChan (<span class="dt">OutChan</span> chan) ws <span class="ot">=</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="op">$</span> writeList2Chan chan ws</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>writeToOChan (<span class="dt">OutHandle</span> h) ws <span class="ot">=</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>        BS.hPutStr h <span class="op">$</span> BS.pack ws</span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>        hFlush h</span></code></pre></div>
<h2 id="a-few-combinators">A few combinators</h2>
<p>We first define a few combinators that will help us define the <code>interpret</code>
function.</p>
<p>Pop two operands, and push the result:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">liftOp ::</span> (<span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span>) <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>liftOp op <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> popInt</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    pushInt <span class="op">$</span> op a b</span></code></pre></div>
<p>Exchange two registers:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="ot">xchg ::</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> <span class="dt">EvalState</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>xchg l1 l2 <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  x1 <span class="ot">&lt;-</span> use l1</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  x2 <span class="ot">&lt;-</span> use l2</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>  l1 <span class="op">.=</span> x2</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  l2 <span class="op">.=</span> x1</span></code></pre></div>
<p>Convert a boolean to an integer:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromBool ::</span> <span class="dt">Bool</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>fromBool <span class="dt">False</span> <span class="ot">=</span> <span class="dv">0</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>fromBool <span class="dt">True</span> <span class="ot">=</span> <span class="dv">1</span></span></code></pre></div>
<h2 id="the-interpret-function">The <code>interpret</code> function</h2>
<p>The core of the interpreter is the following function. It takes an instruction
and transforms it into a monadic action in <code>Eval</code>.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="ot">interpret ::</span> <span class="dt">Instr</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span></code></pre></div>
<p>Some cases are very simple.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">AJW</span> n) <span class="ot">=</span> wptr <span class="op">+=</span> <span class="dv">4</span> <span class="op">*</span> n</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">LDNLP</span> n) <span class="ot">=</span> areg <span class="op">+=</span> <span class="dv">4</span> <span class="op">*</span> n</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">J</span> n) <span class="ot">=</span> iptr <span class="op">+=</span> n</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">LDC</span> n) <span class="ot">=</span> pushInt n</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">MINT</span>) <span class="ot">=</span> pushInt <span class="bn">0x80000000</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">GAJW</span>) <span class="ot">=</span> xchg areg wptr</span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">GCALL</span>) <span class="ot">=</span> xchg areg iptr</span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">ADC</span> n) <span class="ot">=</span> areg <span class="op">+=</span> n</span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">EQC</span> n) <span class="ot">=</span> areg <span class="op">%=</span> (\ a <span class="ot">-&gt;</span> fromBool <span class="op">$</span> a <span class="op">==</span> n)</span></code></pre></div>
<p>For some others, we can lift them into the host language and use Haskell
operations.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">PROD</span>) <span class="ot">=</span> liftOp (<span class="op">*</span>)</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">XOR</span>) <span class="ot">=</span> liftOp xor</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">AND</span>) <span class="ot">=</span> liftOp (<span class="op">.&amp;.</span>)</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">BSUB</span>) <span class="ot">=</span> liftOp (<span class="op">+</span>)</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">SSUB</span>) <span class="ot">=</span> liftOp <span class="op">$</span> \ a b <span class="ot">-&gt;</span> a <span class="op">+</span> <span class="dv">2</span> <span class="op">*</span> b</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">WSUB</span>) <span class="ot">=</span> liftOp (<span class="op">@@</span>)</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">GTx</span>) <span class="ot">=</span> liftOp <span class="op">$</span> \ a b <span class="ot">-&gt;</span> fromBool <span class="op">$</span> b <span class="op">&gt;</span> a</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">SHR</span>) <span class="ot">=</span> liftOp <span class="op">$</span> \ a b <span class="ot">-&gt;</span> b <span class="ot">`shiftR`</span> <span class="fu">fromIntegral</span> a</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">SHL</span>) <span class="ot">=</span> liftOp <span class="op">$</span> \ a b <span class="ot">-&gt;</span> b <span class="ot">`shiftL`</span> <span class="fu">fromIntegral</span> a</span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">REM</span>) <span class="ot">=</span> liftOp <span class="op">$</span> \ a b <span class="ot">-&gt;</span> b <span class="ot">`mod`</span> a</span></code></pre></div>
<p>Others need a few operations to prepare the operands and access memory.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">SB</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>    memByte a <span class="op">.=</span> <span class="fu">fromIntegral</span> b</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">DUP</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>    pushInt a</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    pushInt a</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">STL</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>    v <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>    var n <span class="op">.=</span> v</span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">LDLP</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>    v <span class="ot">&lt;-</span> use wptr</span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>    pushInt <span class="op">$</span> v <span class="op">@@</span> n</span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">LDL</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>    v <span class="ot">&lt;-</span> use <span class="op">$</span> var n</span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>    pushInt v</span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">LDPI</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>    ip <span class="ot">&lt;-</span> use iptr</span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>    areg <span class="op">+=</span> ip</span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">CJ</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> d <span class="ot">=</span> <span class="kw">if</span> a <span class="op">==</span> <span class="dv">0</span> <span class="kw">then</span> n <span class="kw">else</span> <span class="dv">0</span></span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">+=</span> d</span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">LB</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> use areg</span>
<span id="cb29-27"><a href="#cb29-27" aria-hidden="true" tabindex="-1"></a>    a&#39; <span class="ot">&lt;-</span> <span class="fu">fromIntegral</span> <span class="op">&lt;$&gt;</span> use (memByte a)</span>
<span id="cb29-28"><a href="#cb29-28" aria-hidden="true" tabindex="-1"></a>    areg <span class="op">.=</span> a&#39;</span>
<span id="cb29-29"><a href="#cb29-29" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">STNL</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-30"><a href="#cb29-30" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-31"><a href="#cb29-31" aria-hidden="true" tabindex="-1"></a>    b <span class="ot">&lt;-</span> popInt</span>
<span id="cb29-32"><a href="#cb29-32" aria-hidden="true" tabindex="-1"></a>    memWord (a <span class="op">@@</span> n) <span class="op">.=</span> b</span>
<span id="cb29-33"><a href="#cb29-33" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">LDNL</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb29-34"><a href="#cb29-34" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> use areg</span>
<span id="cb29-35"><a href="#cb29-35" aria-hidden="true" tabindex="-1"></a>    a&#39; <span class="ot">&lt;-</span> use <span class="op">$</span> memWord <span class="op">$</span> a <span class="op">@@</span> n</span>
<span id="cb29-36"><a href="#cb29-36" aria-hidden="true" tabindex="-1"></a>    areg <span class="op">.=</span> a&#39;</span></code></pre></div>
<p>Call and return instructions use the workspace to pass arguments.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Pri</span> <span class="dt">CALL</span> n) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    (a, b, c) <span class="ot">&lt;-</span> popAll</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>    pushWorkspace c</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>    pushWorkspace b</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    pushWorkspace a</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>    ip <span class="ot">&lt;-</span> use iptr</span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>    pushWorkspace ip</span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>    areg <span class="op">.=</span> ip</span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">+=</span> n</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">RET</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>    newIp <span class="ot">&lt;-</span> popWorkspace</span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">&lt;-</span> popWorkspace</span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">&lt;-</span> popWorkspace</span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">&lt;-</span> popWorkspace</span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">.=</span> newIp</span></code></pre></div>
<p>To perform I/O, the calling transputer needs to supply three things in the int
stack:</p>
<ul>
<li>the number of bytes to transfer;</li>
<li>a pointer to a channel;</li>
<li>where to read or write the message.</li>
</ul>
<p>The channel itself is abstracted in the transputer’s channel maps. Most reads
succeed; however the first transputer’s channel 0 will read directly from a
file, so it will reach end of file at some time. We can detect that when an
empty list is read, and exit the process.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">OUT</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    (len, pChan, pMsg) <span class="ot">&lt;-</span> popAll</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>    message <span class="ot">&lt;-</span> use <span class="op">$</span> mem8s pMsg len</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>    chan <span class="ot">&lt;-</span> asks <span class="op">$</span> getOChan pChan</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>    writeToOChan chan message</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>interpret (<span class="dt">Sec</span> <span class="dt">IN</span>) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>    (len, pChan, pMsg) <span class="ot">&lt;-</span> popAll</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>    chan <span class="ot">&lt;-</span> asks <span class="op">$</span> getIChan pChan</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">&lt;-</span> readFromIChan chan len</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>    when (<span class="fu">null</span> input) <span class="op">$</span> liftIO exitSuccess</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>    mem8s pMsg (<span class="fu">fromIntegral</span> <span class="op">$</span> <span class="fu">length</span> input) <span class="op">.=</span> input</span></code></pre></div>
<p>The core of the interpreter is then very simple:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ot">evalLoop ::</span> <span class="dt">Eval</span> ()</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>evalLoop <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>    i <span class="ot">&lt;-</span> decodeInstr</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>    interpret i</span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>    evalLoop</span></code></pre></div>
<h2 id="boot-from-link">Boot from link</h2>
<p>Several things are missing: the memory map, and how the system boots.</p>
<p>It turns out that the ST20 has a very simple boot protocol:</p>
<ul>
<li>read 1 byte from port 0, call it <code>n</code></li>
<li>read <code>n</code> bytes from port 0</li>
<li>store those at <code>memStart</code></li>
<li>set the workspace just after this memory chunk</li>
<li>jump to <code>memStart</code></li>
</ul>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">bootSeq ::</span> <span class="dt">Eval</span> ()</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>bootSeq <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>    chan <span class="ot">&lt;-</span> asks <span class="op">$</span> getIChan <span class="op">$</span> iPin <span class="dv">0</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>    len <span class="ot">&lt;-</span> <span class="fu">head</span> <span class="op">&lt;$&gt;</span> readFromIChan chan <span class="dv">1</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>    prog <span class="ot">&lt;-</span> readFromIChan chan <span class="op">$</span> <span class="fu">fromIntegral</span> len</span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>    mem8s memStart (<span class="fu">fromIntegral</span> <span class="op">$</span> <span class="fu">length</span> prog) <span class="op">.=</span> prog</span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>    wptr <span class="op">.=</span> memStart <span class="op">+</span> <span class="fu">fromIntegral</span> len</span></code></pre></div>
<p>There’s some flexibility on <code>memStart</code>, but this value works:</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">memStart ::</span> <span class="dt">Address</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>memStart <span class="ot">=</span> <span class="bn">0x80000100</span></span></code></pre></div>
<p>Pin numbers, however, are mapped to fixed address:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="ot">iPin ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>iPin n <span class="ot">=</span> <span class="bn">0x80000010</span> <span class="op">@@</span> n</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="ot">oPin ::</span> <span class="dt">Int32</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>oPin n <span class="ot">=</span> <span class="bn">0x80000000</span> <span class="op">@@</span> n</span></code></pre></div>
<p>We decide to initialize the memory with zeroes:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="ot">initialMem ::</span> <span class="dt">Mem</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>initialMem <span class="ot">=</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>    M.fromList <span class="op">$</span> <span class="fu">zip</span> [<span class="bn">0x80000000</span> <span class="op">..</span> memEnd] <span class="op">$</span> <span class="fu">repeat</span> <span class="dv">0</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>            memSize <span class="ot">=</span> <span class="bn">0x4000</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>            memEnd <span class="ot">=</span> memStart <span class="op">+</span> memSize <span class="op">-</span> <span class="dv">1</span></span></code></pre></div>
<p>Booting a transputer is then just a matter of reading from the correct channel
and doing the rest of the evaluation loop.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="ot">transputer ::</span> <span class="dt">Maybe</span> <span class="dt">Analysis</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>           <span class="ot">-&gt;</span> [((<span class="dt">Int32</span>, <span class="dt">IChannel</span>), (<span class="dt">Int32</span>, <span class="dt">OChannel</span>))]</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>           <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">MVar</span> ())</span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>transputer analysis cmap <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> (imap, omap) <span class="ot">=</span> <span class="fu">unzip</span> cmap</span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>    fork <span class="op">$</span> runEval initialMem imap omap <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>        bootSeq</span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>        runAnalysis analysis</span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>        evalLoop</span></code></pre></div>
<h2 id="multithreading-boilerplate">Multithreading boilerplate</h2>
<p>If you fork threads and don’t wait for them, nothing will happen since the main
thread will just exit. The solution is to create a “control” <code>MVar</code> that will be
signalled to by each thread:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fork ::</span> <span class="dt">IO</span> () <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">MVar</span> ())</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>fork io <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>    mvar <span class="ot">&lt;-</span> newEmptyMVar</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">&lt;-</span> forkFinally io <span class="op">$</span> \ _ <span class="ot">-&gt;</span> putMVar mvar ()</span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> mvar</span></code></pre></div>
<p>And to wait for all of them:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runAll ::</span> [<span class="dt">IO</span> (<span class="dt">MVar</span> ())] <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>runAll ms <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>    threads <span class="ot">&lt;-</span> <span class="fu">sequence</span> ms</span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">mapM_</span> takeMVar threads</span></code></pre></div>
<h2 id="connecting-the-lines">Connecting the lines</h2>
<p>For this problem we have 13 transputers.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">TransputerName</span> <span class="ot">=</span> <span class="dt">T00</span> <span class="op">|</span> <span class="dt">T01</span> <span class="op">|</span> <span class="dt">T02</span> <span class="op">|</span> <span class="dt">T03</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> <span class="dt">T04</span> <span class="op">|</span> <span class="dt">T05</span> <span class="op">|</span> <span class="dt">T06</span> <span class="op">|</span> <span class="dt">T07</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> <span class="dt">T08</span> <span class="op">|</span> <span class="dt">T09</span> <span class="op">|</span> <span class="dt">T10</span> <span class="op">|</span> <span class="dt">T11</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> <span class="dt">T12</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Enum</span>, <span class="dt">Eq</span>)</span></code></pre></div>
<p>We devise a way to connect them together. The communication between two
transputers is bidirectional, so we need two channels. Each of them is converted
to an <code>OChannel</code> on one side and an <code>IChannel</code> on the other one.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="ot">connect ::</span> <span class="dt">TransputerName</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">TransputerName</span> <span class="ot">-&gt;</span> <span class="dt">Int32</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">IO</span> [(<span class="dt">TransputerName</span>, <span class="dt">Int32</span>, <span class="dt">OChannel</span>, <span class="dt">IChannel</span>)]</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>connect src srcPort dst dstPort <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>  x <span class="ot">&lt;-</span> newChan</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>  y <span class="ot">&lt;-</span> newChan</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">return</span> [ (src, srcPort, <span class="dt">OutChan</span> x, <span class="dt">InChan</span> y)</span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>         , (dst, dstPort, <span class="dt">OutChan</span> y, <span class="dt">InChan</span> x)</span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>         ]</span></code></pre></div>
<p>Booting them is a matter of creating the correct communication channels (this
pinout list comes from a schematic that was present in the challenge files).</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>    pins <span class="ot">&lt;-</span> <span class="fu">concat</span> <span class="op">&lt;$&gt;</span> <span class="fu">sequence</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>        [ connect <span class="dt">T00</span> <span class="dv">1</span> <span class="dt">T01</span> <span class="dv">0</span></span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T00</span> <span class="dv">2</span> <span class="dt">T02</span> <span class="dv">0</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T00</span> <span class="dv">3</span> <span class="dt">T03</span> <span class="dv">0</span></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T01</span> <span class="dv">1</span> <span class="dt">T04</span> <span class="dv">0</span></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T01</span> <span class="dv">2</span> <span class="dt">T05</span> <span class="dv">0</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T01</span> <span class="dv">3</span> <span class="dt">T06</span> <span class="dv">0</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T02</span> <span class="dv">1</span> <span class="dt">T07</span> <span class="dv">0</span></span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T02</span> <span class="dv">2</span> <span class="dt">T08</span> <span class="dv">0</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T02</span> <span class="dv">3</span> <span class="dt">T09</span> <span class="dv">0</span></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T03</span> <span class="dv">1</span> <span class="dt">T10</span> <span class="dv">0</span></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T03</span> <span class="dv">2</span> <span class="dt">T11</span> <span class="dv">0</span></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T03</span> <span class="dv">3</span> <span class="dt">T12</span> <span class="dv">0</span></span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>        , connect <span class="dt">T11</span> <span class="dv">1</span> <span class="dt">T12</span> <span class="dv">1</span></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>        ]</span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>    runAll <span class="op">$</span> <span class="fu">map</span> (buildTransputer pins) [<span class="dt">T00</span> <span class="op">..</span>]</span>
<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>            buildTransputer pins t <span class="ot">=</span></span>
<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a>                transputer (isDebug t) <span class="op">$</span> onlyFor t pins <span class="op">++</span> extraPins t</span>
<span id="cb42-22"><a href="#cb42-22" aria-hidden="true" tabindex="-1"></a>            pin n ochan ichan <span class="ot">=</span> ((iPin n, ichan), (oPin n, ochan))</span>
<span id="cb42-23"><a href="#cb42-23" aria-hidden="true" tabindex="-1"></a>            onlyFor src l <span class="ot">=</span> [pin p oc ic <span class="op">|</span> (name, p, oc, ic) <span class="ot">&lt;-</span> l, name <span class="op">==</span> src]</span>
<span id="cb42-24"><a href="#cb42-24" aria-hidden="true" tabindex="-1"></a>            extraPins <span class="dt">T00</span> <span class="ot">=</span> [((iPin <span class="dv">0</span>, <span class="dt">InHandle</span> stdin), (oPin <span class="dv">0</span>, <span class="dt">OutHandle</span> stdout))]</span>
<span id="cb42-25"><a href="#cb42-25" aria-hidden="true" tabindex="-1"></a>            extraPins _ <span class="ot">=</span> []</span></code></pre></div>
<h2 id="bonus-static-analysis-tools">Bonus: static analysis tools</h2>
<p>The above <code>transputer</code> function is controlled by the following configuration:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Analysis</span> <span class="ot">=</span> <span class="dt">Graph</span> <span class="op">|</span> <span class="dt">Disasm</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a><span class="ot">isDebug ::</span> <span class="dt">TransputerName</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Analysis</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>isDebug _ <span class="ot">=</span> <span class="dt">Nothing</span></span></code></pre></div>
<p>It means that for each transputer, we can choose to print a graph or a
disassembly of the code that will be executed. To do that, we will first compute
the set of all edges in the control flow graph.</p>
<p>This analysis relies on a <code>nextInstr</code> function that statically computes the set
of next instructions. These can be reached either because it’s the next
one in the instruction flow (<code>DSeq</code>), because of jump (<code>DJmp</code>), or an unknown
destination, for example after a <code>RET</code> (<code>DDyn</code>).</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Dest</span> <span class="ot">=</span> <span class="dt">DSeq</span> <span class="dt">Address</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>          <span class="op">|</span> <span class="dt">DJmp</span> <span class="dt">Address</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>          <span class="op">|</span> <span class="dt">DDyn</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>)</span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a><span class="ot">nextInstrs ::</span> <span class="dt">Instr</span> <span class="ot">-&gt;</span> [<span class="dt">Dest</span>]</span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>nextInstrs (<span class="dt">Pri</span> <span class="dt">CJ</span> n) <span class="ot">=</span> [<span class="dt">DSeq</span> <span class="dv">0</span>, <span class="dt">DJmp</span> n]</span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>nextInstrs (<span class="dt">Pri</span> <span class="dt">J</span> n) <span class="ot">=</span> [<span class="dt">DJmp</span> n]</span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>nextInstrs (<span class="dt">Pri</span> <span class="dt">CALL</span> n) <span class="ot">=</span> [<span class="dt">DSeq</span> <span class="dv">0</span>, <span class="dt">DJmp</span> n]</span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>nextInstrs (<span class="dt">Sec</span> <span class="dt">GCALL</span>) <span class="ot">=</span> [<span class="dt">DDyn</span>]</span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>nextInstrs (<span class="dt">Sec</span> <span class="dt">RET</span>) <span class="ot">=</span> [<span class="dt">DDyn</span>]</span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>nextInstrs _ <span class="ot">=</span> [<span class="dt">DSeq</span> <span class="dv">0</span>]</span></code></pre></div>
<p>We can wrap this function in a monadic one that can turn these relative
addresses into absolute ones (since it can know the addresses of functions).</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">EdgeSet</span> <span class="ot">=</span> <span class="dt">S.Set</span> (<span class="dt">Address</span>, <span class="dt">Instr</span>, <span class="dt">Dest</span>)</span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a><span class="ot">instrDests ::</span> <span class="dt">Address</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> <span class="dt">EdgeSet</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>instrDests start <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">.=</span> start</span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>    i <span class="ot">&lt;-</span> decodeInstr</span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> deltaips <span class="ot">=</span> nextInstrs i</span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>    new <span class="ot">&lt;-</span> use iptr</span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> <span class="op">$</span> S.fromList <span class="op">$</span> <span class="fu">map</span> (\ d <span class="ot">-&gt;</span> (start, i, adjust new d)) deltaips</span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a>            adjust n (<span class="dt">DSeq</span> d) <span class="ot">=</span> <span class="dt">DSeq</span> <span class="op">$</span> n <span class="op">+</span> d</span>
<span id="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a>            adjust n (<span class="dt">DJmp</span> d) <span class="ot">=</span> <span class="dt">DJmp</span> <span class="op">$</span> n <span class="op">+</span> d</span>
<span id="cb45-13"><a href="#cb45-13" aria-hidden="true" tabindex="-1"></a>            adjust _ <span class="dt">DDyn</span> <span class="ot">=</span> <span class="dt">DDyn</span></span></code></pre></div>
<p>Then, the algorithm consists in computing the fixpoint of the following
iterating function:</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="ot">step ::</span> <span class="dt">EdgeSet</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> <span class="dt">EdgeSet</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a>step s <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>    xs <span class="ot">&lt;-</span> <span class="fu">mapM</span> (basicBlockM <span class="op">.</span> getDest) <span class="op">$</span> S.toList s</span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> <span class="op">$</span> S.union s <span class="op">$</span> S.unions xs</span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>            getDest (_, _, <span class="dt">DSeq</span> a) <span class="ot">=</span> <span class="dt">Just</span> a</span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>            getDest (_, _, <span class="dt">DJmp</span> a) <span class="ot">=</span> <span class="dt">Just</span> a</span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>            getDest (_, _, <span class="dt">DDyn</span>) <span class="ot">=</span> <span class="dt">Nothing</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a>            basicBlockM (<span class="dt">Just</span> a) <span class="ot">=</span> instrDests a</span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>            basicBlockM <span class="dt">Nothing</span> <span class="ot">=</span> <span class="fu">return</span> S.empty</span></code></pre></div>
<p>The fixpoint itself is computed using the following function, which takes a
predicate on two <code>EdgeSet</code>s to stop the iteration.</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="ot">stepUntil ::</span> ((<span class="dt">EdgeSet</span>, <span class="dt">EdgeSet</span>) <span class="ot">-&gt;</span> <span class="dt">Bool</span>) <span class="ot">-&gt;</span> (<span class="dt">EdgeSet</span>, <span class="dt">EdgeSet</span>) <span class="ot">-&gt;</span> <span class="dt">Eval</span> <span class="dt">EdgeSet</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>stepUntil p (a, b) <span class="op">|</span> p (a, b) <span class="ot">=</span> <span class="fu">return</span> b</span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>stepUntil p (_, b) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a>    c <span class="ot">&lt;-</span> step b</span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a>    stepUntil p (b, c)</span></code></pre></div>
<p>We’ll stop when their size is equal.</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runAnalysis ::</span> <span class="dt">Maybe</span> <span class="dt">Analysis</span> <span class="ot">-&gt;</span> <span class="dt">Eval</span> ()</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>runAnalysis <span class="dt">Nothing</span> <span class="ot">=</span> <span class="fu">return</span> ()</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>runAnalysis (<span class="dt">Just</span> analysis) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>    s0 <span class="ot">&lt;-</span> instrDests memStart</span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> p (a, b) <span class="ot">=</span> S.size a <span class="op">==</span> S.size b</span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>    r <span class="ot">&lt;-</span> stepUntil p (S.empty, s0)</span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="op">$</span> <span class="fu">putStrLn</span> <span class="op">$</span> convert analysis r</span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>    iptr <span class="op">.=</span> memStart</span></code></pre></div>
<p>Finally, here is how to convert the <code>EdgeSet</code>s in a human-readable form.</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="ot">convert ::</span> <span class="dt">Analysis</span> <span class="ot">-&gt;</span> <span class="dt">EdgeSet</span> <span class="ot">-&gt;</span> <span class="dt">String</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>convert <span class="dt">Graph</span> es <span class="ot">=</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;digraph G{\n&quot;</span></span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">++</span> <span class="st">&quot;node[shape=point]\n&quot;</span></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">++</span> <span class="fu">concatMap</span> edge (S.toList es)</span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">++</span> <span class="st">&quot;}&quot;</span></span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span></span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>            edge (x, i, y) <span class="ot">=</span> <span class="fu">show</span> x <span class="op">++</span> <span class="st">&quot; -&gt; &quot;</span> <span class="op">++</span> toNode x y <span class="op">++</span> <span class="st">&quot;[label=\&quot;&quot;</span> <span class="op">++</span> <span class="fu">show</span> i <span class="op">++</span> <span class="st">&quot;\&quot;];\n&quot;</span></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>            toNode _ (<span class="dt">DSeq</span> a) <span class="ot">=</span> <span class="fu">show</span> a</span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a>            toNode _ (<span class="dt">DJmp</span> a) <span class="ot">=</span> <span class="fu">show</span> a</span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a>            toNode x <span class="dt">DDyn</span> <span class="ot">=</span> <span class="st">&quot;dyn&quot;</span> <span class="op">++</span> <span class="fu">show</span> x</span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a>convert <span class="dt">Disasm</span> es <span class="ot">=</span> <span class="fu">concatMap</span> go <span class="op">$</span> S.toList es</span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span></span>
<span id="cb49-14"><a href="#cb49-14" aria-hidden="true" tabindex="-1"></a>        go (x, i, <span class="dt">DSeq</span> _) <span class="ot">=</span></span>
<span id="cb49-15"><a href="#cb49-15" aria-hidden="true" tabindex="-1"></a>            printf <span class="st">&quot;%04x %s\n&quot;</span> x (<span class="fu">show</span> i)</span>
<span id="cb49-16"><a href="#cb49-16" aria-hidden="true" tabindex="-1"></a>        go (x, i, <span class="dt">DJmp</span> y) <span class="ot">=</span></span>
<span id="cb49-17"><a href="#cb49-17" aria-hidden="true" tabindex="-1"></a>            printf <span class="st">&quot;%04x %s  [* %04x]\n&quot;</span> x (<span class="fu">show</span> i) y</span>
<span id="cb49-18"><a href="#cb49-18" aria-hidden="true" tabindex="-1"></a>        go (x, i, <span class="dt">DDyn</span>) <span class="ot">=</span></span>
<span id="cb49-19"><a href="#cb49-19" aria-hidden="true" tabindex="-1"></a>            printf <span class="st">&quot;%04x %s  [* dyn]\n&quot;</span> x (<span class="fu">show</span> i)</span></code></pre></div>
<p>For example here is an extract of the beginning of the first transputer. You can
notice instructions with several destinations (conditional jumps) are displayed
twice.</p>
<pre><code>80000100 AJW -76
80000102 LDC 0
80000103 STL 1
80000104 LDC 0
80000105 STL 3
80000106 MINT
80000108 LDNLP 1024
8000010b GAJW
8000010d AJW -76
8000010f LDC 201
80000111 LDPI
80000113 MINT
80000115 LDC 8
80000116 OUT
80000117 LDLP 73
80000119 MINT
8000011b LDNLP 4
8000011c LDC 12
8000011d IN
8000011e LDL 73
80000120 CJ 21
80000120 CJ 21  [* 80000137]
80000122 LDC 205
80000124 LDPI</code></pre>
<p>For the graph output, I assume that you have already seen graphviz output:</p>
<figure>
<img src="/img/st20/t03.png" alt="T03 with dot driver" />
<figcaption aria-hidden="true">T03 with dot driver</figcaption>
</figure>
<p>The introduction image was done using the same output but an alternative layout
engines.</p>
<p>Hope you enjoyed this article!</p>]]></description>
    <pubDate>Thu, 20 Aug 2015 00:00:00 UT</pubDate>
    <guid>http://blog.emillon.org/posts/2015-08-20-a-lens-based-st20-emulator.html</guid>
    <dc:creator>Etienne Millon</dc:creator>
</item>

    </channel>
</rss>
