<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://resume.dreamw1ngs.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://resume.dreamw1ngs.com/" rel="alternate" type="text/html" /><updated>2026-09-17T11:29:36+00:00</updated><id>https://resume.dreamw1ngs.com/feed.xml</id><title type="html">Zhejian Lai’s README</title><subtitle>Zhejian Lai&apos;s academic portfolio</subtitle><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><entry><title type="html">Flakes &amp;amp; chezmoi 配置使用</title><link href="https://resume.dreamw1ngs.com/posts/2025/11/10/tools/" rel="alternate" type="text/html" title="Flakes &amp;amp; chezmoi 配置使用" /><published>2025-11-10T00:00:00+00:00</published><updated>2025-11-10T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2025/11/10/blog-post-tool</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2025/11/10/tools/"><![CDATA[<h1 id="tool-使用">Tool 使用</h1>

<h2 id="flakes">Flakes</h2>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sh &lt;<span class="o">(</span>curl <span class="nt">-L</span> https://nixos.org/nix/install<span class="o">)</span>
git clone <span class="nt">--recursive</span> https://github.com/LaiZhejian/flakes
<span class="nb">cd </span>flakes
git submodule update <span class="nt">--init</span> <span class="nt">--recursive</span> <span class="c"># 如果上一步没使用--recursive需补上</span>
</code></pre></div></div>

<ul>
  <li>
    <p>For WSL or command-line Linux systems</p>

    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>nix <span class="nt">--extra-experimental-features</span> <span class="s1">'nix-command flakes'</span> run home-manager/master <span class="nt">--</span> switch <span class="nt">--flake</span> <span class="s2">".?submodules=1#dream"</span>
</code></pre></div>    </div>

    <p>In <code class="language-plaintext highlighter-rouge">/etc/nix/nix.conf</code>, add the below content</p>

    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>experimental-features <span class="o">=</span> nix-command flakes
substituters <span class="o">=</span> https://mirrors.ustc.edu.cn/nix-channels/store https://cache.nixos.org/
trusted-users <span class="o">=</span> root dream
</code></pre></div>    </div>
  </li>
  <li>
    <p>For Mac</p>

    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>nix <span class="nt">--extra-experimental-features</span> <span class="s1">'nix-command flakes'</span> run nix-darwin <span class="nt">--</span> switch <span class="nt">--flake</span> <span class="s2">".?submodules=1#darwin"</span> <span class="c"># setup</span>
<span class="nb">sudo </span>darwin-rebuild switch <span class="nt">--flake</span> <span class="s2">".?submodules=1#darwin"</span> <span class="c"># rebuild</span>
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="configuration">Configuration</h3>

<p>specific指代具体某个nix配置，platform指代宏观的如darwin（mac自己的preference）, desktop, command line</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">flake.nix</code> 存储全局nix的配置，包括darwin，dream使用哪些具体的nix配置 （需要添加新specific改这里），组装【platform的nix】和【specific的nix】</li>
  <li><code class="language-plaintext highlighter-rouge">configurations/{specific}/default.nix</code> 存储对应specific的nix配置（需要添加新specific改这里）</li>
  <li><code class="language-plaintext highlighter-rouge">home/presets/{platform}</code> 存储对应platform的nix配置 （增添app）</li>
  <li><code class="language-plaintext highlighter-rouge">modules/{platform}/{app}</code>修改platform下对应app的具体配置 （修改app）</li>
</ul>

<h2 id="chezmoi">chezmoi</h2>

<ol>
  <li>
    <p>初始化<code class="language-plaintext highlighter-rouge">chezmoi init https://github.com/LaiZhejian/dotfiles</code></p>

    <p>其中的文件<code class="language-plaintext highlighter-rouge">.chezmoi.toml.tmpl</code>允许使用明文加密和解析</p>

    <div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">{{</span> <span class="err">$passphrase</span> <span class="py">:</span><span class="p">=</span> <span class="err">promptStringOnce</span> <span class="err">.</span> <span class="s">"passphrase"</span> <span class="s">"passphrase"</span> <span class="err">-}}</span>
   
<span class="py">encryption</span> <span class="p">=</span> <span class="s">"gpg"</span>
<span class="nn">[data]</span>
    <span class="nn">passphrase</span> <span class="o">=</span> <span class="p">{</span><span class="err">{</span> <span class="err">$passphrase</span> <span class="err">|</span> <span class="err">quote</span> <span class="p">}</span><span class="err">}</span>
<span class="nn">[gpg]</span>
    <span class="py">symmetric</span> <span class="p">=</span> <span class="kc">true</span>
    <span class="py">args</span> <span class="p">=</span> <span class="p">[</span><span class="s">"--batch"</span><span class="p">,</span> <span class="s">"--passphrase"</span><span class="p">,</span> <span class="err">{{</span> <span class="err">$passphrase</span> <span class="err">|</span> <span class="err">quote</span> <span class="err">}}</span><span class="p">,</span> <span class="s">"--no-symkey-cache"</span><span class="p">,</span> <span class="s">"--quiet"</span><span class="p">]</span>
   
</code></pre></div>    </div>
  </li>
  <li><code class="language-plaintext highlighter-rouge">chezmoi apply</code>解密配置细腻下</li>
  <li><code class="language-plaintext highlighter-rouge">chezmoi add [--encrypt]</code>添加被管理文件，可选加密</li>
</ol>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="Notes" /><summary type="html"><![CDATA[Tool 使用]]></summary></entry><entry><title type="html">CUDA / CUDA Toolkit / CudNN / NCCL 配置</title><link href="https://resume.dreamw1ngs.com/posts/2025/06/20/cuda/" rel="alternate" type="text/html" title="CUDA / CUDA Toolkit / CudNN / NCCL 配置" /><published>2025-06-20T00:00:00+00:00</published><updated>2025-06-20T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2025/06/20/blog-post-cuda</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2025/06/20/cuda/"><![CDATA[<blockquote>
  <p>对于一个深耕机器学习的孩纸来说，cuda简直是噩梦的代名词，一般我们都选择继承前辈遗产或者抄菜谱，最近在实习，迫于现实无奈狠狠研究了一下CUDA各个名词之间的关系，并在此进行汇总，希望能够对读者有所帮助</p>
</blockquote>

<p>TLDR</p>

<ul>
  <li>安装最新的CUDA Driver</li>
  <li>根据约束关系安装最新的CUDA Toolkit</li>
  <li>根据CUDA Toolkit，安装你需要的各种包</li>
</ul>

<h2 id="万物源头显卡">万物源头：显卡</h2>

<p>首先我们得有一张NVIDIA显卡，显卡不依赖于任何包，只依赖于💰(bushi)。其算力情况和架构均可以在 https://developer.nvidia.com/cuda-gpus 该网站上查询。</p>

<h2 id="显卡操作指南cuda-driver">显卡操作指南：CUDA Driver</h2>

<p>（依赖于<a href="#万物源头：显卡">显卡</a>）</p>

<p><a href="https://www.nvidia.com/en-us/drivers/unix/">【下载点击这里】</a></p>

<p><strong>CUDA Driver</strong> 是 NVIDIA 提供的一部分软件，用于在计算机上运行使用 <strong>CUDA</strong>（Compute Unified Device Architecture）编写的程序。它是连接 <strong>GPU 硬件</strong> 和 <strong>CUDA 应用程序</strong> 的中间层，主要负责在 GPU 上执行 CUDA 程序。当你运行使用 CUDA 编写的程序时，CUDA Driver 提供运行时支持（Runtime API 是基于它工作的）。</p>

<p>每张显卡都有一个 <strong>最低驱动版本要求</strong>，通常是为了启用对应的 CUDA Compute Capability</p>

<p>NVIDIA 的最新版驱动往往支持 <strong>当前所有显卡</strong>，甚至包括旧型号――这是它们所谓的「向下兼容性」。</p>

<p>所以，简单来说：CUDA Driver版本越高越好！</p>

<p>我们可以通过<code class="language-plaintext highlighter-rouge">nvidia-smi</code>查看CUDA Driver的版本</p>

<h2 id="开发者工具cuda-toolkit">开发者工具：CUDA Toolkit</h2>

<p>（依赖于GCC版本，<a href="#显卡操作指南：CUDA Driver">CUDA Driver</a>以及<a href="#万物源头：显卡">显卡</a>）</p>

<p><a href="https://developer.nvidia.com/cuda-downloads">【下载点击这里】</a></p>

<p>我们常常说的CUDA版本一般代指的就是此处CUDA Toolkit的版本。</p>

<p>CUDA Toolkit是NVIDIA 提供的开发工具包，用于在 GPU 上进行并行计算，包括nvcc 编译器，用来编译 CUDA C/C++ 代码。既然提到了C，这里很显然要依赖于GCC版本，GCC和GLIBC以及LINUX内核是绑定的，所以一般<strong>系统决定了我们的CUDA Toolkit的版本上限</strong>。在 <a href="https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#host-compiler-support-policy">【点击这里】</a> 中可以查看到最新版本的CUDA所需要的编译器版本。</p>

<p>同时<strong>CUDA Toolkit必须要比CUDA Driver的版本要低</strong>，具体关系在<a href="https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-driver">【点击这里】</a>有介绍。</p>

<p>最后CUDA Toolkit和显卡是有约束关系的，在wiki中有一张 <a href="https://en.wikipedia.org/wiki/CUDA#GPUs_supported">【矩阵图】</a> 展示了这个情况。但是这个约束关系最弱，一般来说只要不是古董级显卡，CUDA Toolkit版本越高能兼容更多显卡。</p>

<p>我们可以通过<code class="language-plaintext highlighter-rouge">nvcc --version</code>查看CUDA Toolkit的版本。</p>

<p>下面给出我们自己安装的 CUDA Toolkit 和torch包中包含的 CUDA Toolkit 的区别。我们在pytorch官网中看到的CUDA版本指的就是编译torch的CUDA Toolkit版本，并且这个CUDA Toolkit会以丐版的形式安装在我们的conda环境中。但无论是哪种，我们都需要记得指定<code class="language-plaintext highlighter-rouge">LD_LIBRARAY_PATH=/usr/local/cuda/lib64</code>（这里展示的是自己安装的cuda的，conda的话是在环境下的lib64文件夹）以确保可以让程序找到动态链接库。</p>

<table>
  <thead>
    <tr>
      <th><strong>CUDA Toolkit（NVIDIA 官方）</strong></th>
      <th><strong>conda cudatoolkit / pytorch-cuda</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>编译/开发任何 CUDA 程序</td>
      <td>运行 PyTorch 本身</td>
    </tr>
    <tr>
      <td>nvcc、profiler、头文件、全部库</td>
      <td>仅 cudart + cuBLAS/cuDNN/NCCL…</td>
    </tr>
    <tr>
      <td>~2 GB</td>
      <td>数百 MB</td>
    </tr>
    <tr>
      <td>系统级目录</td>
      <td>Conda/Pip 虚拟环境</td>
    </tr>
    <tr>
      <td>需匹配显卡驱动；占用系统 PATH</td>
      <td>只需驱动；环境隔离</td>
    </tr>
    <tr>
      <td>编译自定义 Kernel、C++ GPU 应用</td>
      <td>常规 PyTorch 训练/推理</td>
    </tr>
  </tbody>
</table>

<h2 id="其他内容cudnnnccl等">其他内容cuDNN、NCCL等</h2>

<p>（依赖于<a href="开发者工具：CUDA Toolkit">CUDA Toolkit</a>）</p>

<h3 id="cudnncuda-deep-neural-network-library">cuDNN（CUDA Deep Neural Network library）</h3>

<p><a href="https://developer.nvidia.com/cudnn-downloads">【下载点击这里】</a>（需登陆账号）</p>

<p>提供各种深度学习常用操作的高效GPU实现，例如卷积（Convolution）、池化（Pooling）、激活函数、RNN/LSTM、BatchNorm 等，加速前向/反向传播。</p>

<p>与CUDA toolkit的关系在 <a href="https://docs.nvidia.com/deeplearning/cudnn/backend/latest/reference/support-matrix.html">【点击这里】</a></p>

<hr />

<h3 id="ncclnvidia-collective-communications-library"><strong>NCCL</strong>（NVIDIA Collective Communications Library）</h3>

<p><a href="https://developer.nvidia.com/nccl/nccl-download">【下载点击这里】</a>（需登陆账号）</p>

<p>提供多GPU/多节点之间的高性能通信原语，包含 AllReduce、Broadcast、AllGather、ReduceScatter、点对点 send/recv 等，能够自动根据 PCIe、NVLink、InfiniBand 等硬件拓扑优化通信路径与性能。</p>

<p>与CUDA toolkit的关系在 <a href="https://docs.nvidia.com/deeplearning/nccl/install-guide/index.html#softreq">【点击这里】</a></p>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="Notes" /><summary type="html"><![CDATA[对于一个深耕机器学习的孩纸来说，cuda简直是噩梦的代名词，一般我们都选择继承前辈遗产或者抄菜谱，最近在实习，迫于现实无奈狠狠研究了一下CUDA各个名词之间的关系，并在此进行汇总，希望能够对读者有所帮助]]></summary></entry><entry><title type="html">NJU ICS2024 PA 作业心得（四）</title><link href="https://resume.dreamw1ngs.com/posts/2025/01/15/ics-pa4/" rel="alternate" type="text/html" title="NJU ICS2024 PA 作业心得（四）" /><published>2025-01-15T00:00:00+00:00</published><updated>2025-01-15T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2025/01/15/blog-post-ics-pa4</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2025/01/15/ics-pa4/"><![CDATA[<blockquote>
  <p>深入探讨多道程序处理中的上下文切换实现，分析系统调用、进程调度与内存管理的核心机制，并对比 main() 和 execve() 参数设计的差异。</p>
</blockquote>

<h2 id="多道程序问题处理">多道程序问题处理</h2>

<p>在系统调用的实现中，当进程A触发了<code class="language-plaintext highlighter-rouge">ecall</code>指令并陷入到内核模式时，A的上下文结构会通过<code class="language-plaintext highlighter-rouge">__am_asm_trap()</code>保存到A的栈上。系统调用处理完毕后，<code class="language-plaintext highlighter-rouge">__am_asm_trap()</code>会根据保存的上下文来恢复A的执行状态。然而，若要实现进程之间的切换，在系统调用完成后，<code class="language-plaintext highlighter-rouge">__am_asm_trap()</code>不立即恢复A的上下文，而是先切换到另一个进程B的上下文。由于B的栈上已保存了其上下文信息，因此接下来的操作将恢复B的上下文。当<code class="language-plaintext highlighter-rouge">__am_asm_trap()</code>返回时，进程B开始执行。</p>

<h3 id="kcontext怎么实现和__am_asm_trap怎么修改">kcontext怎么实现和__am_asm_trap怎么修改？</h3>

<ol>
  <li>
    <p>kcontext通过修改一个 <code class="language-plaintext highlighter-rouge">kstack</code>结构中的信息来初始化一个新的Context。所以我们需要先创造一个这样大小的空间，并将其中的<code class="language-plaintext highlighter-rouge">sp</code>指针指向栈底，同时根据ABI手册要求，将参数覆给<code class="language-plaintext highlighter-rouge">a0</code>寄存器。同时设置好<code class="language-plaintext highlighter-rouge">mepc</code>寄存器指向当前的调用入口位置，并为了使得通过difftest检验，设置<code class="language-plaintext highlighter-rouge">mstatus</code>为<code class="language-plaintext highlighter-rouge">0x1800</code>。</p>
  </li>
  <li>
    <p>至于<code class="language-plaintext highlighter-rouge">__am_asm_trap</code>，按照要求在<code class="language-plaintext highlighter-rouge">call</code>指令后，将<code class="language-plaintext highlighter-rouge">sp</code>寄存器设置为<code class="language-plaintext highlighter-rouge">a0</code>寄存器的内容进行恢复即可。</p>
  </li>
</ol>

<h3 id="怎么在nanos-lite实现上下文切换">怎么在Nanos-lite实现上下文切换？</h3>

<p>在<code class="language-plaintext highlighter-rouge">context_kload</code>直接利用<code class="language-plaintext highlighter-rouge">kcontext</code>函数创建上下文即可。</p>

<p><code class="language-plaintext highlighter-rouge">schedule</code>函数中保存好当前执行上下文状态，再调度到另一个上下文即可。</p>

<p>为了实现载入用户程序，我们需要实现<code class="language-plaintext highlighter-rouge">context_uload</code>，它需要实现下面这些功能：</p>

<ol>
  <li>为即将执行的用户程序分配内存页面。</li>
  <li>加载指定的程序（<code class="language-plaintext highlighter-rouge">filename</code>）并获取其入口地址。</li>
  <li>设置用户进程的上下文，包括栈、地址空间、入口地址等。</li>
  <li>处理命令行参数（<code class="language-plaintext highlighter-rouge">argv</code>）和环境变量（<code class="language-plaintext highlighter-rouge">envp</code>），将它们复制到内存，并更新 <code class="language-plaintext highlighter-rouge">pcb</code>（进程控制块）中的相关信息。</li>
  <li>最终，将构建好的上下文（包括参数等）保存到 <code class="language-plaintext highlighter-rouge">pcb</code> 中，为进程的启动做好准备。</li>
</ol>

<p>为了验证PAL试运行在用户栈而不是内核栈，一个非常简单的方法，是验证执行该程序时，<code class="language-plaintext highlighter-rouge">sp</code>指针是不是位于AM中划分好的用户空间<code class="language-plaintext highlighter-rouge"> RANGE(0x40000000, 0x80000000)</code>。</p>

<h3 id="一山不能藏二虎">一山不能藏二虎?</h3>

<p>在 <code class="language-plaintext highlighter-rouge">navy-apps/scripts/$ISA.mk</code> 中，程序被编译时会指定一个固定的 <strong>链接地址</strong>，即所有程序的代码和数据都会被链接到 <strong>0x83000000</strong> 这个内存地址。这个地址被用作每个程序的 <strong>加载地址</strong>。因此，当你加载第二个用户进程时，第二个进程会把第一个进程的内存空间完全覆盖，导致第一个进程的代码和数据丢失，或者发生不可预期的行为。</p>

<h3 id="为什么少了一个const">为什么少了一个const?</h3>

<p>这个差异主要反映了 <code class="language-plaintext highlighter-rouge">main()</code> 和 <code class="language-plaintext highlighter-rouge">execve()</code> 在处理命令行参数和环境变量时的不同语义：</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">main()</code> 函数中的 <code class="language-plaintext highlighter-rouge">argv</code> 和 <code class="language-plaintext highlighter-rouge">envp</code> 是可修改的</strong>：在 <code class="language-plaintext highlighter-rouge">main()</code> 中，程序启动时传入的命令行参数和环境变量可能会被修改。例如，<code class="language-plaintext highlighter-rouge">argv[0]</code> 可能会被修改为程序的名称，或者你可能会修改环境变量 <code class="language-plaintext highlighter-rouge">envp</code>。所以，<code class="language-plaintext highlighter-rouge">main()</code> 中的 <code class="language-plaintext highlighter-rouge">argv</code> 和 <code class="language-plaintext highlighter-rouge">envp</code> 没有被声明为 <code class="language-plaintext highlighter-rouge">const</code>，允许对它们进行修改。</li>
  <li><strong><code class="language-plaintext highlighter-rouge">execve()</code> 函数中的 <code class="language-plaintext highlighter-rouge">argv</code> 和 <code class="language-plaintext highlighter-rouge">envp</code> 是常量数组</strong>：<code class="language-plaintext highlighter-rouge">execve()</code> 是用来执行一个新的程序，它的参数（<code class="language-plaintext highlighter-rouge">argv</code> 和 <code class="language-plaintext highlighter-rouge">envp</code>）指向的内容不应该被修改。执行一个新程序时，操作系统会用这些参数来设置新的进程环境。如果允许修改 <code class="language-plaintext highlighter-rouge">argv</code> 或 <code class="language-plaintext highlighter-rouge">envp</code>，可能会导致新的程序的启动环境不一致或错误。因此，<code class="language-plaintext highlighter-rouge">execve()</code> 将 <code class="language-plaintext highlighter-rouge">argv</code> 和 <code class="language-plaintext highlighter-rouge">envp</code> 声明为 <code class="language-plaintext highlighter-rouge">char *const []</code>，以禁止修改指向这些字符串数组的指针。</li>
</ul>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="ICS" /><summary type="html"><![CDATA[深入探讨多道程序处理中的上下文切换实现，分析系统调用、进程调度与内存管理的核心机制，并对比 main() 和 execve() 参数设计的差异。]]></summary></entry><entry><title type="html">NJU ICS2024 PA 作业心得（三）</title><link href="https://resume.dreamw1ngs.com/posts/2024/12/24/ics-pa3/" rel="alternate" type="text/html" title="NJU ICS2024 PA 作业心得（三）" /><published>2024-12-24T00:00:00+00:00</published><updated>2024-12-24T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2024/12/24/blog-post-ics-pa3</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2024/12/24/ics-pa3/"><![CDATA[<blockquote>
  <p>记录了在RISC-V架构下实现异常响应机制、系统调用和文件系统的过程，包括NEMU模拟器的扩展、AM抽象层的异常处理以及Nanos-lite操作系统的系统调用实现，并分析了ELF加载和程序执行流程。</p>
</blockquote>

<h2 id="需要参考的内容">需要参考的内容</h2>

<ol>
  <li><a href="https://d3s.mff.cuni.cz/files/teaching/nswi200/202324/doc/riscv-abi.pdf">RISC-V ABIs Specification</a>：是一组规则和规范，定义了在 RISC-V 架构上编写和链接程序的方式。它确保了不同语言编写的代码、不同编译器生成的代码以及操作系统之间的兼容性。<strong>在这部分PA中我们需要参考其中定义的每个寄存器的功能，以及对应存储传递内容的含义。</strong></li>
  <li><a href="https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf">The RISC-V Instruction Set Manual–Volume II: Privileged Architecture</a>：定义了 RISC-V 架构的特权模式和相关功能。这本手册的核心内容是描述操作系统、虚拟化和其他需要硬件支持的高特权操作所需的架构支持。<strong>在这部分PA中我们需要参考其中的控制状态寄存器相关指令，包括实现方式及具体意义。</strong></li>
</ol>

<h2 id="穿越时空的旅程问题处理">穿越时空的旅程问题处理</h2>

<p>我们首先需要明确的是<code class="language-plaintext highlighter-rouge">cte_init</code>函数的作用是什么，在文档中已经给了详细的说明，我们也需要在<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/cte.c</code>中<code class="language-plaintext highlighter-rouge">cte_init</code>函数的代码分别找到对应实现：</p>

<ol>
  <li>
    <p>设置异常入口地址</p>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">asm</span> <span class="nf">volatile</span><span class="p">(</span><span class="s">"csrw mtvec, %0"</span> <span class="o">:</span> <span class="o">:</span> <span class="s">"r"</span><span class="p">(</span><span class="n">__am_asm_trap</span><span class="p">));</span>
</code></pre></div>    </div>

    <p>这里csrw是一个针对控制状态寄存器读写操作的指令，上述的汇编指令将<code class="language-plaintext highlighter-rouge">am_asm_trap</code>函数的地址（指针）写入到了<code class="language-plaintext highlighter-rouge">mtvec</code>寄存器中。</p>
  </li>
  <li>
    <p>注册一个事件处理回调函数</p>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">user_handler</span> <span class="o">=</span> <span class="n">handler</span><span class="p">;</span>
</code></pre></div>    </div>

    <p>这个事件处理回调函数是由更上一层的操作系统提供的，在<a href="##实现SYS_yield系统调用问题处理">之后</a>我们再详细介绍她的功能，现在只要知道他是一个函数指针<code class="language-plaintext highlighter-rouge">Context*(*handler)(Event, Context*)</code>，通过给定异常事件类型以及和上下文便可以处理异常事件，并将异常处理的结果写入上下文的寄存器中，方便用户程序得知结果。</p>
  </li>
</ol>

<p>再进一步的我们阅读<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/trap.S</code>中关于<code class="language-plaintext highlighter-rouge">am_asm_trap</code>的代码我们可以看到这个函数</p>

<ol>
  <li>
    <p>创建一段上下文大小的内存空间，并把CPU寄存器的值存入其中。</p>
  </li>
  <li>
    <p>分别将控制状态寄存器读取到一些特定的寄存器，从而将控制状态寄存器的值存入第一步创建的内存空间中，方便后续恢复上下文。</p>
  </li>
  <li>
    <p>将内存空间中保存的上下文作为参数（根据ABI手册规定<code class="language-plaintext highlighter-rouge">a0</code>寄存器是函数传入的第一个参数）交给<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/cte.c</code>中的<code class="language-plaintext highlighter-rouge">__am_irq_handle</code>处理异常。</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">__am_irq_handle</code>函数会根据上下文信息确定事件类型交由操作系统的事件处理函数。</p>

    <p><em>需要说明的是，事件的类型判断本应当与操作系统有关而与AM无关，所以一个更科学的写法是把这事件类型的判断放在<code class="language-plaintext highlighter-rouge">user_handler</code>中完成。</em></p>
  </li>
  <li>
    <p>通过1，2步保存的上下文信息，恢复上下文并返回。</p>
  </li>
</ol>

<h3 id="如何实现异常响应机制">如何实现异常响应机制？</h3>

<ol>
  <li>
    <p>完善<code class="language-plaintext highlighter-rouge">isa_raise_intr</code>的功能，从而成功实现<code class="language-plaintext highlighter-rouge">yield</code>函数的调用。</p>

    <p>通过阅读<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/cte.c</code>中<code class="language-plaintext highlighter-rouge">yield</code>函数的源码我们可以看出来，它首先将<code class="language-plaintext highlighter-rouge">-1</code>这个特殊的异常号存入<code class="language-plaintext highlighter-rouge">a7</code>寄存器中，然后调用<code class="language-plaintext highlighter-rouge">ecall</code>指令。</p>

    <p>根据RISCV手册中规定，<code class="language-plaintext highlighter-rouge">ecall</code>指令会触发异常并进入更高的特权级（如 S 模式或 M 模式）处理系统调用。也就是说<code class="language-plaintext highlighter-rouge">ecall</code>指令应当调用<code class="language-plaintext highlighter-rouge">isa_raise_intr</code>函数，正确的对控制状态寄存器进行赋值后，将<code class="language-plaintext highlighter-rouge">pc</code>移动到<code class="language-plaintext highlighter-rouge">mtvec</code>寄存器中。并且通过观察已经给出的<code class="language-plaintext highlighter-rouge">ebreak</code>指令可以看出，在PA中默认我们在M-Mode，因此<code class="language-plaintext highlighter-rouge">PRIV</code>字段为<code class="language-plaintext highlighter-rouge">0b11</code>，从而我们可以获得对应的<code class="language-plaintext highlighter-rouge">ecall</code>指令码。</p>

    <p>再看<code class="language-plaintext highlighter-rouge">isa_raise_intr</code>，它需要负责对控制状态寄存器进行正确的赋值。那么为了实现这个功能，我们首先得在CPU中创建这样的控制状态寄存器，也就是在<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/isa/riscv32/include/isa-def.h</code>中，更改CPU结构体。并且为了通过DIFFTEST，我们需要在CPU初始化时把<code class="language-plaintext highlighter-rouge">mstatus</code>寄存器赋值位<code class="language-plaintext highlighter-rouge">0x1800</code>。</p>

    <p>通过阅读源码可以看到<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/monitor/monitor.c</code>中调用了<code class="language-plaintext highlighter-rouge">init_isa</code>函数，这个函数在<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/isa/riscv32/init.c</code>中。同时这个函数调用了同文件下的<code class="language-plaintext highlighter-rouge">restart</code>函数完成CPU初始化，在其中对<code class="language-plaintext highlighter-rouge">mstatus</code>寄存器进行更改即可。</p>

    <p>然后通过阅读RISCV手册，我们了解到在<code class="language-plaintext highlighter-rouge">ecall</code>指令调用下，<code class="language-plaintext highlighter-rouge">mcause</code>寄存器需要存入<code class="language-plaintext highlighter-rouge">11</code>，对应<code class="language-plaintext highlighter-rouge">Environment call from M-mode</code>。</p>
  </li>
  <li>
    <p>实现相关指令。通过阅读源码，出现了一些在PA2中未曾实现的指令<code class="language-plaintext highlighter-rouge">ecall</code>、<code class="language-plaintext highlighter-rouge">csrr</code>、<code class="language-plaintext highlighter-rouge">csrw</code>、<code class="language-plaintext highlighter-rouge">mret</code>。这些指令有的涉及到了控制状态寄存器的读写，每个状态控制寄存器的编号，可以通过RISCV手册查询获得。</p>
  </li>
</ol>

<h3 id="如何重新组织context结构体">如何重新组织Context结构体？</h3>

<p>通过查看<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/trap.S</code>中关于<code class="language-plaintext highlighter-rouge">OFFSET</code>的代码，我们知道在开辟的内存空间中要在低位存通用寄存器，高位存控制状态寄存器。</p>

<h2 id="用户程序与系统调用问题解决">用户程序与系统调用问题解决</h2>

<h3 id="如何为nanos-lite实现正确的事件分发问题处理">如何为Nanos-lite实现正确的事件分发问题处理？</h3>

<p>Nanos-lite是一个操作系统，它在<code class="language-plaintext highlighter-rouge">/home/dream/ics2024/nanos-lite/src/irq.c</code>处提供了异常事件的处理函数<code class="language-plaintext highlighter-rouge">do_event</code>，在该函数中对<code class="language-plaintext highlighter-rouge">EVENT_YIELD</code>进行打印处理即可。</p>

<h3 id="堆和栈在哪里">堆和栈在哪里？</h3>

<ul>
  <li>
    <p><strong>堆</strong>：堆用于动态内存分配（如 <code class="language-plaintext highlighter-rouge">malloc</code> 或 <code class="language-plaintext highlighter-rouge">new</code>），其大小和内容在程序运行时才会确定。因为堆的使用是动态的，无法在编译阶段确定其内容或大小，所以无法将堆的内容预先包含在可执行文件中。</p>
  </li>
  <li>
    <p><strong>栈</strong>：栈用于函数调用、局部变量和中断上下文保存，其内容也在程序运行时动态变化。尽管栈的初始位置和大小通常是由编译器或操作系统定义的，但栈内容本身取决于程序的执行流，无法预先包含。</p>
  </li>
</ul>

<h3 id="filesiz与memsiz的区别是什么">FileSiz与MemSiz的区别是什么？</h3>

<p>ELF 文件中的段在加载时可能需要额外的内存分配，导致两者的值不同。主要原因包括：</p>

<ol>
  <li>
    <p>BSS 段</p>

    <p>BSS 段（未初始化数据）在文件中通常不存储实际内容，而是仅在运行时分配所需的内存。由于从<code class="language-plaintext highlighter-rouge">[VirtAddr + FileSiz, VirtAddr + MemSiz)</code><strong>可能对应BSS段存储的那些在内存空间中需要初始化为0的数据</strong>，因此需要清零。</p>

    <p>例子:</p>

    <ul>
      <li>
        <p>一个未初始化的全局变量 <code class="language-plaintext highlighter-rouge">int arr[1000];</code>，占用 4000 字节内存。</p>
      </li>
      <li>
        <p>在 ELF 文件中，BSS 段的 <code class="language-plaintext highlighter-rouge">FileSiz</code> 为 0，因为没有实际数据，但 <code class="language-plaintext highlighter-rouge">MemSiz</code> 为 4000，用于分配运行时内存。</p>
      </li>
    </ul>
  </li>
  <li>
    <p>对齐和填充</p>

    <p>ELF 段通常需要按照内存对齐要求加载，可能会分配额外的空间以满足对齐需求。这些对齐的空白区域不会占用文件存储，但在内存中需要分配。</p>
  </li>
</ol>

<h3 id="loader函数怎么实现">loader函数怎么实现？</h3>

<p>其实和之前的FTRACE实现很像，我们首先得了解ELF文件的结构。</p>

<ol>
  <li>在ELF文件最开头存储了ELF文件头，通过这个文件头我们可以检查ELF魔数，编译ELF文件的指令集，找到程序段。</li>
  <li>我们访问所有程序段，并且通过<code class="language-plaintext highlighter-rouge">PT_LOAD</code>标志判断是否要在运行时载入，并按照ELF文件的要求将这些内容初始化在指定的内存位置，供程序运行时读写。</li>
</ol>

<h3 id="sys_yield系统调用怎么实现">SYS_yield系统调用怎么实现？</h3>

<p>现在我们需要捋一捋系统调用的整个过程：当程序（Navy_app）通过操作系统调用<code class="language-plaintext highlighter-rouge">_syscall_</code>进行系统调用后，该函数通过调用<code class="language-plaintext highlighter-rouge">ecall</code>指令，进而转入NEMU中<code class="language-plaintext highlighter-rouge">isa_raise_intr</code>进行硬件负责的中断处理程序跳转，当NEMU确定好该异常对应的控制状态寄存器后，然后转入AM中将会进行上下文的保存，并进入<code class="language-plaintext highlighter-rouge">__am_irq_handle</code>获得这个异常的事件类型，并将事件交由Nanos中<code class="language-plaintext highlighter-rouge">do_event</code>，这个事件处理回调函数。如果这个事件的类型是系统调用，那么会转入Nanos的<code class="language-plaintext highlighter-rouge">do_syscall</code>中执行一些操作系统级别的指令（例如文件读写等）处理异常。</p>

<p>再回到这道题目本身，我们需要实现<code class="language-plaintext highlighter-rouge">SYS_yield</code>，根据<code class="language-plaintext highlighter-rouge">man syscall</code>我们知道了<code class="language-plaintext highlighter-rouge">a7</code>寄存器存储了系统调用的类型，<code class="language-plaintext highlighter-rouge">a0,a1</code>寄存器分别保存第一返回值和第二返回值。这个系统调用的规范在<code class="language-plaintext highlighter-rouge">$NAVY_APPS_HOME/libs/libos/src/syscall.c</code>的<code class="language-plaintext highlighter-rouge">_syscall_</code>宏定义中被实现了。那根据这个要求在<code class="language-plaintext highlighter-rouge">do_syscall</code>中进行对应的功能实现即可。</p>

<p><em>很令笔者费解的一点在于，为什么既有<code class="language-plaintext highlighter-rouge">EVENT_YIELD</code>又有<code class="language-plaintext highlighter-rouge">SYSCALL_YIELD</code>，感觉好像存在功能的冗余？若有见解，还望广大读者不吝赐教。</em></p>

<h3 id="hello程序是什么-它从而何来-要到哪里去">hello程序是什么, 它从而何来, 要到哪里去？</h3>

<p><code class="language-plaintext highlighter-rouge">hello.c</code> 是一个 C 源文件，存储在磁盘上。当我们使用编译器（如 <code class="language-plaintext highlighter-rouge">gcc</code> 或 <code class="language-plaintext highlighter-rouge">clang</code>）编译它时，生成一个可执行的 ELF 文件（如 <code class="language-plaintext highlighter-rouge">hello</code>）。这个文件仍然在磁盘上，直到被加载到内存。</p>

<p>当我们在操作系统中用loader根据ELF文件信息数据与命令内容文件加载到了内存中的正确区域中。</p>

<p>它的第一条指令由ELF文件指定在<code class="language-plaintext highlighter-rouge">e_entry</code>位置上。这个指针指向<code class="language-plaintext highlighter-rouge">$AM_HOME/am/src/riscv/nemu/start.S</code>的<code class="language-plaintext highlighter-rouge">_start</code>函数。然后被NEMU从该位置从内存中的该位置读取第一条指令并译码顺序执行。</p>

<p>Hello程序打印字符串的过程</p>

<ol>
  <li>用户态的函数调用
<code class="language-plaintext highlighter-rouge">printf("Hello, world!\n") </code>会调用标准库中的 <code class="language-plaintext highlighter-rouge">_write</code> 函数，该函数会调用<code class="language-plaintext highlighter-rouge">write</code>系统调用。
<code class="language-plaintext highlighter-rouge">write</code> 系统调用通过系统调用号和参数向操作系统发起请求。</li>
  <li>系统调用切换到内核态
<code class="language-plaintext highlighter-rouge">write</code> 系统调用切换到内核态（通过 <code class="language-plaintext highlighter-rouge">syscall</code> 指令）。
参数（如文件描述符、缓冲区地址、长度）通过寄存器传递到内核。</li>
  <li>内核处理数据
内核根据文件描述符（<code class="language-plaintext highlighter-rouge">FD_STDOUT</code>，值为 1）识别终端设备。
将用户缓冲区中的字符串数据拷贝到NEMU模拟的串口驱动程序<code class="language-plaintext highlighter-rouge">putch</code>。</li>
  <li>驱动程序输出字符
字符可能通过<code class="language-plaintext highlighter-rouge">putch</code>发送到屏幕。</li>
  <li>用户看到结果
最终，字符串被显示在终端窗口或硬件屏幕上。</li>
</ol>

<h2 id="文件系统问题处理">文件系统问题处理</h2>

<h3 id="如何实现如sbrk-open-close-gettimeofday等系统调用">如何实现如sbrk, open, close, gettimeofday等系统调用？</h3>

<p>这些系统调用直接查看手册，根据规范实现即可，如果需要调动外设，通过AM定义好的函数接口调用。</p>

<p>关于文件系统的实现，一定要注意好在每次读入文件时，<strong>文件指针的初始化</strong>，忘记将其归位为0可能导致一些BUG！并且可以关于其中虚拟文件系统的设计思想非常有参考意义，和程序设计中的多态非常像，对读写行为进行了很好抽象。</p>

<h2 id="精彩纷呈的应用程序问题处理">精彩纷呈的应用程序问题处理</h2>

<h3 id="之后的关于一些vga和键盘事件的实现还有一些app的怎么实现">之后的关于一些VGA和键盘事件的实现，还有一些APP的怎么实现？</h3>

<p>笔者完成了VGA和键盘事件的实现，在VGA的实现过程中需要去阅读SDL的源码，完整的复刻其行为才能使得程序正确运行。在最后一章节的APP实现中，感觉与ICS的内容核心有所分离，没那么偏向于系统的模拟与实现，且需要耗费大量时间，因此从Flappy Bird开始的所有APP均未实现。</p>

<h2 id="源码">源码</h2>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* cte.c 粘一些代表性的，不全粘贴 */</span> 
<span class="n">Context</span><span class="o">*</span> <span class="nf">__am_irq_handle</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">c</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">user_handler</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Event</span> <span class="n">ev</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
    <span class="k">switch</span> <span class="p">(</span><span class="n">c</span><span class="o">-&gt;</span><span class="n">mcause</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">case</span> <span class="mi">11</span><span class="p">:</span> 
        <span class="k">if</span> <span class="p">(</span><span class="n">c</span><span class="o">-&gt;</span><span class="n">gpr</span><span class="p">[</span><span class="mi">17</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>  <span class="c1">// check a7 value</span>
          <span class="n">ev</span><span class="p">.</span><span class="n">event</span> <span class="o">=</span> <span class="n">EVENT_YIELD</span><span class="p">;</span>
        <span class="k">else</span> 
          <span class="n">ev</span><span class="p">.</span><span class="n">event</span> <span class="o">=</span> <span class="n">EVENT_SYSCALL</span><span class="p">;</span>
        <span class="n">c</span><span class="o">-&gt;</span><span class="n">mepc</span> <span class="o">+=</span> <span class="mi">4</span><span class="p">;</span>
        <span class="k">break</span><span class="p">;</span>
      <span class="nl">default:</span> <span class="n">ev</span><span class="p">.</span><span class="n">event</span> <span class="o">=</span> <span class="n">EVENT_ERROR</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">user_handler</span><span class="p">(</span><span class="n">ev</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">c</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="n">c</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* syscall.c 粘一些代表性的，不全粘贴 */</span> 
<span class="kt">void</span> <span class="nf">do_syscall</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">c</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uintptr_t</span> <span class="n">a</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
  <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPR1</span><span class="p">;</span>
  <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPR2</span><span class="p">;</span>
  <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPR3</span><span class="p">;</span>
  <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPR4</span><span class="p">;</span>
  
  <span class="c1">// int i;</span>
  <span class="c1">// printf("\n%-10s\t%-10s\t%s\n", "REG_NAME", "HEX_VALUE", "DEC_VALUE");</span>
  <span class="c1">// for (i = 0; i &lt; 32; ++i) {</span>
  <span class="c1">//   printf("%-10s\t%#010x\t%-12u\n", "", c-&gt;gpr[i], c-&gt;gpr[i]);</span>
  <span class="c1">// }</span>
  <span class="c1">// printf("%-10s\t%#010x\t%-12u\n", "mstatus", c-&gt;mstatus, c-&gt;mstatus);</span>
  <span class="c1">// printf("%-10s\t%#010x\t%-12u\n", "mcause", c-&gt;mcause, c-&gt;mcause);</span>
  <span class="c1">// printf("%-10s\t%#010x\t%-12u\n", "mepc", c-&gt;mepc, c-&gt;mepc);</span>

  <span class="k">switch</span> <span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span>
    <span class="k">case</span> <span class="n">SYS_exit</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: exit"</span><span class="p">);</span> <span class="n">halt</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_yield</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: yield"</span><span class="p">);</span> <span class="n">yield</span><span class="p">();</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_open</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: open"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">fs_open</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_read</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: read"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">fs_read</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_write</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: write"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">fs_write</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_lseek</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: lseek"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">fs_lseek</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_close</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: close"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">fs_close</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SYS_brk</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: brk"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// fail return -1</span>
    <span class="k">case</span> <span class="n">SYS_gettimeofday</span><span class="p">:</span> <span class="k">if</span> <span class="p">(</span><span class="n">SYS_DEBUG</span><span class="p">)</span> <span class="n">Log</span><span class="p">(</span><span class="s">"Syscall: gettimeofday"</span><span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">GPRx</span> <span class="o">=</span> <span class="n">sys_gettimeofday</span><span class="p">((</span><span class="k">struct</span> <span class="n">timeval</span> <span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="k">struct</span> <span class="n">timezone</span> <span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span> <span class="k">break</span><span class="p">;</span>
    <span class="nl">default:</span> <span class="n">panic</span><span class="p">(</span><span class="s">"Unhandled syscall ID = %d"</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
  <span class="p">}</span>

<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* inst.c 粘一些代表性的，不全粘贴 */</span> 

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 001 ????? 11100 11"</span><span class="p">,</span> <span class="n">csrrw</span>  <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">rd</span><span class="o">?</span> <span class="p">(</span><span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">CSR</span><span class="p">(</span><span class="n">imm</span><span class="p">))</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span> <span class="n">CSR</span><span class="p">(</span><span class="n">imm</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 010 ????? 11100 11"</span><span class="p">,</span> <span class="n">csrrs</span>  <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">CSR</span><span class="p">(</span><span class="n">imm</span><span class="p">);</span> <span class="n">src1</span><span class="o">?</span> <span class="p">(</span><span class="n">CSR</span><span class="p">(</span><span class="n">imm</span><span class="p">)</span> <span class="o">|=</span> <span class="n">src1</span><span class="p">)</span> <span class="o">:</span> <span class="mi">0</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 00000 00000 000 00000 11100 11"</span><span class="p">,</span> <span class="n">ecall</span>  <span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="n">isa_raise_intr</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">));</span> <span class="c1">// Environment call from M-mode</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 00001 00000 000 00000 11100 11"</span><span class="p">,</span> <span class="n">ebreak</span> <span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">NEMUTRAP</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="mi">10</span><span class="p">)));</span> <span class="c1">// R(10) is $a0</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0011000 00010 00000 000 00000 11100 11"</span><span class="p">,</span> <span class="n">mret</span>   <span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="n">CSR</span><span class="p">(</span><span class="mh">0x341</span><span class="p">));</span> <span class="c1">// Get return address from 0x341</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* fs.c 粘一些代表性的，不全粘贴 */</span> 

<span class="k">static</span> <span class="n">Finfo</span> <span class="n">file_table</span><span class="p">[]</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">used</span><span class="p">))</span> <span class="o">=</span> <span class="p">{</span>
  <span class="p">[</span><span class="n">FD_STDIN</span><span class="p">]</span>  <span class="o">=</span> <span class="p">{</span><span class="s">"stdin"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">invalid_read</span><span class="p">,</span> <span class="n">serial_write</span><span class="p">},</span>
  <span class="p">[</span><span class="n">FD_STDOUT</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s">"stdout"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">invalid_read</span><span class="p">,</span> <span class="n">serial_write</span><span class="p">},</span>
  <span class="p">[</span><span class="n">FD_STDERR</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s">"stderr"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">invalid_read</span><span class="p">,</span> <span class="n">invalid_write</span><span class="p">},</span>
  <span class="p">[</span><span class="n">FD_EVENTS</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s">"/dev/events"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">events_read</span><span class="p">,</span> <span class="n">invalid_write</span><span class="p">},</span>
  <span class="p">[</span><span class="n">FD_FB</span><span class="p">]</span>     <span class="o">=</span> <span class="p">{</span><span class="s">"/dev/fb"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">invalid_read</span><span class="p">,</span> <span class="n">fb_write</span><span class="p">},</span>
  <span class="p">{</span><span class="s">"/proc/dispinfo"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">dispinfo_read</span><span class="p">,</span> <span class="n">invalid_write</span> <span class="p">},</span>
<span class="cp">#include</span> <span class="cpf">"files.h"</span><span class="cp">
</span><span class="p">};</span>

<span class="kt">void</span> <span class="nf">init_fs</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// initialize the size of /dev/fb</span>
  <span class="n">AM_GPU_CONFIG_T</span> <span class="n">gpu_config</span> <span class="o">=</span> <span class="n">io_read</span><span class="p">(</span><span class="n">AM_GPU_CONFIG</span><span class="p">);</span>
  <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="n">gpu_config</span><span class="p">.</span><span class="n">width</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">height</span> <span class="o">=</span> <span class="n">gpu_config</span><span class="p">.</span><span class="n">height</span><span class="p">;</span>
  <span class="n">file_table</span><span class="p">[</span><span class="n">FD_FB</span><span class="p">].</span><span class="n">size</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">height</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint32_t</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">fs_open</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pathname</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mode</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">file_table</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">file_table</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="n">file_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">name</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">file_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="k">return</span> <span class="n">i</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">fs_read</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">nread</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">read</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
    <span class="n">nread</span> <span class="o">=</span> <span class="n">ramdisk_read</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">disk_offset</span> <span class="o">+</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="k">else</span>
    <span class="n">nread</span> <span class="o">=</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">read</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">disk_offset</span> <span class="o">+</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">!=</span> <span class="n">FD_STDIN</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">=</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">+</span> <span class="n">nread</span> <span class="o">&gt;</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span> <span class="o">?</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span> <span class="o">:</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">+</span> <span class="n">nread</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">nread</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">fs_write</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">nwrite</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">write</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
    <span class="n">nwrite</span> <span class="o">=</span> <span class="n">ramdisk_write</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">disk_offset</span> <span class="o">+</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="k">else</span>
    <span class="n">nwrite</span> <span class="o">=</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">write</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">disk_offset</span> <span class="o">+</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">!=</span> <span class="n">FD_STDOUT</span> <span class="o">&amp;&amp;</span> <span class="n">fd</span> <span class="o">!=</span> <span class="n">FD_STDERR</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">=</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">+</span> <span class="n">nwrite</span> <span class="o">&gt;</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span> <span class="o">?</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span> <span class="o">:</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">+</span> <span class="n">nwrite</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">fd</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">nwrite</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">fs_lseek</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">int</span> <span class="n">whence</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">switch</span> <span class="p">(</span><span class="n">whence</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">case</span> <span class="n">SEEK_SET</span><span class="p">:</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">=</span> <span class="n">offset</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SEEK_CUR</span><span class="p">:</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">+=</span> <span class="n">offset</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">SEEK_END</span><span class="p">:</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">=</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span> <span class="o">+</span> <span class="n">offset</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
    <span class="nl">default:</span> <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">&gt;</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">size</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Log</span><span class="p">(</span><span class="s">"fs_lseek: offset out of range"</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">file_table</span><span class="p">[</span><span class="n">fd</span><span class="p">].</span><span class="n">open_offset</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">fs_close</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* loader.c 粘一些代表性的，不全粘贴 */</span> 

<span class="k">static</span> <span class="kt">uintptr_t</span> <span class="nf">loader</span><span class="p">(</span><span class="n">PCB</span> <span class="o">*</span><span class="n">pcb</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">fs_open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to open file %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">filename</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">Elf_Ehdr</span> <span class="n">ehdr</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fs_read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ehdr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Elf_Ehdr</span><span class="p">))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read ELF header</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">memcmp</span><span class="p">(</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_ident</span><span class="p">,</span> <span class="n">ELFMAG</span><span class="p">,</span> <span class="n">SELFMAG</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"Not an ELF file</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_machine</span> <span class="o">!=</span> <span class="n">EXPECT_TYPE</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"Not an ELF file of target ISA</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">Elf_Phdr</span> <span class="n">phdr</span><span class="p">[</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_phnum</span><span class="p">];</span>
  <span class="n">fs_lseek</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_phoff</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fs_read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">phdr</span><span class="p">,</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_phnum</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Elf_Phdr</span><span class="p">))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read program headers</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_phnum</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_type</span> <span class="o">==</span> <span class="n">PT_LOAD</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">fs_lseek</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_offset</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">fs_read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_vaddr</span><span class="p">,</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_filesz</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
              <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read segment %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
              <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_filesz</span> <span class="o">&lt;</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_memsz</span><span class="p">)</span> <span class="p">{</span>
              <span class="n">memset</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_vaddr</span> <span class="o">+</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_filesz</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_memsz</span> <span class="o">-</span> <span class="n">phdr</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">p_filesz</span><span class="p">);</span>
          <span class="p">}</span>
      <span class="p">}</span>
  <span class="p">}</span>
  <span class="n">fs_close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_entry</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* device.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">int</span> <span class="nf">sys_gettimeofday</span><span class="p">(</span><span class="k">struct</span> <span class="n">timeval</span> <span class="o">*</span><span class="n">tv</span><span class="p">,</span> <span class="k">struct</span> <span class="n">timezone</span> <span class="o">*</span><span class="n">tz</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint64_t</span> <span class="n">us</span> <span class="o">=</span> <span class="n">io_read</span><span class="p">(</span><span class="n">AM_TIMER_UPTIME</span><span class="p">).</span><span class="n">us</span><span class="p">;</span>
  <span class="n">tv</span><span class="o">-&gt;</span><span class="n">tv_sec</span> <span class="o">=</span> <span class="n">us</span> <span class="o">/</span> <span class="mi">1000000</span><span class="p">;</span>
  <span class="n">tv</span><span class="o">-&gt;</span><span class="n">tv_usec</span> <span class="o">=</span> <span class="n">us</span> <span class="o">%</span> <span class="mi">1000000</span><span class="p">;</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">serial_write</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">putch</span><span class="p">(((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buf</span> <span class="o">+</span> <span class="n">offset</span><span class="p">)[</span><span class="n">i</span><span class="p">]);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">len</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">events_read</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">AM_INPUT_KEYBRD_T</span> <span class="n">kb</span> <span class="o">=</span> <span class="n">io_read</span><span class="p">(</span><span class="n">AM_INPUT_KEYBRD</span><span class="p">);</span>
  <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">snprintf</span><span class="p">((</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"%s %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">kb</span><span class="p">.</span><span class="n">keydown</span> <span class="o">?</span> <span class="s">"kd"</span> <span class="o">:</span> <span class="s">"ku"</span><span class="p">,</span> <span class="n">keyname</span><span class="p">[</span><span class="n">kb</span><span class="p">.</span><span class="n">keycode</span><span class="p">]);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">kb</span><span class="p">.</span><span class="n">keycode</span> <span class="o">==</span> <span class="n">AM_KEY_NONE</span><span class="p">)</span>
    <span class="n">nread</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">return</span> <span class="n">nread</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">dispinfo_read</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">AM_GPU_CONFIG_T</span> <span class="n">gpu_config</span> <span class="o">=</span> <span class="n">io_read</span><span class="p">(</span><span class="n">AM_GPU_CONFIG</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">snprintf</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"WIDTH: %d</span><span class="se">\n</span><span class="s">HEIGHT: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">gpu_config</span><span class="p">.</span><span class="n">width</span><span class="p">,</span> <span class="n">gpu_config</span><span class="p">.</span><span class="n">height</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">size_t</span> <span class="nf">fb_write</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">AM_GPU_CONFIG_T</span> <span class="n">gpu_config</span> <span class="o">=</span> <span class="n">io_read</span><span class="p">(</span><span class="n">AM_GPU_CONFIG</span><span class="p">);</span>
  <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="n">gpu_config</span><span class="p">.</span><span class="n">width</span><span class="p">;</span>
 
  <span class="n">offset</span> <span class="o">/=</span> <span class="mi">4</span><span class="p">;</span>
  <span class="n">len</span> <span class="o">/=</span> <span class="mi">4</span><span class="p">;</span>
 
  <span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="n">offset</span> <span class="o">/</span> <span class="n">width</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">offset</span> <span class="o">%</span> <span class="n">width</span><span class="p">;</span>
 
  <span class="n">io_write</span><span class="p">(</span><span class="n">AM_GPU_FBDRAW</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
 
  <span class="k">return</span> <span class="n">len</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* fixdptc.h 粘一些代表性的，不全粘贴 */</span> 

<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_muli</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">,</span> <span class="kt">int</span> <span class="n">B</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">A</span> <span class="o">*</span> <span class="n">B</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/* Divides a fixedpt number with an integer, returns the result. */</span>
<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_divi</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">,</span> <span class="kt">int</span> <span class="n">B</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">A</span> <span class="o">/</span> <span class="n">B</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/* Multiplies two fixedpt numbers, returns the result. */</span>
<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_mul</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">,</span> <span class="n">fixedpt</span> <span class="n">B</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">A</span> <span class="o">*</span> <span class="p">(</span><span class="n">B</span> <span class="o">&gt;&gt;</span> <span class="n">FIXEDPT_FBITS</span><span class="p">);</span>
<span class="p">}</span>


<span class="cm">/* Divides two fixedpt numbers, returns the result. */</span>
<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_div</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">,</span> <span class="n">fixedpt</span> <span class="n">B</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">A</span> <span class="o">/</span> <span class="p">(</span><span class="n">B</span> <span class="o">&gt;&gt;</span> <span class="n">FIXEDPT_FBITS</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_abs</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">A</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="o">-</span><span class="n">A</span> <span class="o">:</span> <span class="n">A</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_floor</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">fixedpt_fracpart</span><span class="p">(</span><span class="n">A</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">A</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">A</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">A</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">FIXEDPT_FMASK</span><span class="p">;</span>
	<span class="k">else</span> <span class="k">return</span> <span class="p">(</span><span class="n">A</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">FIXEDPT_FMASK</span><span class="p">)</span> <span class="o">-</span> <span class="n">FIXEDPT_ONE</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kr">inline</span> <span class="n">fixedpt</span> <span class="nf">fixedpt_ceil</span><span class="p">(</span><span class="n">fixedpt</span> <span class="n">A</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">fixedpt_fracpart</span><span class="p">(</span><span class="n">A</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">A</span><span class="p">;</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">A</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="p">(</span><span class="n">A</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">FIXEDPT_FMASK</span><span class="p">)</span> <span class="o">+</span> <span class="n">FIXEDPT_ONE</span><span class="p">;</span>
	<span class="k">else</span> <span class="k">return</span> <span class="n">A</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">FIXEDPT_FMASK</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* event.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">int</span> <span class="nf">SDL_PollEvent</span><span class="p">(</span><span class="n">SDL_Event</span> <span class="o">*</span><span class="n">ev</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">NDL_PollEvent</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">)))</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="n">type</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
    <span class="kt">char</span> <span class="n">key</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">sscanf</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="s">"%s %s"</span><span class="p">,</span> <span class="n">type</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">ev</span><span class="o">-&gt;</span><span class="n">key</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="s">"kd"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="n">SDL_KEYDOWN</span> <span class="o">:</span> <span class="n">SDL_KEYUP</span><span class="p">;</span>
      <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">keyname</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">keyname</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">keyname</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">ev</span><span class="o">-&gt;</span><span class="n">key</span><span class="p">.</span><span class="n">keysym</span><span class="p">.</span><span class="n">sym</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
          <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">SDL_WaitEvent</span><span class="p">(</span><span class="n">SDL_Event</span> <span class="o">*</span><span class="n">event</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ret</span> <span class="o">=</span> <span class="n">SDL_PollEvent</span><span class="p">(</span><span class="n">event</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="n">ret</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* NDL.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">uint32_t</span> <span class="nf">NDL_GetTicks</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// return the time in milliseconds</span>
  <span class="n">assert</span><span class="p">(</span><span class="n">gettimeofday</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">tv</span><span class="p">.</span><span class="n">tv_sec</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o">+</span> <span class="n">tv</span><span class="p">.</span><span class="n">tv_usec</span> <span class="o">/</span> <span class="mi">1000</span> <span class="o">-</span> <span class="n">start_time</span><span class="p">;</span>

<span class="p">}</span>

<span class="kt">int</span> <span class="nf">NDL_PollEvent</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/dev/events"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="n">assert</span><span class="p">(</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">nread</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">NDL_OpenCanvas</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">w</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">h</span><span class="p">)</span> <span class="p">{</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">getenv</span><span class="p">(</span><span class="s">"NWM_APP"</span><span class="p">))</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">fbctl</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
    <span class="n">fbdev</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
    <span class="n">screen_w</span> <span class="o">=</span> <span class="o">*</span><span class="n">w</span><span class="p">;</span> <span class="n">screen_h</span> <span class="o">=</span> <span class="o">*</span><span class="n">h</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">sprintf</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="s">"%d %d"</span><span class="p">,</span> <span class="n">screen_w</span><span class="p">,</span> <span class="n">screen_h</span><span class="p">);</span>
    <span class="c1">// let NWM resize the window and create the frame buffer</span>
    <span class="n">write</span><span class="p">(</span><span class="n">fbctl</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
    <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// 3 = evtdev</span>
      <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">nread</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
      <span class="n">buf</span><span class="p">[</span><span class="n">nread</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="s">"mmap ok"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">close</span><span class="p">(</span><span class="n">fbctl</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">canvas_h</span> <span class="o">=</span> <span class="o">*</span><span class="n">h</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">canvas_h</span> <span class="o">&gt;</span> <span class="n">screen_h</span> <span class="o">?</span> <span class="n">screen_h</span> <span class="o">:</span> <span class="o">*</span><span class="n">h</span><span class="p">;</span>
    <span class="n">canvas_w</span> <span class="o">=</span> <span class="o">*</span><span class="n">w</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">canvas_w</span> <span class="o">&gt;</span> <span class="n">screen_w</span> <span class="o">?</span> <span class="n">screen_w</span> <span class="o">:</span> <span class="o">*</span><span class="n">w</span><span class="p">;</span>
    <span class="o">*</span><span class="n">h</span> <span class="o">=</span> <span class="n">canvas_h</span><span class="p">;</span>
    <span class="o">*</span><span class="n">w</span> <span class="o">=</span> <span class="n">canvas_w</span><span class="p">;</span>
    <span class="n">canvas_x</span> <span class="o">=</span> <span class="p">(</span><span class="n">screen_w</span> <span class="o">-</span> <span class="n">canvas_w</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
    <span class="n">canvas_y</span> <span class="o">=</span> <span class="p">(</span><span class="n">screen_h</span> <span class="o">-</span> <span class="n">canvas_h</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">NDL_DrawRect</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="n">pixels</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="kt">int</span> <span class="n">w</span><span class="p">,</span> <span class="kt">int</span> <span class="n">h</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">w</span> <span class="o">=</span> <span class="n">w</span> <span class="o">?</span> <span class="n">w</span> <span class="o">:</span> <span class="n">canvas_w</span><span class="p">;</span>
  <span class="n">h</span> <span class="o">=</span> <span class="n">h</span> <span class="o">?</span> <span class="n">h</span> <span class="o">:</span> <span class="n">canvas_h</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/dev/fb"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">h</span> <span class="o">&amp;&amp;</span> <span class="n">y</span> <span class="o">+</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">canvas_h</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">lseek</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="p">((</span><span class="n">y</span> <span class="o">+</span> <span class="n">canvas_y</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">*</span> <span class="n">screen_w</span> <span class="o">+</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">canvas_x</span><span class="p">))</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint32_t</span><span class="p">),</span> <span class="n">SEEK_SET</span><span class="p">);</span>
    <span class="n">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">pixels</span> <span class="o">+</span> <span class="n">i</span> <span class="o">*</span> <span class="n">w</span><span class="p">,</span>  <span class="p">(</span><span class="n">w</span> <span class="o">&lt;</span> <span class="n">canvas_w</span> <span class="o">-</span> <span class="n">x</span> <span class="o">?</span> <span class="n">w</span> <span class="o">:</span> <span class="n">canvas_w</span> <span class="o">-</span> <span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint32_t</span><span class="p">));</span>
  <span class="p">}</span>
  <span class="n">assert</span><span class="p">(</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>

<span class="p">}</span>

<span class="kt">int</span> <span class="nf">NDL_Init</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">flags</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">getenv</span><span class="p">(</span><span class="s">"NWM_APP"</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">evtdev</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/proc/dispinfo"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
  <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
  <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">nread</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">buf</span><span class="p">[</span><span class="n">nread</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">':'</span><span class="p">)</span> <span class="o">++</span><span class="n">i</span><span class="p">;</span>
    <span class="n">screen_w</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">buf</span> <span class="o">+</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="o">++</span><span class="n">i</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">':'</span><span class="p">)</span> <span class="o">++</span><span class="n">i</span><span class="p">;</span>
    <span class="n">screen_h</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">buf</span> <span class="o">+</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="n">gettimeofday</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
  <span class="n">start_time</span> <span class="o">=</span> <span class="n">tv</span><span class="p">.</span><span class="n">tv_sec</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o">+</span> <span class="n">tv</span><span class="p">.</span><span class="n">tv_usec</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">;</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="ICS" /><summary type="html"><![CDATA[记录了在RISC-V架构下实现异常响应机制、系统调用和文件系统的过程，包括NEMU模拟器的扩展、AM抽象层的异常处理以及Nanos-lite操作系统的系统调用实现，并分析了ELF加载和程序执行流程。]]></summary></entry><entry><title type="html">NJU ICS2024 PA 作业心得（一）</title><link href="https://resume.dreamw1ngs.com/posts/2024/09/15/ics-pa1/" rel="alternate" type="text/html" title="NJU ICS2024 PA 作业心得（一）" /><published>2024-09-15T00:00:00+00:00</published><updated>2024-09-15T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2024/09/15/blog-post-ics-pa1</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2024/09/15/ics-pa1/"><![CDATA[<blockquote>
  <p>由于自己并不是NJU 2024的学生，因此“堂而皇之”的把这份心得发在了网上，并且只是仅供<strong>非以此课程作为自己当前学年保研课</strong>的同学参考。如若这是你的目前正在进修的保研课程，请速速关闭此网页！！！</p>
</blockquote>

<h2 id="序幕工具的准备">序幕（工具的准备）</h2>

<p>【该章节只在PA1中出现】由于PA0涉及简单的系统安装与环境配置，因此并不打算单独写一个心得博客。但自己在过程中也使用了一些好用的小工具，在此分享一下。</p>

<h3 id="vscode-but-not-vim"><strong>Vscode</strong> but not Vim.</h3>

<p>对不起Vim，我知道你是神，但我真的不会用。Vscode真的太好用了，有GUI，有那么多好用的插件，甚至背景都能自定义，我太爱他（bushi</p>

<h3 id="clangd">clangd</h3>

<p><code class="language-plaintext highlighter-rouge">clangd</code>是一个开源的语言服务器，可以配合<a href="https://github.com/nickdiego/compiledb">CompileDB项目</a>生成compile_commands.json（所有符号表索引数据库），方便只参与编译的文件代码进行快速跳转。
具体食用方式：</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">pip3 install compiledb</code> 安装compiledb。</li>
  <li>在<code class="language-plaintext highlighter-rouge">NEMU_PATH</code>下运行<code class="language-plaintext highlighter-rouge">compiledb make</code>，在<code class="language-plaintext highlighter-rouge">NEMU_PATH</code>下生成<code class="language-plaintext highlighter-rouge">compile_commands.json</code>文件。</li>
  <li>在自己的环境中使用<code class="language-plaintext highlighter-rouge">apt-get install clangd</code>安装clangd</li>
  <li>vscode安装clangd插件后，设置<code class="language-plaintext highlighter-rouge">--compile-commands-dir=nemu</code>。这样会找到你vscode工作目录下<code class="language-plaintext highlighter-rouge">nemu</code>目录里的<code class="language-plaintext highlighter-rouge">compile_commands.json</code></li>
</ol>

<p>然后就可以快乐的通过这种方式找到一堆之前使用C++插件找不到的宏定义啦</p>

<h3 id="codelldb">CodeLLDB</h3>

<p>这个项目太需要Debug了，我们使用lldb作为调试工具（当然也可以使用gdb）。</p>

<p>具体食用方式：</p>

<ol>
  <li>
    <p>在自己的环境中使用<code class="language-plaintext highlighter-rouge">apt-get install lldb</code>安装lldb</p>
  </li>
  <li>
    <p>vscode安装CodeLLDB插件</p>
  </li>
  <li>
    <p>在<code class="language-plaintext highlighter-rouge">Run and Debug</code>功能下修改配置文件<code class="language-plaintext highlighter-rouge">launch.json</code>，添加如下配置</p>

    <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"configurations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
           
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: gcc build and debug active file"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lldb"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"request"</span><span class="p">:</span><span class="w"> </span><span class="s2">"launch"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"program"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${workspaceFolder}/nemu/build/riscv32-nemu-interpreter"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
            </span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${workspaceFolder}/nemu"</span><span class="p">,</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: gcc build and debug current file"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lldb"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"request"</span><span class="p">:</span><span class="w"> </span><span class="s2">"launch"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"program"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${fileDirname}/${fileBasenameNoExtension}"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
            </span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${workspaceFolder}/nemu"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"preLaunchTask"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: gcc build active file"</span><span class="p">,</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.0.0"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
</ol>

<h3 id="gitlens--git-graph">GitLens &amp; Git Graph</h3>

<p>GitLens可以方便的让你在编辑器中看到上一次commit的提交情况。</p>

<p>Git Graph可以方便的让你看到git log信息，查看方式是在点击<code class="language-plaintext highlighter-rouge">Sys Control</code>功能后单击最右边的小图标<code class="language-plaintext highlighter-rouge">View git graph</code>。</p>

<h3 id="wakatime">WakaTime</h3>

<p>记录你的项目时长，统计通关时间。在注册账户后找到个人token，在vscode通过<code class="language-plaintext highlighter-rouge">ctrl+shift+P</code>找到<code class="language-plaintext highlighter-rouge">WakaTime: Api Key</code>，在提示内填入即可。</p>

<h2 id="rtfsc问题处理">RTFSC问题处理</h2>

<h3 id="宏的工作原理">宏的工作原理</h3>

<p>C语言中的宏（Macro）是预处理指令，由预处理器在实际编译之前处理。宏的工作原理主要包括文本替换、条件编译和文件包含等功能。</p>

<p>对象宏基本上是一个简单的替换。预处理器会在编译代码之前将所有宏名替换为宏定义中的内容。例如：</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define PI 3.14159
</span></code></pre></div></div>

<p>函数宏允许宏定义带有参数，这使得宏的替换可以根据参数动态变化。函数宏在形式上类似于函数，但在实际处理上仍然是文本替换。例如：</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define SQUARE(x) ((x) * (x))
</span></code></pre></div></div>

<p>宏还常用于条件编译，根据不同的编译条件包含或排除代码块。例如：</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifdef DEBUG
</span>    <span class="n">printf</span><span class="p">(</span><span class="s">"Debug information</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="cp">#endif
</span></code></pre></div></div>

<h3 id="parse_args参数哪里来">parse_args参数哪里来？</h3>

<p>从main的参数直接传递而来，argc是命令行参数的数量，argv是一个常量字符串数组的地址。</p>

<h3 id="处理assert报错">处理assert报错</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[src/monitor/monitor.c:20 welcome] Exercise: Please remove me in the source code and compile NEMU again.
riscv32-nemu-interpreter: src/monitor/monitor.c:21: welcome: Assertion `0' failed.
</code></pre></div></div>

<p>通过报错信息可以定位错误在<code class="language-plaintext highlighter-rouge">src/monitor/monitor.c</code>文件21行，删去<code class="language-plaintext highlighter-rouge">assert(0)</code>即可</p>

<h3 id="cmd_c为什么传入-1">cmd_c为什么传入-1</h3>

<p>因为此时用户的目的是继续执行程序，执行多少步是未知的，所以期望下程序会执行无限步直至CPU进入停止状态。为了无限步执行，所以这里需要传入一个参数的最大值。由于在NEMU中，参数是uint32_t类型，所以其最大值是全1二进制串，对应为int32的-1。</p>

<h2 id="基础设施问题处理">基础设施问题处理</h2>

<p>没有什么难度，按照需求实现即可。注意我们在RTFSC部分已经了解到</p>

<blockquote>
  <p>内存通过在<code class="language-plaintext highlighter-rouge">nemu/src/memory/paddr.c</code>中定义的大数组<code class="language-plaintext highlighter-rouge">pmem</code>来模拟. 在客户程序运行的过程中, 总是使用<code class="language-plaintext highlighter-rouge">vaddr_read()</code>和<code class="language-plaintext highlighter-rouge">vaddr_write()</code> (在<code class="language-plaintext highlighter-rouge">nemu/src/memory/vaddr.c</code>中定义)来访问模拟的内存. vaddr, paddr分别代表虚拟地址和物理地址。</p>
</blockquote>

<p>所以在实现扫描内存时，要用到<code class="language-plaintext highlighter-rouge">vaddr_read</code>参数，当然为了打印的好看，我们可以设置一下格式化字符串给出列名，并打印制定的长度，详情参考<a href="https://zh.wikipedia.org/wiki/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2">wiki百科</a>。</p>

<h2 id="表达式求值问题处理">表达式求值问题处理</h2>

<h3 id="如何进行词法分析">如何进行词法分析</h3>

<p>详情请参考<a href="https://www.runoob.com/regexp/regexp-syntax.html">正则表达式</a>，构建正确的正则表达式并分别给予对应的type。</p>

<p><em>第一个坑点在于，<code class="language-plaintext highlighter-rouge">regex.h</code>这个C库提供的正则表达式不包含<code class="language-plaintext highlighter-rouge">\d</code>，<code class="language-plaintext highlighter-rouge">\s</code>这样的元字符，所以找数字时需要用<code class="language-plaintext highlighter-rouge">[0-9]</code>等方式代替。</em></p>

<p><em>第二个坑点在于，由于单token长度最大可以超过32，所以记得处理数字过长导致超过uint32_t表示范围的情况（至少打印一个warning），方便之后找到BUG原因。u_int32最大值约为4e9，即十进制表示10位，十六进制表示8位。</em></p>

<h3 id="如何实现简单的计算功能">如何实现简单的计算功能</h3>

<p>一般我们实现计算功能的方式是通过栈内外优先级的方式，但是讲义通过BNF表达式，给出了一个递归式的求值框架，我们对他进行分析</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">eval</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* Bad expression */</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">==</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* Single token.
     * For now this token should be a number.
     * Return the value of the number.
     */</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">check_parentheses</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span> <span class="o">==</span> <span class="nb">true</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* The expression is surrounded by a matched pair of parentheses.
     * If that is the case, just throw away the parentheses.
     */</span>
    <span class="k">return</span> <span class="n">eval</span><span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="cm">/* We should do more things here. */</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ol>
  <li>
    <p>我们从后向前探索这个框架，先看最后一个else条件框。它代表了一个普通表达式，我们如果想要分治求解，就需要将普通表达式，抽象成<code class="language-plaintext highlighter-rouge">&lt;expr&gt; &lt;operator&gt; &lt;expr&gt;</code>的形式，将两个<code class="language-plaintext highlighter-rouge">&lt;expr&gt;</code>递归求值，由于我们知道分治的合并过程需要在<code class="language-plaintext highlighter-rouge">&lt;expr&gt;</code>计算之后才能进行，因此为了满足原表达式的计算规则，<code class="language-plaintext highlighter-rouge">&lt;operator&gt;</code>必须是其中<strong>优先级最低</strong>的运算符，这样才能保证在合并过程中该运算符被最后运算。</p>

    <p>在<a href="https://blog.csdn.net/qq_43432875/article/details/102515831">利用栈的算法</a>中，我们将括号也视为一种运算符，利用栈内外优先级的方法轻松解决了括号的问题，但此时栈内外优先级是相同的，我们如何处理括号呢？在遇到左括号时，要把与之匹配的右括号构成的<strong>合法括号内的表达式看作一个整体</strong>，由于括号内计算优先级最高，所以寻找匹配有括号过程中不要记录该部分的运算符优先级。如若我们无法找到合法括号，那意味着表达式不合法，需要及时中断。</p>
  </li>
  <li>
    <p>在上一步我们只是将合法括号表达式看作一个整体交由函数递归处理。函数现在仍然无法处理括号，所以我们需要一个检测算法，将最外层可以被去除且不影响表达式内部合法性的括号去除，这是因为<code class="language-plaintext highlighter-rouge">&lt;expr&gt; ::= "(" &lt;expr&gt; ")"</code>。</p>
  </li>
  <li>
    <p>如果$p=q$那么此时一定只剩余一个运算数，即<code class="language-plaintext highlighter-rouge">&lt;expr&gt; ::= &lt;number&gt;</code>，我们根据这个运算数的数据类型将其转化成<code class="language-plaintext highlighter-rouge">word_t</code>的数字即可。</p>
  </li>
  <li>
    <p>如果$p&lt;q$，意味着要不第一次传入的表达式index存在问题，要不然在递归过程中第三个if对应的括号内部表达式为空。这种情况我们直接<code class="language-plaintext highlighter-rouge">assert(0)</code>即可。</p>
  </li>
</ol>

<p>第1，3，4步都很好实现，问题转移到了第2步<code class="language-plaintext highlighter-rouge">check_parentheses(p, q)</code>该如何实现呢？根据讲义，<code class="language-plaintext highlighter-rouge">check_parentheses(p, q)</code>只有在传入<code class="language-plaintext highlighter-rouge">"(" &lt;expr&gt; ")"</code>时才返回<code class="language-plaintext highlighter-rouge">true</code>，那么为了实现这个功能，我们定义</p>

<ul>
  <li>返回值<code class="language-plaintext highlighter-rouge">0</code>代表传入的表达式内含有<strong>不合法的括号序列</strong></li>
  <li>返回值<code class="language-plaintext highlighter-rouge">-1</code>代表传入的表达式内<strong>括号序列合法</strong>，但是<strong>不能删除表达式左右端的运算符</strong></li>
  <li>返回值<code class="language-plaintext highlighter-rouge">1</code>代表传入的表达式内<strong>括号序列合法</strong>，且<strong>表达式左右端的运算符可以删除</strong>（即括号）</li>
</ul>

<p>它得做到以下几种情况的处理：</p>

<ol>
  <li>
    <p>检测传入表达式内的括号是否合法，不合法直接返回<code class="language-plaintext highlighter-rouge">0</code> 。【针对样例<code class="language-plaintext highlighter-rouge">(4 + 3)) * ((2 - 1)</code>】</p>
  </li>
  <li>
    <p>检测表达式两断是否有左右括号，没有直接返回<code class="language-plaintext highlighter-rouge">-1</code>。 【针对样例<code class="language-plaintext highlighter-rouge">4 + 3 * (2 - 1)</code>】</p>
  </li>
  <li>
    <p>递归检测去除括号的内部表达式包含的的括号序列是否合法（查看返回值是否为<code class="language-plaintext highlighter-rouge">true</code>或者<code class="language-plaintext highlighter-rouge">-1</code>），合法返回<code class="language-plaintext highlighter-rouge">true</code>，不合法返回<code class="language-plaintext highlighter-rouge">-1</code>。【针对样例<code class="language-plaintext highlighter-rouge">(4 + 3) * (2 - 1)</code>】</p>

    <p><em>需要说明的是这里虽然内部不合法，但是函数顺序执行，如果了第1步的检测来到这里，就意味着当前表达式符合返回值<code class="language-plaintext highlighter-rouge">-1</code>的定义，而非返回值<code class="language-plaintext highlighter-rouge">0</code>的定义。</em></p>
  </li>
  <li>
    <p>由于要有递归终点，当$p&lt;q$时，我们需要返回<code class="language-plaintext highlighter-rouge">-1</code>。</p>
  </li>
</ol>

<p><em>注意在这里，我们不检测<code class="language-plaintext highlighter-rouge">&lt;expr&gt;</code>本身的合法性，他的合法性由<code class="language-plaintext highlighter-rouge">eval</code>函数检测，例如在$p=q$时对于最后一个剩余字符必须为运算数的类型之一。</em></p>

<h3 id="如何拓展表达式求值功能">如何拓展表达式求值功能</h3>

<p>Congratulations！因为到了这里，一般就不会写出啥BUG了。拓展功能设计两个方面：</p>

<ol>
  <li>
    <p>兼容单目运算符</p>

    <p>为了做到第一点，我们需要在<code class="language-plaintext highlighter-rouge">eval</code>函数中将单目运算符与双目运算符区别开进行计算即可。但形如<code class="language-plaintext highlighter-rouge">-（单目-取反/双目-减法）</code>和<code class="language-plaintext highlighter-rouge">*（单目-解引用/双目-乘法）</code>这样，一个字符对应两种运算符的情况，我们只需要在<code class="language-plaintext highlighter-rouge">eval</code>函数之前找到连续运算符，将连续运算符段中靠后的那个运算符设置为对应的单目运算符即可。</p>
  </li>
  <li>
    <p>添加更多运算符，运算数类型</p>

    <p>这个就太简单了，加正则表达式，加优先级，加<code class="language-plaintext highlighter-rouge">eval</code>中运算符对应的运算方式…</p>

    <p><em>解引用运算直接用<code class="language-plaintext highlighter-rouge">vaddr_read()</code>函数读取1个uint32_t长度（4个字节）的数据即可。</em></p>
  </li>
</ol>

<p>除此之外，还是建议在代码中多添加<code class="language-plaintext highlighter-rouge">assert</code>检查格式是否有问题方便之后遇到问题时DEBUG，例如单目运算符计算时必须保证第一个字符的类型一定是运算符类型。</p>

<h3 id="如何编写测试样例生成和测试程序">如何编写测试样例生成和测试程序</h3>

<h4 id="测试样例生成程序">测试样例生成程序</h4>

<p>根据BNF表达式，递归构造字符串，但一个值得我们思考的问题，我们如何给这个构造函数设置一个递归终点？一种解决方法是如果长度超出限制，那就舍弃并重新构造，但这样的方式可能会引发栈帧溢出的错误。另一种解决方式是给构造函数多增加一个输入参数限制最大的生成长度，如果函数当前的最大生成长度低于某一阈值则停止递归调用。</p>

<p>根据合法的表达式生成正确答案的过程实际上是把生成的表达式作为C代码的一部分，让其编译执行后打印出表达式的结果。</p>

<p>值得一提的是根据框架已经给好的C代码可以看出，<code class="language-plaintext highlighter-rouge">eval</code>函数返回值是int，<code class="language-plaintext highlighter-rouge">expr</code>函数的返回值才是<code class="language-plaintext highlighter-rouge">uint32_t</code>。</p>

<h4 id="测试程序">测试程序</h4>

<p>打开文件后，读入每一行的字符串，使用<code class="language-plaintext highlighter-rouge">strtok</code>分隔<code class="language-plaintext highlighter-rouge">gold_answer</code>和<code class="language-plaintext highlighter-rouge">expression</code>，检测<code class="language-plaintext highlighter-rouge">eval(expresssion)=gold_answer</code>即可。</p>

<h2 id="其他问题处理">其他问题处理</h2>

<h3 id="如何添加监视点功能">如何添加监视点功能</h3>

<p>维护一个<a href="https://www.cnblogs.com/ranjiewen/p/5428839.html">支持增删改查的链表</a>即可，不过多赘述了。</p>

<p>由于<code class="language-plaintext highlighter-rouge">watchpoint.c</code>需要提供一些接口（如查看表达式值是否发生变化），且该文件没有对应的头文件，所以记得要在<code class="language-plaintext highlighter-rouge">sdb.c</code>顶部给出函数声明。</p>

<h3 id="watchpoint文件为什么要用一些static变量">watchpoint文件为什么要用一些static变量</h3>

<p>使用<code class="language-plaintext highlighter-rouge">static</code>修饰的变量具有<strong>内部链接性</strong>，意味着它只能在定义它的源文件中可见，其他文件无法引用。这样使得监视点池有良好的封装性，不会被其他文件窥探并修改其中的内容。</p>

<h3 id="gdb会提供哪些信息">GDB会提供哪些信息</h3>

<p>GDB（GNU调试器）可以提供多种信息，包括：</p>

<ol>
  <li><strong>程序状态</strong>：当前执行的行、调用栈、寄存器值。</li>
  <li><strong>变量信息</strong>：局部变量、全局变量及其值。</li>
  <li><strong>内存状态</strong>：内存中的数据及其地址。</li>
  <li><strong>源代码</strong>：与当前执行点相关联的源代码行。</li>
  <li><strong>程序输出</strong>：输出流的信息，方便调试。</li>
  <li><strong>断点管理</strong>：设置、删除断点及其命中情况。</li>
</ol>

<h3 id="gdb中把断点设置在指令的非首字节会发生什么">GDB中把断点设置在指令的非首字节会发生什么</h3>

<p>在GDB中，如果把断点设置在指令的非首字节（例如，中间或末尾），会发生以下情况：</p>

<ol>
  <li><strong>无法正常设置断点</strong>：GDB通常会拒绝在非首字节设置断点，因为断点是通过修改指令的机器码来实现的。如果你尝试在非首字节设置断点，GDB会报告错误。</li>
  <li><strong>可能导致程序崩溃或异常</strong>：如果指令的非首字节被修改为中断指令，程序在执行时可能会导致不可预测的行为，包括崩溃或错误。</li>
  <li><strong>指令分割</strong>：某些指令可能在字节边界上有特定要求（例如，ARM架构的Thumb模式），在不正确的位置设置断点可能导致指令无法正确解析。</li>
</ol>

<p>断点的工作原理是用一种特殊的指令（通常是中断指令或陷入指令）替换目标地址处的机器码，从而暂停程序执行。由于指令通常由多个字节组成，修改非首字节可能导致指令的不完整性，从而造成程序崩溃或无法执行。</p>

<h3 id="nemu和gdb分别是怎样调试程序的">NEMU和GDB分别是怎样调试程序的</h3>

<p>模拟器（如NEMU）用于模拟整个硬件环境，使软件在不同架构上运行，而调试器（如GDB）专注于调试已编译的程序，帮助开发者分析和修复错误。NEMU模拟CPU和系统行为，支持基本调试功能；GDB则提供丰富的调试工具，允许设置断点、单步执行和检查程序状态。</p>

<h3 id="riscv32有哪几种指令格式">riscv32有哪几种指令格式</h3>

<ul>
  <li><strong>R型（R-Type）</strong>：典型指令有算术运算（如<code class="language-plaintext highlighter-rouge">ADD</code>，<code class="language-plaintext highlighter-rouge">SUB</code>）、逻辑运算等。</li>
  <li><strong>I型（I-Type）</strong>：用于立即数操作、加载类指令，典型指令有<code class="language-plaintext highlighter-rouge">ADDI</code>（立即数加法）、<code class="language-plaintext highlighter-rouge">LOAD</code>（加载内存到寄存器）。</li>
  <li><strong>S型（S-Type）</strong>：用于存储类指令，典型指令有<code class="language-plaintext highlighter-rouge">STORE</code>（存储寄存器到内存）。</li>
  <li><strong>B型（B-Type）</strong>：用于条件分支跳转类指令，典型指令有<code class="language-plaintext highlighter-rouge">BEQ</code>（相等条件分支）、<code class="language-plaintext highlighter-rouge">BNE</code>（不等条件分支）。</li>
  <li><strong>U型（U-Type）</strong>：用于指令中带有大立即数（高20位）操作，典型指令有<code class="language-plaintext highlighter-rouge">LUI</code>（加载高立即数）、<code class="language-plaintext highlighter-rouge">AUIPC</code>（将立即数加到PC）。</li>
  <li><strong>J型（J-Type）</strong>：用于无条件跳转指令，典型指令有<code class="language-plaintext highlighter-rouge">JAL</code>（跳转并链接）。</li>
</ul>

<h3 id="lui指令的行为是什么">LUI指令的行为是什么</h3>

<p>LUI（Load Upper Immediate）指令将一个20位的立即数加载到目标寄存器的高20位，低12位填充为0。这通常用于构建较大的立即数或地址。</p>

<h3 id="mstatus寄存器的结构是怎么样的">mstatus寄存器的结构是怎么样的</h3>

<p><code class="language-plaintext highlighter-rouge">mstatus</code>寄存器的结构包含多个字段，包括：</p>

<ul>
  <li><strong>MIE</strong>：机器中断使能位。</li>
  <li><strong>MPIE</strong>：机器中断使能的先前值。</li>
  <li><strong>MPRV</strong>：用于指示是否在特权级下访问。</li>
  <li><strong>XS</strong>：扩展状态位，指示浮点状态。</li>
  <li><strong>FS</strong>：浮点状态位，指示浮点单元的状态。</li>
</ul>

<h3 id="如何统计代码行数">如何统计代码行数</h3>

<p>基本思路：<code class="language-plaintext highlighter-rouge">find</code>找到所有.c和.h文件，<code class="language-plaintext highlighter-rouge">grep</code>过滤空行，<code class="language-plaintext highlighter-rouge">wc</code>统计行数</p>

<p>讲义中有提及到<a href="(https://nju-projectn.github.io/ics-pa-gitbook/ics2024/linux.html#%E7%BB%9F%E8%AE%A1%E4%BB%A3%E7%A0%81%E8%A1%8C%E6%95%B0)">包含空行的代码统计方式</a>，我们需要进行一些更改。</p>

<pre><code class="language-Makefile">count:
	@echo "line counts = $(shell find $(NEMU_HOME)/ -name "*.c" -o -name "*.h" | xargs grep -v '^\s*$$' | wc -l)"

.PHONY: run gdb run-env clean-tools clean-all $(clean-tools) count
</code></pre>

<h3 id="gcc中的wall和werror什么作用">gcc中的Wall和Werror什么作用？</h3>

<p>-Wall</p>

<ul>
  <li><strong>作用</strong>：启用大多数的警告信息，这些警告通常表示潜在的代码问题。使用<code class="language-plaintext highlighter-rouge">-Wall</code>可以帮助开发者发现代码中的错误和不规范的地方。</li>
  <li><strong>使用原因</strong>：通过开启更多的警告，开发者可以及时识别和修复可能导致未定义行为或其他问题的代码，从而提高代码质量和可靠性。</li>
</ul>

<p>-Werror</p>

<ul>
  <li><strong>作用</strong>：将所有警告视为错误。如果编译过程中出现任何警告，编译器将停止编译，并返回错误状态。</li>
  <li><strong>使用原因</strong>：使用<code class="language-plaintext highlighter-rouge">-Werror</code>可以强制开发者关注代码中的警告，因为它们被视为阻碍编译的错误。这有助于确保代码在发布前是干净的，没有潜在问题。</li>
</ul>

<h2 id="源码">源码</h2>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* sdb.c 粘一些代表性的，不全粘贴 */</span> 
<span class="k">static</span> <span class="kt">int</span> <span class="nf">cmd_x</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
  <span class="cm">/* extract the first argument */</span>
  <span class="kt">char</span><span class="o">*</span> <span class="n">arg</span> <span class="o">=</span> <span class="n">strtok</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">" "</span><span class="p">);</span>

  <span class="n">word_t</span> <span class="n">N</span><span class="p">;</span>
  <span class="n">vaddr_t</span> <span class="n">EXPR</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">arg</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* no argument is given */</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: x need two argument: N implies length, EXPR implies expression"</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="cm">/* read the first argument */</span>
    <span class="n">sscanf</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="s">"%u"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">N</span><span class="p">);</span>
          
    <span class="n">arg</span> <span class="o">=</span> <span class="n">strtok</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">" "</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">arg</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
      <span class="cm">/* only one argument is given */</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: x need two argument: N implies length, EXPR implies expression"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">bool</span> <span class="n">success</span><span class="p">;</span>

      <span class="n">EXPR</span> <span class="o">=</span> <span class="p">(</span><span class="n">vaddr_t</span><span class="p">)</span><span class="n">expr</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">success</span><span class="p">);</span>

      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">success</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"EXPR is invalid"</span><span class="p">);</span>
        <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="k">else</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"%-10s</span><span class="se">\t</span><span class="s">%-10s</span><span class="se">\t</span><span class="s">%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">"VADDR"</span><span class="p">,</span> <span class="s">"HEX_VALUE"</span><span class="p">,</span> <span class="s">"DEC_VALUE"</span><span class="p">);</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">word_t</span> <span class="n">value</span> <span class="o">=</span> <span class="n">vaddr_read</span><span class="p">(</span><span class="n">EXPR</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">word_t</span><span class="p">));</span>
          <span class="n">printf</span><span class="p">(</span><span class="s">"%#010x</span><span class="se">\t</span><span class="s">%#010x</span><span class="se">\t</span><span class="s">%u</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">EXPR</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
          <span class="n">EXPR</span> <span class="o">+=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">word_t</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* expr.c 粘一些代表性的，不全粘贴 */</span> 
<span class="k">static</span> <span class="kt">int</span> <span class="nf">check_parentheses</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// check if the expression is surrounded by a matched pair of parentheses</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="n">q</span><span class="p">)</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">q</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'('</span><span class="p">)</span>
      <span class="o">++</span><span class="n">cnt</span><span class="p">;</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">')'</span><span class="p">)</span>
      <span class="o">--</span><span class="n">cnt</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">cnt</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
      <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">cnt</span><span class="p">)</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">type</span> <span class="o">!=</span> <span class="sc">'('</span> <span class="o">||</span> <span class="n">tokens</span><span class="p">[</span><span class="n">q</span><span class="p">].</span><span class="n">type</span> <span class="o">!=</span> <span class="sc">')'</span><span class="p">)</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">check_parentheses</span><span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="cm">/* value is -1 or 1 */</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
  <span class="k">else</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">int</span> <span class="nf">get_op_level</span><span class="p">(</span><span class="kt">int</span> <span class="n">op_type</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">switch</span> <span class="p">(</span><span class="n">op_type</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">case</span> <span class="n">TK_OR</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
  <span class="k">case</span> <span class="n">TK_AND</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">2</span><span class="p">;</span>
  <span class="k">case</span> <span class="n">TK_EQ</span><span class="p">:</span> <span class="k">case</span> <span class="n">TK_NEQ</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">3</span><span class="p">;</span>
  <span class="k">case</span> <span class="sc">'+'</span><span class="p">:</span> <span class="k">case</span> <span class="sc">'-'</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">4</span><span class="p">;</span>
  <span class="k">case</span> <span class="sc">'*'</span><span class="p">:</span> <span class="k">case</span> <span class="sc">'/'</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">5</span><span class="p">;</span>
  <span class="k">case</span> <span class="n">TK_NEG</span><span class="p">:</span> <span class="k">case</span> <span class="n">TK_DEREF</span><span class="p">:</span> <span class="k">case</span> <span class="n">TK_NOT</span><span class="p">:</span>
    <span class="k">return</span> <span class="mi">6</span><span class="p">;</span>
  <span class="nl">default:</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: invalid operator %d (enum index)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">op_type</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">find_unary_op</span><span class="p">()</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nr_token</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'-'</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">is_bin_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">type</span><span class="p">)))</span> <span class="p">{</span>
      <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">=</span> <span class="n">TK_NEG</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'*'</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">is_bin_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">type</span><span class="p">)))</span> <span class="p">{</span>
      <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">=</span> <span class="n">TK_DEREF</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'!'</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">is_bin_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">type</span><span class="p">)))</span> <span class="p">{</span>
      <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">=</span> <span class="n">TK_NOT</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">int</span> <span class="nf">eval</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* Bad expression */</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: bad expression</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">==</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* Single token.
     * For now this token should be a number.
     * Return the value of the number.
     */</span>
    <span class="kt">long</span> <span class="kt">long</span> <span class="n">num</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="n">TK_HEX</span><span class="p">)</span>
      <span class="n">sscanf</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">str</span><span class="p">,</span> <span class="s">"%llx"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num</span><span class="p">);</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="n">TK_DEC</span><span class="p">)</span>
      <span class="n">sscanf</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">str</span><span class="p">,</span> <span class="s">"%lld"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num</span><span class="p">);</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="n">TK_REG</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">bool</span> <span class="n">success</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
      <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">isa_reg_str2val</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">str</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">success</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">success</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: invalid register %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">str</span><span class="p">);</span>
        <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: invalid token %d (enum index)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">type</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">num</span> <span class="o">&gt;</span> <span class="mh">0x100000000</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">"WARNING: the input number [%s] is too large"</span><span class="p">,</span> <span class="n">tokens</span><span class="p">[</span><span class="n">p</span><span class="p">].</span><span class="n">str</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">word_t</span><span class="p">)</span><span class="n">num</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">check_parentheses</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span> <span class="o">==</span> <span class="nb">true</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* The expression is surrounded by a matched pair of parentheses.
     * If that is the case, just throw away the parentheses.
     */</span>
    <span class="k">return</span> <span class="n">eval</span><span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">current_priority</span><span class="p">,</span> <span class="n">op_pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">priority</span> <span class="o">=</span> <span class="mh">0x3f3f3f3f</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">val1</span><span class="p">,</span> <span class="n">val2</span><span class="p">;</span>

    <span class="cm">/* Find the position of dominant operator */</span>
    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">q</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'('</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">cnt</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">q</span><span class="p">)</span> <span class="p">{</span>
          <span class="o">++</span><span class="n">i</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">'('</span><span class="p">)</span>
            <span class="o">++</span><span class="n">cnt</span><span class="p">;</span>
          <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span> <span class="o">==</span> <span class="sc">')'</span><span class="p">)</span>
            <span class="o">--</span><span class="n">cnt</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">cnt</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: bad expression %d-%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
          <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">is_bin_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span><span class="p">)</span> <span class="o">||</span> <span class="n">is_unary_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">current_priority</span> <span class="o">=</span> <span class="n">get_op_level</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">type</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">current_priority</span> <span class="o">&lt;=</span> <span class="n">priority</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">priority</span> <span class="o">=</span> <span class="n">current_priority</span><span class="p">;</span>
          <span class="n">op_pos</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">is_unary_op</span><span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">op_pos</span><span class="p">].</span><span class="n">type</span><span class="p">))</span> <span class="p">{</span>
      <span class="cm">/* unary operator */</span>
      <span class="n">assert</span><span class="p">(</span><span class="n">op_pos</span> <span class="o">==</span> <span class="n">p</span><span class="p">);</span>
     <span class="k">switch</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">op_pos</span><span class="p">].</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
     <span class="k">case</span> <span class="n">TK_DEREF</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">vaddr_read</span><span class="p">(</span><span class="n">eval</span><span class="p">(</span><span class="n">op_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">),</span> <span class="mi">4</span><span class="p">);</span>
      <span class="k">case</span> <span class="n">TK_NEG</span><span class="p">:</span>
        <span class="k">return</span> <span class="o">-</span><span class="n">eval</span><span class="p">(</span><span class="n">op_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
      <span class="k">case</span> <span class="n">TK_NOT</span><span class="p">:</span>
        <span class="k">return</span> <span class="o">!</span><span class="n">eval</span><span class="p">(</span><span class="n">op_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
      <span class="nl">default:</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: invalid operator %d (enum index)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">tokens</span><span class="p">[</span><span class="n">op_pos</span><span class="p">].</span><span class="n">type</span><span class="p">);</span>
        <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// impossible</span>
     <span class="p">}</span> 
    <span class="p">}</span>

    <span class="n">val1</span> <span class="o">=</span> <span class="n">eval</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">op_pos</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">val2</span> <span class="o">=</span> <span class="n">eval</span><span class="p">(</span><span class="n">op_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>

    <span class="k">switch</span> <span class="p">(</span><span class="n">tokens</span><span class="p">[</span><span class="n">op_pos</span><span class="p">].</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
      <span class="cm">/* TODO: Possible arithmetic overflows are not handled */</span>
    <span class="k">case</span> <span class="sc">'+'</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">+</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="sc">'-'</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">-</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="sc">'*'</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">*</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="sc">'/'</span><span class="p">:</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">val2</span><span class="p">)</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"ERROR: division by zero</span><span class="se">\n</span><span class="s">"</span><span class="p">),</span> <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">/</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">TK_EQ</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">==</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">TK_NEQ</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">!=</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">TK_AND</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">&amp;&amp;</span> <span class="n">val2</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">TK_OR</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">val1</span> <span class="o">||</span> <span class="n">val2</span><span class="p">;</span>
    <span class="nl">default:</span> <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* expr.c 粘一些代表性的，不全粘贴 */</span> 
<span class="n">WP</span> <span class="o">*</span><span class="nf">new_wp</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">free_</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"No enough watchpoints.</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">WP</span> <span class="o">*</span><span class="n">wp</span> <span class="o">=</span> <span class="n">free_</span><span class="p">;</span>
  <span class="n">free_</span> <span class="o">=</span> <span class="n">free_</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
  <span class="n">wp</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
  <span class="n">head</span> <span class="o">=</span> <span class="n">wp</span><span class="p">;</span>
  <span class="k">return</span> <span class="n">wp</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">free_wp</span><span class="p">(</span><span class="n">WP</span> <span class="o">*</span><span class="n">wp</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">wp</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">WP</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">==</span> <span class="n">wp</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">head</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
    <span class="n">wp</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">free_</span><span class="p">;</span>
    <span class="n">free_</span> <span class="o">=</span> <span class="n">wp</span><span class="p">;</span>
    <span class="k">return</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="n">wp</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">p</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">wp</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
      <span class="n">wp</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">free_</span><span class="p">;</span>
      <span class="n">free_</span> <span class="o">=</span> <span class="n">wp</span><span class="p">;</span>
      <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="ICS" /><summary type="html"><![CDATA[由于自己并不是NJU 2024的学生，因此“堂而皇之”的把这份心得发在了网上，并且只是仅供非以此课程作为自己当前学年保研课的同学参考。如若这是你的目前正在进修的保研课程，请速速关闭此网页！！！]]></summary></entry><entry><title type="html">NJU ICS2024 PA 作业心得（二）</title><link href="https://resume.dreamw1ngs.com/posts/2024/10/08/ics-pa2/" rel="alternate" type="text/html" title="NJU ICS2024 PA 作业心得（二）" /><published>2024-09-15T00:00:00+00:00</published><updated>2024-09-15T00:00:00+00:00</updated><id>https://resume.dreamw1ngs.com/posts/2024/10/08/blog-post-ics-pa2</id><content type="html" xml:base="https://resume.dreamw1ngs.com/posts/2024/10/08/ics-pa2/"><![CDATA[<blockquote>
  <p>在实现和调试 RISC-V 架构下的 NEMU 仿真器和 AM 运行环境过程中可能遇到的问题及其解决方案，包括指令解析、输入输出、ELF 文件解析、klib 库、ftrace/mtrace/itrace/difftest 的实现，以及与硬件模拟相关的设备驱动。</p>
</blockquote>

<h2 id="rtfsc问题处理">RTFSC问题处理</h2>

<p>这部分一定要很<strong>仔细很仔细</strong>的阅读RISCV的手册，否则后边会吃苦头的。</p>

<p>我们这里从框架的角度对取指之前和执行之后的操作进行一些简要的补充介绍，方便读者结合帮助文档了解NEMU的整体流程。</p>

<ul>
  <li>
    <p>取指之前</p>

    <ol>
      <li>
        <p>risv32中每条指令的长度为4个字节，这些指令以二进制文件读写的形式被堆排到了bin文件，nemu中定义了位置参数获得需要的bin文件路径。</p>
      </li>
      <li>
        <p>在交互控制台使用<code class="language-plaintext highlighter-rouge">si</code>或者<code class="language-plaintext highlighter-rouge">c</code>执行<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/cpu/cpu-exec.c</code>文件下的<code class="language-plaintext highlighter-rouge">cpu_exec</code>函数，该函数调用同文件下的<code class="language-plaintext highlighter-rouge">execute</code>函数执行若干次指令后。</p>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">execute</code>函数中创建了一个结构体<code class="language-plaintext highlighter-rouge">Decode</code>，<code class="language-plaintext highlighter-rouge">pc</code>指代要被译码的指令地址，<code class="language-plaintext highlighter-rouge">snpc</code>指代<code class="language-plaintext highlighter-rouge">pc</code>之后的下一个地址，<code class="language-plaintext highlighter-rouge">dnpc</code>只带指令执行后，<code class="language-plaintext highlighter-rouge">pc</code>该前往的地址，<code class="language-plaintext highlighter-rouge">inst</code>只带了指令的二进制代码，<code class="language-plaintext highlighter-rouge">logbuf</code>则是用来存指令的反汇编结果。</p>

        <p>然后通过调用若干次<code class="language-plaintext highlighter-rouge">exec_once</code>函数执行顺序若干次指令。</p>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">exec_once</code>函数维护了结构体<code class="language-plaintext highlighter-rouge">Decode</code>的内容，调用了<code class="language-plaintext highlighter-rouge">isa_exec_once</code>以此进行取指，译码、执行</p>
      </li>
    </ol>
  </li>
  <li>
    <p>执行（更新<code class="language-plaintext highlighter-rouge">pc</code>后）之后</p>
    <ol>
      <li>在<code class="language-plaintext highlighter-rouge">exec_once</code>函数中记录指令信息和反汇编结果到<code class="language-plaintext highlighter-rouge">Decode.logbuf</code>中。</li>
      <li>在<code class="language-plaintext highlighter-rouge">execute</code>函数中调用<code class="language-plaintext highlighter-rouge">trace_and_difftest</code>函数检查NEMU中我们的译码行为，并打印追踪日志（所有的XTRACE应该都在这里记录结果）。每次调用<code class="language-plaintext highlighter-rouge">exec_once</code>函数会检查NEMU的状态（出现异常则停止执行指令）</li>
      <li>在<code class="language-plaintext highlighter-rouge">cpu_exec</code>函数中打印执行结果。</li>
    </ol>
  </li>
</ul>

<h3 id="riscv32由于指令字长限制应该如何载入32位常数">riscv32由于指令字长限制应该如何载入32位常数</h3>

<p>两者都使用分段加载的方式，先加载高位，再使用立即数指令将低位部分合并到寄存器中，以此完成32位常数的加载操作。这种方法有效利用了32位指令的有限空间，避免了直接在一条指令中编码整个32位常数的限制，下面我们给出RISC-V32的解决方案。</p>

<ol>
  <li><strong><code class="language-plaintext highlighter-rouge">lui</code>（Load Upper Immediate）指令</strong>：
    <ul>
      <li>使用<code class="language-plaintext highlighter-rouge">lui</code>指令将一个32位常数的高20位加载到寄存器的高位部分。例如，<code class="language-plaintext highlighter-rouge">lui t0, 0x12345</code>会将<code class="language-plaintext highlighter-rouge">0x12345000</code>加载到寄存器<code class="language-plaintext highlighter-rouge">t0</code>中。</li>
    </ul>
  </li>
  <li><strong><code class="language-plaintext highlighter-rouge">addi</code>（Add Immediate）指令</strong>：
    <ul>
      <li>使用<code class="language-plaintext highlighter-rouge">addi</code>指令加载低12位的立即数，并将其与<code class="language-plaintext highlighter-rouge">lui</code>加载的高位相加。例如，<code class="language-plaintext highlighter-rouge">addi t0, t0, 0x678</code>会将寄存器<code class="language-plaintext highlighter-rouge">t0</code>中的值更新为<code class="language-plaintext highlighter-rouge">0x12345678</code>。</li>
    </ul>
  </li>
</ol>

<h3 id="riscv32指令如何实现">riscv32指令如何实现</h3>

<p>本部分是这一小节的重点，有许多容易踩的坑（需要你仔细研读官方文档），</p>

<ul>
  <li><strong>一定要注意运算数是有符号还是无符号！</strong></li>
  <li><strong>一定要按照文档描述按照制定的运算数类型（64位or32位）进行运算！</strong></li>
  <li><strong>一定要按照文档描述对异常情况进行实现！</strong></li>
</ul>

<p>在这一部分为了能通过所有指令测试集（如果指令测试集通过，证明某条指令实现应该没有问题了，之后如果遇到BUG，请对自己实现的指令有充足的信心，不用溯源到此处），我们需要总共实现6中类型的指令R、I、S、B、U、J，需要在<code class="language-plaintext highlighter-rouge">decode_operand</code>添加<code class="language-plaintext highlighter-rouge">TYPE_*</code>以及他们立即数获取方式（参照下图）。</p>

<p><img src="/images/image-2024-10-08-blog-post-ics-pa2-1.png" alt="immediate number" /></p>

<p>为了获取立即数，NEMU框架给我们提供了一些很棒的宏定义：</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">BITS(x, hi, lo)</code>获取二进制数$x$第$[lo,hi]$的比特内容</li>
  <li><code class="language-plaintext highlighter-rouge">SEXT(x, len)</code>有符号拓展$x$到二进制下$len$位。这里的实现用到了位域，巧妙到通过限制有符号int的长度接受到$x$的符号位信息，从而再转化成无符号类型实现有符号位拓展。</li>
</ul>

<p>接着的实现就是根据报错信息找到缺失的指令，根据<code class="language-plaintext highlighter-rouge">opcode</code>,<code class="language-plaintext highlighter-rouge">funct*</code>锁定具体指令实现即可。</p>

<h2 id="程序-运行时环境与am问题处理">程序, 运行时环境与AM问题处理</h2>

<h3 id="如何通过批处理模式运行nemu">如何通过批处理模式运行NEMU</h3>

<p>因为AM文件夹中Makefile肯定通过了某种方式编译了nemu，并传入了参数，我们需要找到这一步，然后想办法将批处理参数<code class="language-plaintext highlighter-rouge">-b</code>传入。</p>

<p>通过阅读<code class="language-plaintext highlighter-rouge">$AM_HOME/Makefile line 97</code>的内容<code class="language-plaintext highlighter-rouge">-include $(AM_HOME)/scripts/$(ARCH).mk</code>可以发现这里引入了<code class="language-plaintext highlighter-rouge">$(AM_HOME)/scripts/$(ARCH).mk</code>，由于我们的<code class="language-plaintext highlighter-rouge">ARCH=riscv32-nemu</code>，于是再查看<code class="language-plaintext highlighter-rouge">$(AM_HOME)/scripts/riscv32-nemu.mk</code>发现他引用了<code class="language-plaintext highlighter-rouge">$AM_HOME/scripts/platform/nemu.mk</code>。</p>

<p>在这个文件的第31行<code class="language-plaintext highlighter-rouge">$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) run ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin</code>发现它传给nemu的参数是<code class="language-plaintext highlighter-rouge">NEMUFLAGS</code>这个变量。细心的你会发现，在我们的测试文件的Makefile中，我们会把命令行中的<code class="language-plaintext highlighter-rouge">ARGS</code>参数传给Makefile<code class="language-plaintext highlighter-rouge">ARGS</code>变量，我们需要将这个变量传给Makefile中的<code class="language-plaintext highlighter-rouge">NEMUFLAGS</code>才对。</p>

<p>但很快你会发现如果改了这一步，会导致NEMU无法输出<code class="language-plaintext highlighter-rouge">nemu.log</code>了，于是我们尝试去寻找<code class="language-plaintext highlighter-rouge">-l xxx/nemu.log</code>参数定义的位置，发现他在<code class="language-plaintext highlighter-rouge">$AM_HOME/scripts/platform/nemu.mk</code>中，但是这个变量在声明的时候<strong>没有添加<code class="language-plaintext highlighter-rouge">override</code>关键字</strong>。这就会导致+=运算无法对命令行传来的变量生效，因为命令行同名变量会覆盖Makefile文件中定义的同名变量，需要加<code class="language-plaintext highlighter-rouge">override</code>专门在针对命令行同名变量进行运算。</p>

<h3 id="如何实现sprintf">如何实现sprintf</h3>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">sprintf</code>：将可变参数列表获取后提供给<code class="language-plaintext highlighter-rouge">vsprintf</code>，将结果输出到一个字符串即可。</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">printf</code>：将可变参数列表获取后提供给<code class="language-plaintext highlighter-rouge">vsprintf</code>，将结果输出到一个字符串，然后再利用<code class="language-plaintext highlighter-rouge">putch</code>住个字符输出即可</p>
  </li>
</ul>

<p>所以如果要实现<code class="language-plaintext highlighter-rouge">sprintf</code>最关键的步骤是实现<code class="language-plaintext highlighter-rouge">vsprintf</code></p>

<p><code class="language-plaintext highlighter-rouge">vsprintf</code> 是一个格式化输出函数，用于将格式化的数据输出到字符串中。该函数的设计思想基于处理格式化字符串中的不同占位符，并根据可变参数的类型将其转换为相应的字符串形式，最后将结果拼接到输出缓冲区 <code class="language-plaintext highlighter-rouge">out</code> 中。以下是该函数的设计思路：</p>

<h4 id="1-输入参数">1. 输入参数</h4>

<ul>
  <li><code class="language-plaintext highlighter-rouge">char *out</code>：输出缓冲区指针，用于存储格式化后的字符串。</li>
  <li><code class="language-plaintext highlighter-rouge">const char *fmt</code>：格式化字符串，包含普通字符和格式化占位符（例如 <code class="language-plaintext highlighter-rouge">%d</code>，<code class="language-plaintext highlighter-rouge">%s</code> 等）。</li>
  <li><code class="language-plaintext highlighter-rouge">va_list ap</code>：可变参数列表，包含需要格式化输出的数据。</li>
</ul>

<h4 id="2-遍历格式化字符串">2. 遍历格式化字符串</h4>

<p>使用 <code class="language-plaintext highlighter-rouge">while (*fmt != '\0')</code> 遍历格式化字符串 <code class="language-plaintext highlighter-rouge">fmt</code>，逐个字符处理。处理分为两种情况：</p>

<ol>
  <li>如果当前字符不是 <code class="language-plaintext highlighter-rouge">%</code>，将其作为普通字符直接拷贝到输出缓冲区中，并更新缓冲区指针和总输出长度。</li>
  <li>如果当前字符是 <code class="language-plaintext highlighter-rouge">%</code>，则需要进入格式化处理逻辑。</li>
</ol>

<h4 id="3-格式化占位符解析">3. 格式化占位符解析</h4>

<p>当遇到 <code class="language-plaintext highlighter-rouge">%</code> 时，函数进入解析模式，依次解析各类格式化修饰符：</p>

<ol>
  <li><strong>标志位解析</strong>：
    <ul>
      <li>通过 <code class="language-plaintext highlighter-rouge">switch</code> 语句处理常见的标志位，如 <code class="language-plaintext highlighter-rouge">-</code>（左对齐）、<code class="language-plaintext highlighter-rouge">+</code>（显示正负号）、<code class="language-plaintext highlighter-rouge">0</code>（填充零）、<code class="language-plaintext highlighter-rouge">#</code>（特殊格式）等。每个标志位被映射为一个二进制标志位，并存储在 <code class="language-plaintext highlighter-rouge">flags</code> 变量中。</li>
    </ul>
  </li>
  <li><strong>宽度解析</strong>：
    <ul>
      <li>如果格式说明符中指定了宽度（例如 <code class="language-plaintext highlighter-rouge">%10d</code> 表示输出宽度至少为 10），该宽度要么是直接给出的数字，要么是通过 <code class="language-plaintext highlighter-rouge">*</code> 从 <code class="language-plaintext highlighter-rouge">va_list</code> 参数中动态获取。</li>
    </ul>
  </li>
  <li><strong>精度解析</strong>：
    <ul>
      <li>如果存在精度修饰符（例如 <code class="language-plaintext highlighter-rouge">%.2f</code> 表示小数点后保留 2 位），解析精度值。同样，精度值可以是直接指定的数字或通过 <code class="language-plaintext highlighter-rouge">*</code> 从 <code class="language-plaintext highlighter-rouge">va_list</code> 参数中获取。</li>
    </ul>
  </li>
  <li><strong>类型说明符解析</strong>：
    <ul>
      <li>格式说明符的最后一个字符为类型说明符（如 <code class="language-plaintext highlighter-rouge">d</code>, <code class="language-plaintext highlighter-rouge">s</code>, <code class="language-plaintext highlighter-rouge">x</code> 等），用于确定当前参数的数据类型。根据类型说明符的不同，调用不同的处理函数来进行参数格式化。</li>
    </ul>
  </li>
</ol>

<h4 id="4-不同类型的格式化处理">4. 不同类型的格式化处理</h4>

<ul>
  <li>
    <p><strong>整数类型</strong> (<code class="language-plaintext highlighter-rouge">d</code>, <code class="language-plaintext highlighter-rouge">i</code>, <code class="language-plaintext highlighter-rouge">u</code>, <code class="language-plaintext highlighter-rouge">x</code>, <code class="language-plaintext highlighter-rouge">o</code>)：调用 <code class="language-plaintext highlighter-rouge">int_to_str</code> 函数，将整数值按照不同的进制转换为字符串（支持十进制、八进制、十六进制等），并根据指定的宽度和精度进行格式化输出。</p>
  </li>
  <li>
    <p><strong>字符类型</strong> (<code class="language-plaintext highlighter-rouge">c</code>)：直接将 <code class="language-plaintext highlighter-rouge">char</code> 类型的参数输出到缓冲区。</p>
  </li>
  <li>
    <p><strong>字符串类型</strong> (<code class="language-plaintext highlighter-rouge">s</code>)：将字符串按照指定的宽度和精度进行处理，支持左对齐或右对齐。</p>
  </li>
  <li>
    <p><strong>指针类型</strong> (<code class="language-plaintext highlighter-rouge">p</code>)：将指针地址转换为十六进制格式输出，并加上 <code class="language-plaintext highlighter-rouge">0x</code> 前缀。</p>
  </li>
  <li>
    <p><strong>特殊类型</strong>：</p>

    <ul>
      <li>
        <p><code class="language-plaintext highlighter-rouge">%</code>：直接输出 <code class="language-plaintext highlighter-rouge">%</code> 符号。</p>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">n</code>：将当前输出字符的长度存储到相应的指针位置。</p>
      </li>
    </ul>
  </li>
</ul>

<h4 id="5-输出结果拼接">5. 输出结果拼接</h4>

<p>在处理每个占位符后，格式化后的结果通过指针操作被拼接到输出缓冲区 <code class="language-plaintext highlighter-rouge">out</code> 中，并更新当前缓冲区指针 <code class="language-plaintext highlighter-rouge">buf</code> 以及总长度 <code class="language-plaintext highlighter-rouge">total_len</code>。</p>

<h4 id="6-返回结果">6. 返回结果</h4>

<p>当格式化字符串处理完毕后，在输出缓冲区末尾添加字符串终止符 <code class="language-plaintext highlighter-rouge">\0</code>，并返回输出缓冲区的长度。</p>

<h3 id="如何实现string库">如何实现string库</h3>

<p>使用<code class="language-plaintext highlighter-rouge">man 3 &lt;function_name&gt;</code>仔细根据手册实现即可，否则可能存在问题，这里也有一点容易踩的坑，</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">strnpy</code>如果$n$超出了$det$的长度，就不用添加字符串终止符 <code class="language-plaintext highlighter-rouge">\0</code>了</li>
  <li><code class="language-plaintext highlighter-rouge">strcmp</code>要注意字符串中的字符一般为无符号char，在这里如果要对读入的字符进行无符号转换，否则对于在ASCII码在128及以后的字符的大小比较会出现问题。</li>
</ul>

<h3 id="如何编写klib库的测试程序">如何编写klib库的测试程序</h3>

<p>尽量用多层for循环嵌套，枚举给定两字符串的起始位置和结束为止，以及操作长度$n$（如果有的话），这样一般是可以覆盖所有情况的（包括前面坑点提到的边界情况）。</p>

<h3 id="itrace的环形缓冲区如何实现">itrace的环形缓冲区如何实现</h3>

<p>我的实现是新建了<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/cpu/iringbuf.c</code>文件，在里面维护了一个环形队列，对外暴露的接口是一个函数<code class="language-plaintext highlighter-rouge">void record_inst(uint64_t pc, const char *asm_code)</code>传入了当前记录指令的pc指针和反汇编字符串，以及<code class="language-plaintext highlighter-rouge">void info_inst_records()</code>函数打印当前队列的信息。</p>

<p>在<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/cpu/cpu-exec.c</code>的<code class="language-plaintext highlighter-rouge">trace_and_difftest</code>函数中，将原本打印指令的位置更改成将指令记录到缓冲区。在同文件下的<code class="language-plaintext highlighter-rouge">assert_fail_msg</code>函数中，在NEMU框架<code class="language-plaintext highlighter-rouge">ASSERT</code>中断时输出调用<code class="language-plaintext highlighter-rouge">info_inst_records</code>。</p>

<h3 id="mtrace如何实现">mtrace如何实现</h3>

<p>在<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/memory/paddr.c</code>中<code class="language-plaintext highlighter-rouge">paddr_read</code>和<code class="language-plaintext highlighter-rouge">paddr_write</code>函数成功调用后记录信息即可。</p>

<h3 id="ftrace如何实现">ftrace如何实现</h3>

<p>首先我们需要了解elf文件的结构，这里就需要我们首先使用<code class="language-plaintext highlighter-rouge">riscv64-linux-gnu-readelf -a</code>获取elf文件的信息，再通过<code class="language-plaintext highlighter-rouge">hd</code>命令验证我们获取的elf文件信息，我们就可以很清晰的了解elf文件的架构了，下面我们进行一个简单的介绍。</p>

<h4 id="elf文件结构的整体组成">ELF文件结构的整体组成</h4>

<p>ELF文件由三个主要部分组成：</p>

<ol>
  <li>
    <p><strong>ELF Header</strong>（ELF头）：描述整个文件的组织结构，包括文件类型、目标架构、入口点等基本信息。</p>

    <p>ELF头位于文件的最前面，包含整个ELF文件的元数据信息。其结构固定，大小通常为64字节（32位格式为52字节），主要包含以下字段：</p>

    <ul>
      <li>
        <p><strong>魔数（Magic Number）</strong>：标识这是一个ELF文件，前4个字节为固定值 <code class="language-plaintext highlighter-rouge">0x7F</code>、<code class="language-plaintext highlighter-rouge">E</code>、<code class="language-plaintext highlighter-rouge">L</code>、<code class="language-plaintext highlighter-rouge">F</code>。</p>
      </li>
      <li>
        <p>Class：文件的架构类型，32位（<code class="language-plaintext highlighter-rouge">ELFCLASS32</code>）或64位（<code class="language-plaintext highlighter-rouge">ELFCLASS64</code>）。</p>
      </li>
      <li>
        <p>Data：数据编码，表示字节序的排列方式（小端<code class="language-plaintext highlighter-rouge">LSB</code>或大端<code class="language-plaintext highlighter-rouge">MSB</code>）。</p>
      </li>
      <li>
        <p>Version：文件格式的版本，通常为<code class="language-plaintext highlighter-rouge">1</code>。</p>
      </li>
      <li>
        <p>OS ABI：目标操作系统接口的ABI（应用程序二进制接口）。</p>
      </li>
      <li>
        <p>文件类型：指定这是可执行文件（<code class="language-plaintext highlighter-rouge">ET_EXEC</code>）、可重定位文件（<code class="language-plaintext highlighter-rouge">ET_REL</code>）或共享库（<code class="language-plaintext highlighter-rouge">ET_DYN</code>）。</p>
      </li>
      <li>
        <p>目标架构：如x86（<code class="language-plaintext highlighter-rouge">EM_386</code>）或ARM（<code class="language-plaintext highlighter-rouge">EM_ARM</code>）等。</p>
      </li>
      <li>
        <p>入口点地址：程序开始执行的虚拟地址。</p>
      </li>
      <li>
        <p>Program Header表偏移量：指向程序头表的偏移量。</p>
      </li>
      <li>
        <p><strong>Section Header表偏移量</strong>：指向节头表的偏移量。</p>
      </li>
      <li>
        <p>标志：与处理器相关的标志。</p>
      </li>
      <li>
        <p>头部的大小：ELF头的大小。</p>
      </li>
      <li>
        <p>Program Header表的条目大小及数量。</p>
      </li>
      <li><strong>Section Header表的条目大小及数量。</strong></li>
      <li><strong>Section header string表在节头表中的Index</strong></li>
    </ul>
  </li>
  <li>
    <p><strong>Program Header Table</strong>（程序头表）：描述如何将文件映射到内存中的不同段，用于执行时加载可执行文件。</p>

    <p>程序头表描述了如何将文件中的数据段映射到内存，以便程序执行。每个程序头条目描述了一个内存段的属性。程序头表在执行时用于决定哪些部分加载到内存中。</p>
  </li>
  <li>
    <p><strong>Section Header Table</strong>（节头表）：描述文件中的各个节（Section）的属性，用于链接和重定位。</p>

    <p>节头表的每个条目（节头）用于描述文件中的各个节（section），这些节在链接和重定位阶段起作用。每个节都有自己特定的作用，如存储代码、数据、符号表、重定位信息等。每个节头条目通常包含以下信息：</p>

    <ul>
      <li>
        <p><strong>Section Name（节名称）：通过节名称表（Section header string）来索引。</strong></p>
      </li>
      <li>
        <p>Section Type（节类型）：描述该节的内容，如可重定位数据（<code class="language-plaintext highlighter-rouge">SHT_RELA</code>）、符号表（<code class="language-plaintext highlighter-rouge">SHT_SYMTAB</code>）、字符串表（<code class="language-plaintext highlighter-rouge">SHT_STRTAB</code>）等。</p>
      </li>
      <li>
        <p>Section Flags（节标志）：描述节的属性，如可写、可执行、分配到内存等。</p>
      </li>
      <li>
        <p>Section Address（节地址）：如果该节被加载到内存中，它的虚拟地址。</p>
      </li>
      <li>
        <p><strong>Section Offset（文件偏移）：节在文件中的偏移量。</strong></p>
      </li>
      <li>
        <p><strong>Section Size（节大小）：节在文件中的大小。</strong></p>
      </li>
      <li>
        <p>Link：与其他节的关联，如符号表与字符串表的关联。</p>
      </li>
      <li>
        <p>Info：附加信息，不同类型的节该字段含义不同。</p>
      </li>
      <li>
        <p>Address Alignment（对齐）：节在文件中或内存中的对齐要求。</p>
      </li>
      <li>
        <p><strong>Entry Size（条目大小）：如果节中包含固定大小的条目（如符号表），该字段指定条目大小。</strong></p>
      </li>
    </ul>

    <p>典型的ELF文件会包含以下节：</p>

    <ul>
      <li>
        <p>.text：代码段。</p>
      </li>
      <li>
        <p>.data：已初始化的数据。</p>
      </li>
      <li>
        <p>.bss：未初始化的数据。</p>
      </li>
      <li>
        <p><strong>.symtab：符号表，包含所有符号及其地址信息。</strong></p>
      </li>
      <li>
        <p><strong>.strtab：字符串表，存储符号名称和节名称。</strong></p>
      </li>
      <li>
        <p>.rel.text 或 .rela.text：重定位表，针对代码段的重定位信息。</p>
      </li>
    </ul>
  </li>
</ol>

<p>我们首先要明确以下信息：</p>

<ul>
  <li>我们通过符号表获取函数的地址以及函数的名称在字符串表中的偏移量，通过字符串表译码偏移量获取函数名称。</li>
  <li>节名称表，符号表和字符串表，虽然中文叫表，但实际上他们是一个节（section）。</li>
  <li>节名称表，符号表和字符串表的节头信息存储在节头表中。节头表是一个数组，这个数组在内存中连续，具体位置（偏移量信息）和大小由ELF头给出。</li>
  <li>ELF头信息位于文件最开头，偏移量为0。</li>
  <li>我们需要的信息已经在上述的结构组成中<strong>黑体加粗</strong>了。</li>
</ul>

<h4 id="获取函数名与函数起始地址的映射的流程">获取函数名与函数起始地址的映射的流程</h4>

<ol>
  <li>
    <p>打开并读取ELF文件</p>

    <p>通过 <code class="language-plaintext highlighter-rouge">fopen</code> 打开传入的ELF文件。如果文件无法打开，输出错误信息并终止程序。</p>

    <p>使用 <code class="language-plaintext highlighter-rouge">fread</code> 读取ELF头部（<code class="language-plaintext highlighter-rouge">Elf32_Ehdr</code>），以获取文件的基本信息，如节头表的偏移和节的数量等。</p>
  </li>
  <li>
    <p>验证文件是否是ELF格式</p>

    <p>检查ELF头部的魔数字段（<code class="language-plaintext highlighter-rouge">e_ident</code>），确保它是一个合法的ELF文件。如果魔数不匹配，输出错误信息并终止程序。</p>
  </li>
  <li>
    <p>读取节头表（Section Headers）</p>

    <p>根据ELF头部中的节头表偏移量，节的数量和每一个节头表的大小，分配足够的内存来存储节头表（<code class="language-plaintext highlighter-rouge">Elf32_Shdr</code>），并使用 <code class="language-plaintext highlighter-rouge">fseek</code> 和 <code class="language-plaintext highlighter-rouge">fread</code> 从文件中读取节头表。</p>
  </li>
  <li>
    <p>读取节名称表</p>

    <p>节名称表是一个特殊的section，用于存储所有节的名称。在节头表中，通过索引找到节名称表（<code class="language-plaintext highlighter-rouge">shstrtab</code>），并读取其内容。</p>
  </li>
  <li>
    <p>查找符号表和字符串表</p>

    <p>遍历所有节头条目，寻找 <code class="language-plaintext highlighter-rouge">.symtab</code>（符号表）和 <code class="language-plaintext highlighter-rouge">.strtab</code>（字符串表）的节头，分别用于存储符号和符号名称。（如果愿意的话，可以根据节头条目提供的节类型信息二次确认我们找到了正确的表）。</p>
  </li>
</ol>

<p>​	如果没有找到这两个节，输出错误信息并终止程序。</p>

<ol>
  <li>
    <p>读取符号表和字符串表</p>

    <p>根据 <code class="language-plaintext highlighter-rouge">.symtab</code> 节头中的偏移和大小，读取符号表。</p>

    <p>根据 <code class="language-plaintext highlighter-rouge">.strtab</code> 节头中的偏移和大小，读取符号名称字符串表。</p>
  </li>
  <li>
    <p>将函数符号添加到符号表</p>

    <p>遍历符号表中的每个符号（<code class="language-plaintext highlighter-rouge">Elf32_Sym</code>），对于每个符号，检查它的类型是否是 <code class="language-plaintext highlighter-rouge">STT_FUNC</code>（即函数类型）。如果是函数符号，调用 <code class="language-plaintext highlighter-rouge">add_symbol</code> 将符号的名称、地址和大小添加到内存中的符号表中。</p>
  </li>
</ol>

<h4 id="实现ftrace">实现FTRACE</h4>

<ol>
  <li>定义<code class="language-plaintext highlighter-rouge">const char *find_symbol(uint64_t addr)</code>函数从保存的映射表中找到内存地址对应的函数</li>
  <li>涉及函数跳转的命令，<code class="language-plaintext highlighter-rouge">jal</code>是直接跳转到目标地址进行函数调用，他的跳转地址是一个立即数，所以是一个编译时已经知道的具体偏移量，因此是直接调用。<code class="language-plaintext highlighter-rouge">jalr</code>的目标地址是由寄存器提供的，这是一个运行时才能确定的偏移量，因此是间接调用。同时由于函数返回时，我们并不能在编译阶段就知道每个函数返回到具体哪个地址，因此我们需要在每次调用前将当前pc存入返回地址寄存器<code class="language-plaintext highlighter-rouge">ra</code>中，利用<code class="language-plaintext highlighter-rouge">jalr ra, 0(ra)</code>实现返回。</li>
  <li>所以我们知道<code class="language-plaintext highlighter-rouge">jal</code>是直接调用，<code class="language-plaintext highlighter-rouge">jalr</code>在传入的立即数为0，且调用了返回地址寄存器<code class="language-plaintext highlighter-rouge">ra</code>时是在返回函数，其他情况下在间接调用，</li>
</ol>

<h3 id="如何实现difftest">如何实现DiffTest</h3>

<p>检测<code class="language-plaintext highlighter-rouge">ref_r</code>中的寄存器信息是否和全局变量<code class="language-plaintext highlighter-rouge">cpu</code>中的一样即可，被忘了pc寄存器</p>

<h2 id="输入输出问题处理">输入输出问题处理</h2>

<p>AM和NEMU的关系是，NEMU通过调用C函数库，模拟了一系列外设的接口，所以我们需要去阅读<code class="language-plaintext highlighter-rouge">$NEMU_HOME/src/device</code>下的文件，看NEMU是如何进行MMIO的，从而我们可以在AM中去读写正确的信息给NEMU处理。</p>

<h3 id="volatile有什么用">volatile有什么用</h3>

<p>比如，假设 <code class="language-plaintext highlighter-rouge">p</code> 指向一个硬件设备的寄存器。如果没有使用 <code class="language-plaintext highlighter-rouge">volatile</code> 修饰，编译器可能会认为这个寄存器的值在程序运行期间不会被外部改变，因此它会把读取 <code class="language-plaintext highlighter-rouge">p</code> 的操作优化为只读取一次，将值缓存在寄存器中，而不再频繁地从该地址重新读取。这对于普通变量来说是合理的优化，但对于设备寄存器，这种优化可能会导致问题。原因是设备寄存器的值可能随时发生变化（比如通过外部硬件设备更新状态），编译器缓存的值不再是最新的，导致程序读取到的设备状态并不正确，从而产生错误行为。</p>

<h3 id="如何实现时钟">如何实现时钟</h3>

<p>阅读NEMU中<code class="language-plaintext highlighter-rouge">timer.c</code>源码，可以看到NEMU的模拟实现是通过调用<code class="language-plaintext highlighter-rouge">&lt;time.h&gt;</code>获得当前的时间，存储到了<code class="language-plaintext highlighter-rouge">rtc_port_base</code>的16个字节中。同时通过其中的<code class="language-plaintext highlighter-rouge">rtc_io_handler</code>可以看到如果我们读取了高位字节，NEMU就会获得最新的时间。所以我们在实现的时候<strong>一定要先读高位字节</strong>，才能刷新设备缓存，获取最新时间。</p>

<h3 id="如何实现malloc">如何实现malloc</h3>

<p>注意好申请的地址要对齐，这里由于我的电脑是64位我就设置了8字节的对齐，即每次申请的空间大小必须向8的整数倍对齐。</p>

<h3 id="如何实现dtrace">如何实现DTRACE</h3>

<p>通过阅读文档我们知道，NEMU通过<code class="language-plaintext highlighter-rouge">map_read</code>和<code class="language-plaintext highlighter-rouge">map_write</code>进行MMIO的操作，所以只要在这两个函数里记录log即可。</p>

<h3 id="如何实现键盘">如何实现键盘</h3>

<p>阅读NEMU中<code class="language-plaintext highlighter-rouge">keyboard.c</code>文件中的<code class="language-plaintext highlighter-rouge">send_key</code>函数可以看到键盘每一次按下的信息是将<code class="language-plaintext highlighter-rouge">keymap</code>中的键位信息与掩码通过按位或的方式记录。我们在AM中解析出这两段信息，写入<code class="language-plaintext highlighter-rouge">kbd</code>即可。</p>

<h3 id="如何实现vga">如何实现VGA</h3>

<p>阅读NEMU中<code class="language-plaintext highlighter-rouge">vga.c</code>可以看到显示的长宽在<code class="language-plaintext highlighter-rouge">vgactl_port_base</code>中的存储顺序。在AM中我们需要提取出这些信息并记录在config中，因为通过阅读<code class="language-plaintext highlighter-rouge">am-test</code>中的测试程序，可以发现程序需要获取这些信息。</p>

<p><code class="language-plaintext highlighter-rouge">__am_gpu_fbdraw</code>中需要将提供的<code class="language-plaintext highlighter-rouge">ctl</code>中的打印信息正确写入VGA的寄存器，这里就是简单的二维数组的映射，我们需要在<code class="language-plaintext highlighter-rouge">x, y</code>作为矩形的左上角端点，写入一个<code class="language-plaintext highlighter-rouge">w*h</code>的矩形图像信息。如果此时要求控制信息要求同步，我们也要将这个信息及时写入VGA的寄存器中。</p>

<h3 id="如何实现声卡">如何实现声卡</h3>

<p>NEMU中由于我们使用<code class="language-plaintext highlighter-rouge">SDL</code>库来模拟声卡，在每次我们调用声卡信息的时候，我们也需要使用刚才的信息初始化一个新的SDL（因为配置信息可能改变），并且设置好他的回调函数。SDL回调函数定义了我们如何处理寄存器中提供的音频信息，由于我们的缓存区有限，我们使用循环队列的方式向缓冲区中写入数据。因此我们需要正确的从缓存区中读出数据并写入stream中。</p>

<p>在AM的<code class="language-plaintext highlighter-rouge">__am_audio_play</code>中，我们需要正确维护好循环队列缓冲区，向其中写入数据。</p>

<h2 id="源码">源码</h2>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* inst.c 粘一些代表性的，不全粘贴 */</span> 
<span class="n">INSTPAT_START</span><span class="p">();</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 000 ????? 01100 11"</span><span class="p">,</span> <span class="n">add</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 000 ????? 01100 11"</span><span class="p">,</span> <span class="n">mul</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)((</span><span class="kt">int64_t</span><span class="p">)(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">*</span> <span class="p">(</span><span class="kt">int64_t</span><span class="p">)(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 001 ????? 01100 11"</span><span class="p">,</span> <span class="n">mulh</span>   <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)(((</span><span class="kt">int64_t</span><span class="p">)(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">*</span> <span class="p">(</span><span class="kt">int64_t</span><span class="p">)(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 010 ????? 01100 11"</span><span class="p">,</span> <span class="n">mulhsu</span> <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">((</span><span class="kt">int64_t</span><span class="p">)(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">*</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 011 ????? 01100 11"</span><span class="p">,</span> <span class="n">mulhu</span>  <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)(((</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">*</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0100000 ????? ????? 000 ????? 01100 11"</span><span class="p">,</span> <span class="n">sub</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">-</span> <span class="n">src2</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 010 ????? 01100 11"</span><span class="p">,</span> <span class="n">slt</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 011 ????? 01100 11"</span><span class="p">,</span> <span class="n">sltu</span>   <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 100 ????? 01100 11"</span><span class="p">,</span> <span class="n">xor</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">^</span> <span class="n">src2</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 100 ????? 01100 11"</span><span class="p">,</span> <span class="n">div</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="n">src1</span> <span class="o">==</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">src2</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">?</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">:</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">/</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">)</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 101 ????? 01100 11"</span><span class="p">,</span> <span class="n">divu</span>   <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">/</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span><span class="p">)</span> <span class="o">:</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="mi">1ll</span> <span class="o">&lt;&lt;</span> <span class="mi">32</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 001 ????? 01100 11"</span><span class="p">,</span> <span class="n">sll</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;&lt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">src2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 101 ????? 01100 11"</span><span class="p">,</span> <span class="n">srl</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;&gt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">src2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0100000 ????? ????? 101 ????? 01100 11"</span><span class="p">,</span> <span class="n">sra</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;&gt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">src2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 110 ????? 01100 11"</span><span class="p">,</span> <span class="n">or</span>     <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">|</span> <span class="n">src2</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 110 ????? 01100 11"</span><span class="p">,</span> <span class="n">rem</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="n">src1</span> <span class="o">==</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">src2</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">%</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">:</span> <span class="n">src1</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000001 ????? ????? 111 ????? 01100 11"</span><span class="p">,</span> <span class="n">remu</span>   <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">%</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">:</span> <span class="n">src1</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 ????? ????? 111 ????? 01100 11"</span><span class="p">,</span> <span class="n">and</span>    <span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">&amp;</span> <span class="n">src2</span><span class="p">);</span>

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 000 ????? 00000 11"</span><span class="p">,</span> <span class="n">lb</span>     <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">SEXT</span><span class="p">(</span><span class="n">Mr</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">1</span><span class="p">),</span> <span class="mi">8</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 001 ????? 00000 11"</span><span class="p">,</span> <span class="n">lh</span>     <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">SEXT</span><span class="p">(</span><span class="n">Mr</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">2</span><span class="p">),</span> <span class="mi">16</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 010 ????? 00000 11"</span><span class="p">,</span> <span class="n">lw</span>     <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">SEXT</span><span class="p">(</span><span class="n">Mr</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">4</span><span class="p">),</span> <span class="mi">32</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 100 ????? 00000 11"</span><span class="p">,</span> <span class="n">lbu</span>    <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">Mr</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">1</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 101 ????? 00000 11"</span><span class="p">,</span> <span class="n">lhu</span>    <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">Mr</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">2</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 000 ????? 00100 11"</span><span class="p">,</span> <span class="n">addi</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">));</span>  <span class="c1">// mv</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 010 ????? 00100 11"</span><span class="p">,</span> <span class="n">slti</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 011 ????? 00100 11"</span><span class="p">,</span> <span class="n">sltiu</span>  <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 100 ????? 00100 11"</span><span class="p">,</span> <span class="n">xori</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">^</span> <span class="n">imm</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"000000? ????? ????? 001 ????? 00100 11"</span><span class="p">,</span> <span class="n">slli</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;&lt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">imm</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"000000? ????? ????? 101 ????? 00100 11"</span><span class="p">,</span> <span class="n">srli</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;&gt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">imm</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"010000? ????? ????? 101 ????? 00100 11"</span><span class="p">,</span> <span class="n">srai</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;&gt;</span> <span class="n">BITS</span><span class="p">(</span><span class="n">imm</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 110 ????? 00100 11"</span><span class="p">,</span> <span class="n">ori</span>    <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">|</span> <span class="n">imm</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 111 ????? 00100 11"</span><span class="p">,</span> <span class="n">andi</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">&amp;</span> <span class="n">imm</span><span class="p">);</span>
  <span class="c1">// INSTPAT("??????? ????? ????? 000 ????? 00011 11", fence  , I, R(rd) = src1 &amp; imm);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 000 ????? 11001 11"</span><span class="p">,</span> <span class="n">jalr</span>   <span class="p">,</span> <span class="n">I</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">snpc</span><span class="p">;</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">&amp;</span> <span class="o">-</span><span class="mi">2ull</span><span class="p">;</span> <span class="n">check_jalr</span><span class="p">(</span><span class="n">rd</span><span class="p">,</span> <span class="n">imm</span><span class="p">,</span> <span class="n">s</span><span class="p">));</span> <span class="c1">// ret</span>

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 000 ????? 01000 11"</span><span class="p">,</span> <span class="n">sb</span>     <span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">Mw</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="n">src2</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 001 ????? 01000 11"</span><span class="p">,</span> <span class="n">sh</span>     <span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">Mw</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">2</span><span class="p">,</span> <span class="n">src2</span><span class="p">));</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 010 ????? 01000 11"</span><span class="p">,</span> <span class="n">sw</span>     <span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">Mw</span><span class="p">((</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">),</span> <span class="mi">4</span><span class="p">,</span> <span class="n">src2</span><span class="p">));</span>

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 000 ????? 11000 11"</span><span class="p">,</span> <span class="n">beq</span>    <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">==</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 001 ????? 11000 11"</span><span class="p">,</span> <span class="n">bne</span>    <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="n">src1</span> <span class="o">!=</span> <span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 100 ????? 11000 11"</span><span class="p">,</span> <span class="n">blt</span>    <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 101 ????? 11000 11"</span><span class="p">,</span> <span class="n">bge</span>    <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 110 ????? 11000 11"</span><span class="p">,</span> <span class="n">bltu</span>   <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? 111 ????? 11000 11"</span><span class="p">,</span> <span class="n">bgeu</span>   <span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src1</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">src2</span> <span class="o">?</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">imm</span><span class="p">)</span> <span class="o">:</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? ??? ????? 00101 11"</span><span class="p">,</span> <span class="n">auipc</span>  <span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="n">imm</span><span class="p">);</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? ??? ????? 01101 11"</span><span class="p">,</span> <span class="n">lui</span>    <span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">imm</span><span class="p">);</span>

  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? ??? ????? 11011 11"</span><span class="p">,</span> <span class="n">jal</span>    <span class="p">,</span> <span class="n">J</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="n">rd</span><span class="p">)</span> <span class="o">=</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">snpc</span><span class="p">;</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span> <span class="o">=</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span> <span class="o">+</span> <span class="n">imm</span><span class="p">;</span> <span class="n">check_jal</span><span class="p">(</span><span class="n">s</span><span class="p">));</span>


  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"0000000 00001 00000 000 00000 11100 11"</span><span class="p">,</span> <span class="n">ebreak</span> <span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">NEMUTRAP</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">,</span> <span class="n">R</span><span class="p">(</span><span class="mi">10</span><span class="p">)));</span> <span class="c1">// R(10) is $a0</span>
  <span class="n">INSTPAT</span><span class="p">(</span><span class="s">"??????? ????? ????? ??? ????? ????? ??"</span><span class="p">,</span> <span class="n">inv</span>    <span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">INV</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">));</span>

<span class="kt">void</span> <span class="nf">check_jal</span><span class="p">(</span><span class="n">Decode</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">elf_loaded</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">func_name</span> <span class="o">=</span> <span class="n">find_symbol</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">func_name</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">call_depth</span><span class="o">++</span><span class="p">;</span>
        <span class="n">log_write</span><span class="p">(</span><span class="s">"F</span><span class="se">\t</span><span class="s">%#010x</span><span class="se">\t</span><span class="s">%*sCall to %s @ %#010x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">,</span> <span class="n">call_depth</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="s">""</span><span class="p">,</span> <span class="n">func_name</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">check_jalr</span><span class="p">(</span><span class="n">word_t</span> <span class="n">rd</span><span class="p">,</span> <span class="n">word_t</span> <span class="n">imm</span><span class="p">,</span> <span class="n">Decode</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">isa</span><span class="p">.</span><span class="n">inst</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">rs1</span> <span class="o">=</span> <span class="n">BITS</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">15</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">elf_loaded</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">rd</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">rs1</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">imm</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Function return</span>
        <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">func_name</span> <span class="o">=</span> <span class="n">find_symbol</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">func_name</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">log_write</span><span class="p">(</span><span class="s">"F</span><span class="se">\t</span><span class="s">%#010x</span><span class="se">\t</span><span class="s">%*sReturn from %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">,</span> <span class="n">call_depth</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="s">""</span><span class="p">,</span> <span class="n">func_name</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">call_depth</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">call_depth</span><span class="o">--</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="c1">// Indirect function call</span>
        <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">func_name</span> <span class="o">=</span> <span class="n">find_symbol</span><span class="p">(</span><span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">func_name</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">call_depth</span><span class="o">++</span><span class="p">;</span>
            <span class="n">log_write</span><span class="p">(</span><span class="s">"F</span><span class="se">\t</span><span class="s">%#010x</span><span class="se">\t</span><span class="s">%*sIndirect call to %s @ %#010x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">pc</span><span class="p">,</span> <span class="n">call_depth</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="s">""</span><span class="p">,</span> <span class="n">func_name</span><span class="p">,</span> <span class="n">s</span><span class="o">-&gt;</span><span class="n">dnpc</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* stdio.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">int</span> <span class="nf">vsprintf</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="kt">va_list</span> <span class="n">ap</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span><span class="o">*</span> <span class="n">buf</span> <span class="o">=</span> <span class="n">out</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">total_len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">!=</span> <span class="sc">'%'</span><span class="p">)</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="o">*</span><span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
            <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
            <span class="c1">// Parse flags</span>
            <span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="kt">int</span> <span class="n">precision</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
            <span class="c1">// int length = 0;</span>
            <span class="kt">int</span> <span class="n">specifier</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

            <span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'-'</span> <span class="o">||</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'+'</span> <span class="o">||</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">' '</span> <span class="o">||</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'#'</span> <span class="o">||</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'0'</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">switch</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span><span class="p">)</span> <span class="p">{</span>
                    <span class="k">case</span> <span class="sc">'#'</span><span class="p">:</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x02</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// Hash</span>
                    <span class="k">case</span> <span class="sc">'+'</span><span class="p">:</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x04</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// Plus sign</span>
                    <span class="k">case</span> <span class="sc">' '</span><span class="p">:</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x08</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// Space</span>
                    <span class="k">case</span> <span class="sc">'-'</span><span class="p">:</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x10</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// Left align</span>
                    <span class="k">case</span> <span class="sc">'0'</span><span class="p">:</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x20</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// Zero padding</span>
                <span class="p">}</span>
                <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
            <span class="p">}</span>

            <span class="c1">// Parse width</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'*'</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">width</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
                <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">&gt;=</span> <span class="sc">'0'</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">&lt;=</span> <span class="sc">'9'</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">width</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="mi">10</span> <span class="o">+</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span><span class="o">++</span> <span class="o">-</span> <span class="sc">'0'</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>

            <span class="c1">// Parse precision</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'.'</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
                <span class="n">precision</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">'*'</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">precision</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
                    <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">&gt;=</span> <span class="sc">'0'</span> <span class="o">&amp;&amp;</span> <span class="o">*</span><span class="n">fmt</span> <span class="o">&lt;=</span> <span class="sc">'9'</span><span class="p">)</span> <span class="p">{</span>
                        <span class="n">precision</span> <span class="o">=</span> <span class="n">precision</span> <span class="o">*</span> <span class="mi">10</span> <span class="o">+</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span><span class="o">++</span> <span class="o">-</span> <span class="sc">'0'</span><span class="p">);</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span>

            <span class="c1">// // Parse length modifier</span>
            <span class="c1">// if (*fmt == 'h' || *fmt == 'l') {</span>
            <span class="c1">//     length = *fmt++;</span>
            <span class="c1">// }</span>

            <span class="c1">// Parse specifier</span>
            <span class="n">specifier</span> <span class="o">=</span> <span class="o">*</span><span class="n">fmt</span><span class="o">++</span><span class="p">;</span>

            <span class="c1">// Handle specifier</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'d'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'i'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
                <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">int_to_str</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">precision</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                <span class="p">}</span>
                <span class="n">total_len</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'o'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span><span class="p">);</span>
                <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">int_to_str</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">precision</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                <span class="p">}</span>
                <span class="n">total_len</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'u'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span><span class="p">);</span>
                <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">int_to_str</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">precision</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                <span class="p">}</span>
                <span class="n">total_len</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'x'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'X'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span><span class="p">);</span>
                <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'X'</span><span class="p">)</span> <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x01</span><span class="p">;</span> <span class="c1">// Uppercase</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">int_to_str</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">precision</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                <span class="p">}</span>
                <span class="n">total_len</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'c'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span><span class="p">)</span><span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
                <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span>
                <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'s'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">char</span> <span class="o">*</span><span class="n">str</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span><span class="p">);</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">precision</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="n">strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">width</span> <span class="o">&gt;</span> <span class="n">len</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// Right align</span>
                    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">width</span> <span class="o">-</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                        <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                        <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
                    <span class="p">}</span>
                <span class="p">}</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span> <span class="o">&amp;&amp;</span> <span class="n">str</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">str</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                    <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">width</span> <span class="o">&gt;</span> <span class="n">len</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// Left align</span>
                    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">width</span> <span class="o">-</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                        <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                        <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'p'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span><span class="p">);</span>
                <span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">value</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">ptr</span><span class="p">;</span>
                <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
                <span class="n">flags</span> <span class="o">|=</span> <span class="mh">0x02</span><span class="p">;</span> <span class="c1">// Force '0x'</span>
                <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">int_to_str</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">precision</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">?</span> <span class="n">precision</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                    <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                <span class="p">}</span>
                <span class="n">total_len</span> <span class="o">+=</span> <span class="n">len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'f'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'F'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'e'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'E'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'g'</span> <span class="o">||</span> <span class="n">specifier</span> <span class="o">==</span> <span class="sc">'G'</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
                <span class="c1">// double value = va_arg(args, double);</span>
                <span class="c1">// char temp[320];</span>
                <span class="c1">// int len = double_to_str(value, temp, precision &gt;= 0 ? precision : 6, specifier, flags, width);</span>
                <span class="c1">// for (int i = 0; i &lt; len; i++) {</span>
                <span class="c1">//     /*buf++ = temp[i];</span>
                <span class="c1">// }</span>
                <span class="c1">// total_len += len;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'%'</span><span class="p">)</span> <span class="p">{</span>
                <span class="o">*</span><span class="n">buf</span><span class="o">++</span> <span class="o">=</span> <span class="sc">'%'</span><span class="p">;</span>
                <span class="n">total_len</span><span class="o">++</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">specifier</span> <span class="o">==</span> <span class="sc">'n'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span><span class="p">);</span>
                <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">total_len</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="c1">// Invalid specifier</span>
                <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="o">*</span><span class="n">buf</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">buf</span> <span class="o">-</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">sprintf</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="p">...)</span> <span class="p">{</span>
    <span class="kt">va_list</span> <span class="n">args</span><span class="p">;</span>
    <span class="n">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">fmt</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">total_len</span> <span class="o">=</span> <span class="n">vsprintf</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">fmt</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
    <span class="n">va_end</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">total_len</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">snprintf</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">n</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="p">...)</span> <span class="p">{</span>
  <span class="n">panic</span><span class="p">(</span><span class="s">"Not implemented"</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">vsnprintf</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">out</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">n</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="kt">va_list</span> <span class="n">ap</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">panic</span><span class="p">(</span><span class="s">"Not implemented"</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">int</span> <span class="nf">int_to_str</span><span class="p">(</span><span class="kt">int</span> <span class="n">value</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">int</span> <span class="n">base</span><span class="p">,</span> <span class="kt">int</span> <span class="n">is_unsigned</span><span class="p">,</span> <span class="kt">int</span> <span class="n">width</span><span class="p">,</span> <span class="kt">int</span> <span class="n">precision</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="n">temp</span><span class="p">[</span><span class="mi">65</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">uvalue</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">is_negative</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">is_unsigned</span> <span class="o">&amp;&amp;</span> <span class="n">value</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">is_negative</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="n">uvalue</span> <span class="o">=</span> <span class="o">-</span><span class="n">value</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">uvalue</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">uvalue</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="kt">int</span> <span class="n">digit</span> <span class="o">=</span> <span class="n">uvalue</span> <span class="o">%</span> <span class="n">base</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">digit</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">digit</span> <span class="o">+</span> <span class="sc">'0'</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x01</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Uppercase for X</span>
                    <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">digit</span> <span class="o">-</span> <span class="mi">10</span> <span class="o">+</span> <span class="sc">'A'</span><span class="p">;</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">digit</span> <span class="o">-</span> <span class="mi">10</span> <span class="o">+</span> <span class="sc">'a'</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="n">uvalue</span> <span class="o">/=</span> <span class="n">base</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Handle precision</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">precision</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Add prefix for '#' flag</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x02</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">base</span> <span class="o">==</span> <span class="mi">8</span> <span class="o">&amp;&amp;</span> <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'0'</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">base</span> <span class="o">==</span> <span class="mi">16</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x01</span> <span class="o">?</span> <span class="sc">'X'</span> <span class="o">:</span> <span class="sc">'x'</span><span class="p">;</span>
            <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="p">{</span>
          <span class="n">assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
    <span class="c1">// Handle zero-padding and width</span>
    <span class="kt">int</span> <span class="n">padding</span> <span class="o">=</span> <span class="n">width</span> <span class="o">-</span> <span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 1-width for the sign</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">padding</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// Right align</span>
      <span class="k">while</span> <span class="p">(</span><span class="n">padding</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">is_negative</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'-'</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x04</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '+' flag</span>
        <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'+'</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x08</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// ' ' flag</span>
        <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">padding</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// Right align</span>
      <span class="k">while</span> <span class="p">(</span><span class="n">padding</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="n">reverse_str</span><span class="p">(</span><span class="n">temp</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>

    <span class="c1">// Copy to buffer</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">*</span><span class="n">buffer</span><span class="o">++</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
    <span class="p">}</span>

    <span class="c1">// Right padding if left align</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">padding</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="mh">0x10</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">padding</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">buffer</span><span class="o">++</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* iringbuf.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">void</span> <span class="nf">record_inst</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">pc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">asm_code</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">inst_buf</span><span class="p">[</span><span class="n">inst_buf_pos</span><span class="p">].</span><span class="n">pc</span> <span class="o">=</span> <span class="n">pc</span><span class="p">;</span>
    <span class="c1">// Safely copy the assembly code to prevent buffer overflow</span>
    <span class="n">strncpy</span><span class="p">(</span><span class="n">inst_buf</span><span class="p">[</span><span class="n">inst_buf_pos</span><span class="p">].</span><span class="n">asm_code</span><span class="p">,</span> <span class="n">asm_code</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">inst_buf</span><span class="p">[</span><span class="n">inst_buf_pos</span><span class="p">].</span><span class="n">asm_code</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">inst_buf</span><span class="p">[</span><span class="n">inst_buf_pos</span><span class="p">].</span><span class="n">asm_code</span><span class="p">[</span><span class="k">sizeof</span><span class="p">(</span><span class="n">inst_buf</span><span class="p">[</span><span class="n">inst_buf_pos</span><span class="p">].</span><span class="n">asm_code</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span> <span class="c1">// Ensure null-termination</span>
    <span class="n">inst_buf_pos</span> <span class="o">=</span> <span class="p">(</span><span class="n">inst_buf_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">INST_BUF_SIZE</span><span class="p">;</span>  <span class="c1">// Update write position to create a ring buffer</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">inst_buf_count</span> <span class="o">&lt;</span> <span class="n">INST_BUF_SIZE</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">inst_buf_count</span><span class="o">++</span><span class="p">;</span>  <span class="c1">// Increment the count of recorded instructions</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* elf.c */</span> 

<span class="cp">#include</span> <span class="cpf">&lt;elf.h&gt;</span><span class="cp">
</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">size</span><span class="p">;</span>
<span class="p">}</span> <span class="n">FunctionSymbol</span><span class="p">;</span>

<span class="k">static</span> <span class="n">FunctionSymbol</span> <span class="o">*</span><span class="n">symbol_table</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">int</span> <span class="n">symbol_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">int</span> <span class="n">symbol_capacity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">bool</span> <span class="n">elf_loaded</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">add_symbol</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">size</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">symbol_count</span> <span class="o">&gt;=</span> <span class="n">symbol_capacity</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">symbol_capacity</span> <span class="o">=</span> <span class="n">symbol_capacity</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">?</span> <span class="mi">1024</span> <span class="o">:</span> <span class="n">symbol_capacity</span> <span class="o">*</span> <span class="mi">2</span><span class="p">;</span>
        <span class="n">symbol_table</span> <span class="o">=</span> <span class="n">realloc</span><span class="p">(</span><span class="n">symbol_table</span><span class="p">,</span> <span class="n">symbol_capacity</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">FunctionSymbol</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="n">symbol_table</span><span class="p">[</span><span class="n">symbol_count</span><span class="p">].</span><span class="n">name</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">name</span><span class="p">);</span>
    <span class="n">symbol_table</span><span class="p">[</span><span class="n">symbol_count</span><span class="p">].</span><span class="n">addr</span> <span class="o">=</span> <span class="n">addr</span><span class="p">;</span>
    <span class="n">symbol_table</span><span class="p">[</span><span class="n">symbol_count</span><span class="p">].</span><span class="n">size</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
    <span class="n">symbol_count</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">find_symbol</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">elf_loaded</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">symbol_count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">addr</span> <span class="o">&gt;=</span> <span class="n">symbol_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">addr</span> <span class="o">&amp;&amp;</span> <span class="n">addr</span> <span class="o">&lt;</span> <span class="n">symbol_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">addr</span> <span class="o">+</span> <span class="n">symbol_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">size</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="n">symbol_table</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">name</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">init_elf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">elf_file</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">elf_file</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">elf_loaded</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">elf_file</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s">"Cannot open '%s'"</span><span class="p">,</span> <span class="n">elf_file</span><span class="p">);</span>

    <span class="n">elf_loaded</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>

    <span class="c1">// Read ELF header</span>
    <span class="n">Elf32_Ehdr</span> <span class="n">ehdr</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fread</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ehdr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Elf32_Ehdr</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read ELF header</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Verify ELF magic number</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">memcmp</span><span class="p">(</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_ident</span><span class="p">,</span> <span class="n">ELFMAG</span><span class="p">,</span> <span class="n">SELFMAG</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Not an ELF file</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Read section headers</span>
    <span class="n">Elf32_Shdr</span> <span class="o">*</span><span class="n">shdrs</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_shentsize</span> <span class="o">*</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shnum</span><span class="p">);</span>
    <span class="n">fseek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shoff</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fread</span><span class="p">(</span><span class="n">shdrs</span><span class="p">,</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shentsize</span><span class="p">,</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shnum</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span> <span class="o">!=</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shnum</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read section headers</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Read section header string table</span>
    <span class="n">Elf32_Shdr</span> <span class="n">shstr_shdr</span> <span class="o">=</span> <span class="n">shdrs</span><span class="p">[</span><span class="n">ehdr</span><span class="p">.</span><span class="n">e_shstrndx</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">shstrtab</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">shstr_shdr</span><span class="p">.</span><span class="n">sh_size</span><span class="p">);</span>
    <span class="n">fseek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">shstr_shdr</span><span class="p">.</span><span class="n">sh_offset</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fread</span><span class="p">(</span><span class="n">shstrtab</span><span class="p">,</span> <span class="n">shstr_shdr</span><span class="p">.</span><span class="n">sh_size</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read section header string table</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Find .symtab and .strtab sections</span>
    <span class="n">Elf32_Shdr</span> <span class="o">*</span><span class="n">symtab_shdr</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">Elf32_Shdr</span> <span class="o">*</span><span class="n">strtab_shdr</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">ehdr</span><span class="p">.</span><span class="n">e_shnum</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">section_name</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">shstrtab</span><span class="p">[</span><span class="n">shdrs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">sh_name</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">shdrs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">sh_type</span> <span class="o">==</span> <span class="n">SHT_SYMTAB</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">section_name</span><span class="p">,</span> <span class="s">".symtab"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">symtab_shdr</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">shdrs</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">shdrs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">sh_type</span> <span class="o">==</span> <span class="n">SHT_STRTAB</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">section_name</span><span class="p">,</span> <span class="s">".strtab"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">strtab_shdr</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">shdrs</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">symtab_shdr</span> <span class="o">==</span> <span class="nb">NULL</span> <span class="o">||</span> <span class="n">strtab_shdr</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to find .symtab or .strtab in ELF file</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Read symbol table</span>
    <span class="kt">int</span> <span class="n">sym_count</span> <span class="o">=</span> <span class="n">symtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_size</span> <span class="o">/</span> <span class="n">symtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_entsize</span><span class="p">;</span>
    <span class="n">Elf32_Sym</span> <span class="o">*</span><span class="n">symtab</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">symtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_size</span><span class="p">);</span>
    <span class="n">fseek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">symtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_offset</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fread</span><span class="p">(</span><span class="n">symtab</span><span class="p">,</span> <span class="n">symtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_entsize</span><span class="p">,</span> <span class="n">sym_count</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span> <span class="o">!=</span> <span class="n">sym_count</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read symbol table</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Read string table</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">strtab</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">strtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_size</span><span class="p">);</span>
    <span class="n">fseek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">strtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_offset</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fread</span><span class="p">(</span><span class="n">strtab</span><span class="p">,</span> <span class="n">strtab_shdr</span><span class="o">-&gt;</span><span class="n">sh_size</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Failed to read string table</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Store function symbols</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">sym_count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Elf32_Sym</span> <span class="n">sym</span> <span class="o">=</span> <span class="n">symtab</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">name</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">strtab</span><span class="p">[</span><span class="n">sym</span><span class="p">.</span><span class="n">st_name</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">ELF32_ST_TYPE</span><span class="p">(</span><span class="n">sym</span><span class="p">.</span><span class="n">st_info</span><span class="p">)</span> <span class="o">==</span> <span class="n">STT_FUNC</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">add_symbol</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">sym</span><span class="p">.</span><span class="n">st_value</span><span class="p">,</span> <span class="n">sym</span><span class="p">.</span><span class="n">st_size</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Free allocated memory</span>
    <span class="n">free</span><span class="p">(</span><span class="n">shdrs</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">shstrtab</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">symtab</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">strtab</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* gpu.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">void</span> <span class="nf">__am_gpu_config</span><span class="p">(</span><span class="n">AM_GPU_CONFIG_T</span> <span class="o">*</span><span class="n">cfg</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint32_t</span> <span class="n">data</span> <span class="o">=</span> <span class="n">inl</span><span class="p">(</span><span class="n">VGACTL_ADDR</span><span class="p">);</span>
  <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="p">(</span><span class="n">data</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">height</span> <span class="o">=</span> <span class="n">data</span> <span class="o">&amp;</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">vmemsz</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">height</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint32_t</span><span class="p">);</span>
  <span class="o">*</span><span class="n">cfg</span> <span class="o">=</span> <span class="p">(</span><span class="n">AM_GPU_CONFIG_T</span><span class="p">)</span> <span class="p">{</span>
    <span class="p">.</span><span class="n">present</span> <span class="o">=</span> <span class="nb">true</span><span class="p">,</span> <span class="p">.</span><span class="n">has_accel</span> <span class="o">=</span> <span class="nb">false</span><span class="p">,</span>
    <span class="p">.</span><span class="n">width</span> <span class="o">=</span> <span class="n">width</span><span class="p">,</span> <span class="p">.</span><span class="n">height</span> <span class="o">=</span> <span class="n">height</span><span class="p">,</span>
    <span class="p">.</span><span class="n">vmemsz</span> <span class="o">=</span> <span class="n">vmemsz</span>
  <span class="p">};</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">__am_gpu_fbdraw</span><span class="p">(</span><span class="n">AM_GPU_FBDRAW_T</span> <span class="o">*</span><span class="n">ctl</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">ctl</span><span class="o">-&gt;</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">ctl</span><span class="o">-&gt;</span><span class="n">y</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="n">ctl</span><span class="o">-&gt;</span><span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">ctl</span><span class="o">-&gt;</span><span class="n">h</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="n">inl</span><span class="p">(</span><span class="n">VGACTL_ADDR</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="n">inl</span><span class="p">(</span><span class="n">VGACTL_ADDR</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffff</span><span class="p">;</span>

  <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">pixels</span> <span class="o">=</span> <span class="n">ctl</span><span class="o">-&gt;</span><span class="n">pixels</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">fb</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">FB_ADDR</span><span class="p">;</span>

  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">+</span> <span class="n">h</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">height</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">+</span> <span class="n">w</span> <span class="o">&amp;&amp;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">width</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">fb</span><span class="p">[</span><span class="n">i</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">pixels</span><span class="p">[(</span><span class="n">i</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span> <span class="o">*</span> <span class="n">w</span> <span class="o">+</span> <span class="p">(</span><span class="n">j</span> <span class="o">-</span> <span class="n">x</span><span class="p">)];</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">sync</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">outl</span><span class="p">(</span><span class="n">SYNC_ADDR</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* audio.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">void</span> <span class="nf">__am_audio_play</span><span class="p">(</span><span class="n">AM_AUDIO_PLAY_T</span> <span class="o">*</span><span class="n">ctl</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">audio_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">start</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">sbuf_size</span> <span class="o">=</span> <span class="n">inl</span><span class="p">(</span><span class="n">AUDIO_SBUF_SIZE_ADDR</span><span class="p">);</span>
  <span class="kt">uint32_t</span> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">end</span> <span class="o">-</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">start</span><span class="p">;</span>

  <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">ab</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">AUDIO_SBUF_ADDR</span><span class="p">;</span> 
  <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
    <span class="n">ab</span><span class="p">[</span><span class="n">sbuf_pos</span><span class="p">]</span> <span class="o">=</span> <span class="n">audio_data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="n">sbuf_pos</span> <span class="o">=</span> <span class="p">(</span><span class="n">sbuf_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">sbuf_size</span><span class="p">;</span>  
  <span class="p">}</span>
  <span class="n">outl</span><span class="p">(</span><span class="n">AUDIO_COUNT_ADDR</span><span class="p">,</span> <span class="n">inl</span><span class="p">(</span><span class="n">AUDIO_COUNT_ADDR</span><span class="p">)</span> <span class="o">+</span> <span class="n">len</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* am/audio.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">void</span> <span class="nf">__am_audio_play</span><span class="p">(</span><span class="n">AM_AUDIO_PLAY_T</span> <span class="o">*</span><span class="n">ctl</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">audio_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">start</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">sbuf_size</span> <span class="o">=</span> <span class="n">inl</span><span class="p">(</span><span class="n">AUDIO_SBUF_SIZE_ADDR</span><span class="p">);</span>
  <span class="kt">uint32_t</span> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">end</span> <span class="o">-</span> <span class="p">(</span><span class="n">ctl</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">).</span><span class="n">start</span><span class="p">;</span>

  <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">ab</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">AUDIO_SBUF_ADDR</span><span class="p">;</span> 
  <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
    <span class="n">ab</span><span class="p">[</span><span class="n">sbuf_pos</span><span class="p">]</span> <span class="o">=</span> <span class="n">audio_data</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="n">sbuf_pos</span> <span class="o">=</span> <span class="p">(</span><span class="n">sbuf_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">sbuf_size</span><span class="p">;</span>  
  <span class="p">}</span>
  <span class="n">outl</span><span class="p">(</span><span class="n">AUDIO_COUNT_ADDR</span><span class="p">,</span> <span class="n">inl</span><span class="p">(</span><span class="n">AUDIO_COUNT_ADDR</span><span class="p">)</span> <span class="o">+</span> <span class="n">len</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* nemu/audio.c 粘一些代表性的，不全粘贴 */</span> 

<span class="kt">void</span> <span class="nf">init_sound</span><span class="p">();</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">audio_io_handler</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">,</span> <span class="n">bool</span> <span class="n">is_write</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span><span class="p">(</span><span class="n">audio_base</span><span class="p">[</span><span class="n">reg_init</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">){</span>
    <span class="n">init_sound</span><span class="p">();</span>
    <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_init</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">sdl_audio_callback</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">userdata</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
  <span class="n">SDL_memset</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
  <span class="kt">uint32_t</span> <span class="n">used_cnt</span> <span class="o">=</span> <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_count</span><span class="p">];</span>
  <span class="n">len</span> <span class="o">=</span> <span class="n">len</span> <span class="o">&gt;</span> <span class="n">used_cnt</span> <span class="o">?</span> <span class="n">used_cnt</span> <span class="o">:</span> <span class="n">len</span><span class="p">;</span>
  
  <span class="kt">uint32_t</span> <span class="n">sbuf_size</span> <span class="o">=</span> <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_sbuf_size</span><span class="p">];</span>
  <span class="k">if</span><span class="p">(</span> <span class="p">(</span><span class="n">sbuf_pos</span> <span class="o">+</span> <span class="n">len</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">sbuf_size</span> <span class="p">){</span>
    <span class="n">SDL_MixAudio</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="n">sbuf</span> <span class="o">+</span> <span class="n">sbuf_pos</span><span class="p">,</span> <span class="n">sbuf_size</span> <span class="o">-</span> <span class="n">sbuf_pos</span> <span class="p">,</span> <span class="n">SDL_MIX_MAXVOLUME</span><span class="p">);</span>
    <span class="n">SDL_MixAudio</span><span class="p">(</span><span class="n">stream</span> <span class="o">+</span>  <span class="p">(</span><span class="n">sbuf_size</span> <span class="o">-</span> <span class="n">sbuf_pos</span><span class="p">),</span> <span class="n">sbuf</span><span class="p">,</span> <span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="n">sbuf_size</span> <span class="o">-</span> <span class="n">sbuf_pos</span><span class="p">),</span> <span class="n">SDL_MIX_MAXVOLUME</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> 
    <span class="n">SDL_MixAudio</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="n">sbuf</span> <span class="o">+</span> <span class="n">sbuf_pos</span><span class="p">,</span> <span class="n">len</span> <span class="p">,</span> <span class="n">SDL_MIX_MAXVOLUME</span><span class="p">);</span>
  <span class="n">sbuf_pos</span> <span class="o">=</span> <span class="p">(</span><span class="n">sbuf_pos</span> <span class="o">+</span> <span class="n">len</span><span class="p">)</span> <span class="o">%</span> <span class="n">sbuf_size</span><span class="p">;</span>
  <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_count</span><span class="p">]</span> <span class="o">-=</span> <span class="n">len</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">init_sound</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">SDL_AudioSpec</span> <span class="n">s</span> <span class="o">=</span> <span class="p">{};</span>
  <span class="n">s</span><span class="p">.</span><span class="n">format</span> <span class="o">=</span> <span class="n">AUDIO_S16SYS</span><span class="p">;</span>
  <span class="n">s</span><span class="p">.</span><span class="n">userdata</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
  <span class="n">s</span><span class="p">.</span><span class="n">freq</span> <span class="o">=</span> <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_freq</span><span class="p">];</span>
  <span class="n">s</span><span class="p">.</span><span class="n">channels</span> <span class="o">=</span> <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_channels</span><span class="p">];</span>
  <span class="n">s</span><span class="p">.</span><span class="n">samples</span> <span class="o">=</span> <span class="n">audio_base</span><span class="p">[</span><span class="n">reg_samples</span><span class="p">];</span>
  <span class="n">s</span><span class="p">.</span><span class="n">callback</span> <span class="o">=</span> <span class="n">sdl_audio_callback</span><span class="p">;</span>
  <span class="n">SDL_InitSubSystem</span><span class="p">(</span><span class="n">SDL_INIT_AUDIO</span><span class="p">);</span>
  <span class="n">SDL_OpenAudio</span><span class="p">(</span><span class="o">&amp;</span><span class="n">s</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
  <span class="n">SDL_PauseAudio</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Zhejian Lai</name><email>laizj@smail.nju.edu.cn</email><uri>https://www.cnblogs.com/DreamW1ngs</uri></author><category term="ICS" /><summary type="html"><![CDATA[在实现和调试 RISC-V 架构下的 NEMU 仿真器和 AM 运行环境过程中可能遇到的问题及其解决方案，包括指令解析、输入输出、ELF 文件解析、klib 库、ftrace/mtrace/itrace/difftest 的实现，以及与硬件模拟相关的设备驱动。]]></summary></entry></feed>