aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/juicebox_asm/imm.rs.html44
-rw-r--r--src/juicebox_asm/insn.rs.html6
-rw-r--r--src/juicebox_asm/label.rs.html28
-rw-r--r--src/juicebox_asm/lib.rs.html286
-rw-r--r--src/juicebox_asm/prelude.rs.html6
-rw-r--r--src/juicebox_asm/reg.rs.html46
-rw-r--r--src/juicebox_asm/rt.rs.html6
7 files changed, 359 insertions, 63 deletions
diff --git a/src/juicebox_asm/imm.rs.html b/src/juicebox_asm/imm.rs.html
index 0990c92..0a9933e 100644
--- a/src/juicebox_asm/imm.rs.html
+++ b/src/juicebox_asm/imm.rs.html
@@ -33,15 +33,33 @@
<a href="#33" id="33">33</a>
<a href="#34" id="34">34</a>
<a href="#35" id="35">35</a>
-</pre><pre class="rust"><code><span class="doccomment">/// Trait to interact with immediate operands.
+<a href="#36" id="36">36</a>
+<a href="#37" id="37">37</a>
+<a href="#38" id="38">38</a>
+<a href="#39" id="39">39</a>
+<a href="#40" id="40">40</a>
+<a href="#41" id="41">41</a>
+<a href="#42" id="42">42</a>
+<a href="#43" id="43">43</a>
+<a href="#44" id="44">44</a>
+<a href="#45" id="45">45</a>
+<a href="#46" id="46">46</a>
+<a href="#47" id="47">47</a>
+<a href="#48" id="48">48</a>
+<a href="#49" id="49">49</a>
+<a href="#50" id="50">50</a>
+</pre><pre class="rust"><code><span class="doccomment">//! Definition of different immediate types which are used as input operands for various
+//! instructions.
+
+/// Trait to interact with immediate operands.
</span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Imm {
<span class="doccomment">/// Get immediate operand as slice of bytes.
</span><span class="kw">fn </span>bytes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>[u8];
}
<span class="macro">macro_rules! </span>impl_imm {
- (<span class="macro-nonterminal">$name</span>:ident, <span class="macro-nonterminal">$size</span>:expr, from: $( <span class="macro-nonterminal">$from</span>:ty ),* $(,)<span class="question-mark">?</span>) =&gt; {
- <span class="doccomment">/// Immediate operand.
+ (<span class="attr">#[<span class="macro-nonterminal">$doc</span>:meta] </span><span class="macro-nonterminal">$name</span>:ident, <span class="macro-nonterminal">$size</span>:expr, from: { $( <span class="macro-nonterminal">$from</span>:ty ),* $(,)<span class="question-mark">? </span>}) =&gt; {
+ <span class="attr">#[<span class="macro-nonterminal">$doc</span>]
</span><span class="kw">pub struct </span><span class="macro-nonterminal">$name</span>([u8; <span class="macro-nonterminal">$size</span>]);
<span class="kw">impl </span>Imm <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
@@ -64,9 +82,21 @@
}
}
-<span class="macro">impl_imm!</span>(Imm8, <span class="number">1</span>, from: u8, i8);
-<span class="macro">impl_imm!</span>(Imm16, <span class="number">2</span>, from: u16, i16, u8, i8);
-<span class="macro">impl_imm!</span>(Imm32, <span class="number">4</span>, from: u32, i32, u16, i16, u8, i8);
-<span class="macro">impl_imm!</span>(Imm64, <span class="number">8</span>, from: u64, i64, u32, i32, u16, i16, u8, i8);
+<span class="macro">impl_imm!</span>(
+ <span class="doccomment">/// Type representing an 8 bit immediate.
+ </span>Imm8, <span class="number">1</span>, from: { u8, i8 }
+);
+<span class="macro">impl_imm!</span>(
+ <span class="doccomment">/// Type representing a 16 bit immediate.
+ </span>Imm16, <span class="number">2</span>, from: { u16, i16, u8, i8 }
+);
+<span class="macro">impl_imm!</span>(
+ <span class="doccomment">/// Type representing a 32 bit immediate.
+ </span>Imm32, <span class="number">4</span>, from: { u32, i32, u16, i16, u8, i8 }
+);
+<span class="macro">impl_imm!</span>(
+ <span class="doccomment">/// Type representing a 64 bit immediate.
+ </span>Imm64, <span class="number">8</span>, from: { u64, i64, u32, i32, u16, i16, u8, i8 }
+);
</code></pre></div>
</section></div></main><div id="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="juicebox_asm" data-themes="" data-resource-suffix="" data-rustdoc-version="1.67.1 (d5a82bbd2 2023-02-07)" data-search-js="search-444266647c4dba98.js" data-settings-js="settings-bebeae96e00e4617.js" data-settings-css="settings-af96d9e2fc13e081.css" ></div></body></html> \ No newline at end of file
diff --git a/src/juicebox_asm/insn.rs.html b/src/juicebox_asm/insn.rs.html
index 93134d8..2affb2d 100644
--- a/src/juicebox_asm/insn.rs.html
+++ b/src/juicebox_asm/insn.rs.html
@@ -44,7 +44,11 @@
<a href="#44" id="44">44</a>
<a href="#45" id="45">45</a>
<a href="#46" id="46">46</a>
-</pre><pre class="rust"><code><span class="kw">mod </span>add;
+<a href="#47" id="47">47</a>
+<a href="#48" id="48">48</a>
+</pre><pre class="rust"><code><span class="doccomment">//! Trait definitions of various instructions.
+
+</span><span class="kw">mod </span>add;
<span class="kw">mod </span>dec;
<span class="kw">mod </span>jmp;
<span class="kw">mod </span>jnz;
diff --git a/src/juicebox_asm/label.rs.html b/src/juicebox_asm/label.rs.html
index cf7e7ae..aff9f8f 100644
--- a/src/juicebox_asm/label.rs.html
+++ b/src/juicebox_asm/label.rs.html
@@ -70,7 +70,20 @@
<a href="#70" id="70">70</a>
<a href="#71" id="71">71</a>
<a href="#72" id="72">72</a>
-</pre><pre class="rust"><code><span class="kw">use </span>std::collections::HashSet;
+<a href="#73" id="73">73</a>
+<a href="#74" id="74">74</a>
+<a href="#75" id="75">75</a>
+<a href="#76" id="76">76</a>
+<a href="#77" id="77">77</a>
+<a href="#78" id="78">78</a>
+<a href="#79" id="79">79</a>
+<a href="#80" id="80">80</a>
+<a href="#81" id="81">81</a>
+<a href="#82" id="82">82</a>
+</pre><pre class="rust"><code><span class="doccomment">//! Definition of the lable type which can be used as jump target and can be bound to a location in
+//! the emitted code.
+
+</span><span class="kw">use </span>std::collections::HashSet;
<span class="doccomment">/// A label which is used as target for jump instructions.
///
@@ -107,7 +120,11 @@
}
}
- <span class="doccomment">/// Bind the label to the `location`.
+ <span class="doccomment">/// Bind the label to the `location`, can only be bound once.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the lable is already bound.
</span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>bind(<span class="kw-2">&amp;mut </span><span class="self">self</span>, loc: usize) {
<span class="comment">// A label can only be bound once!
</span><span class="macro">assert!</span>(!<span class="self">self</span>.is_bound());
@@ -120,11 +137,14 @@
<span class="self">self</span>.offsets.insert(off);
}
- <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>location(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;usize&gt; {
+ <span class="doccomment">/// Get the location of the lable if already bound, `None` else.
+ </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>location(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;usize&gt; {
<span class="self">self</span>.location
}
- <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>offsets_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;mut </span>HashSet&lt;usize&gt; {
+ <span class="doccomment">/// Get the offsets which refer to the label. These are used to patch the jump instructions to
+ /// the label location.
+ </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>offsets_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;mut </span>HashSet&lt;usize&gt; {
<span class="kw-2">&amp;mut </span><span class="self">self</span>.offsets
}
diff --git a/src/juicebox_asm/lib.rs.html b/src/juicebox_asm/lib.rs.html
index 7b17af1..47e6bf6 100644
--- a/src/juicebox_asm/lib.rs.html
+++ b/src/juicebox_asm/lib.rs.html
@@ -302,26 +302,214 @@
<a href="#302" id="302">302</a>
<a href="#303" id="303">303</a>
<a href="#304" id="304">304</a>
-</pre><pre class="rust"><code><span class="kw">pub mod </span>prelude;
-<span class="kw">pub mod </span>rt;
+<a href="#305" id="305">305</a>
+<a href="#306" id="306">306</a>
+<a href="#307" id="307">307</a>
+<a href="#308" id="308">308</a>
+<a href="#309" id="309">309</a>
+<a href="#310" id="310">310</a>
+<a href="#311" id="311">311</a>
+<a href="#312" id="312">312</a>
+<a href="#313" id="313">313</a>
+<a href="#314" id="314">314</a>
+<a href="#315" id="315">315</a>
+<a href="#316" id="316">316</a>
+<a href="#317" id="317">317</a>
+<a href="#318" id="318">318</a>
+<a href="#319" id="319">319</a>
+<a href="#320" id="320">320</a>
+<a href="#321" id="321">321</a>
+<a href="#322" id="322">322</a>
+<a href="#323" id="323">323</a>
+<a href="#324" id="324">324</a>
+<a href="#325" id="325">325</a>
+<a href="#326" id="326">326</a>
+<a href="#327" id="327">327</a>
+<a href="#328" id="328">328</a>
+<a href="#329" id="329">329</a>
+<a href="#330" id="330">330</a>
+<a href="#331" id="331">331</a>
+<a href="#332" id="332">332</a>
+<a href="#333" id="333">333</a>
+<a href="#334" id="334">334</a>
+<a href="#335" id="335">335</a>
+<a href="#336" id="336">336</a>
+<a href="#337" id="337">337</a>
+<a href="#338" id="338">338</a>
+<a href="#339" id="339">339</a>
+<a href="#340" id="340">340</a>
+<a href="#341" id="341">341</a>
+<a href="#342" id="342">342</a>
+<a href="#343" id="343">343</a>
+<a href="#344" id="344">344</a>
+<a href="#345" id="345">345</a>
+<a href="#346" id="346">346</a>
+<a href="#347" id="347">347</a>
+<a href="#348" id="348">348</a>
+<a href="#349" id="349">349</a>
+<a href="#350" id="350">350</a>
+<a href="#351" id="351">351</a>
+<a href="#352" id="352">352</a>
+<a href="#353" id="353">353</a>
+<a href="#354" id="354">354</a>
+<a href="#355" id="355">355</a>
+<a href="#356" id="356">356</a>
+<a href="#357" id="357">357</a>
+<a href="#358" id="358">358</a>
+<a href="#359" id="359">359</a>
+<a href="#360" id="360">360</a>
+<a href="#361" id="361">361</a>
+<a href="#362" id="362">362</a>
+<a href="#363" id="363">363</a>
+<a href="#364" id="364">364</a>
+<a href="#365" id="365">365</a>
+<a href="#366" id="366">366</a>
+<a href="#367" id="367">367</a>
+<a href="#368" id="368">368</a>
+<a href="#369" id="369">369</a>
+<a href="#370" id="370">370</a>
+<a href="#371" id="371">371</a>
+<a href="#372" id="372">372</a>
+<a href="#373" id="373">373</a>
+<a href="#374" id="374">374</a>
+<a href="#375" id="375">375</a>
+<a href="#376" id="376">376</a>
+<a href="#377" id="377">377</a>
+<a href="#378" id="378">378</a>
+<a href="#379" id="379">379</a>
+<a href="#380" id="380">380</a>
+<a href="#381" id="381">381</a>
+<a href="#382" id="382">382</a>
+<a href="#383" id="383">383</a>
+<a href="#384" id="384">384</a>
+<a href="#385" id="385">385</a>
+<a href="#386" id="386">386</a>
+<a href="#387" id="387">387</a>
+<a href="#388" id="388">388</a>
+<a href="#389" id="389">389</a>
+<a href="#390" id="390">390</a>
+<a href="#391" id="391">391</a>
+<a href="#392" id="392">392</a>
+<a href="#393" id="393">393</a>
+<a href="#394" id="394">394</a>
+<a href="#395" id="395">395</a>
+<a href="#396" id="396">396</a>
+<a href="#397" id="397">397</a>
+<a href="#398" id="398">398</a>
+<a href="#399" id="399">399</a>
+<a href="#400" id="400">400</a>
+<a href="#401" id="401">401</a>
+<a href="#402" id="402">402</a>
+<a href="#403" id="403">403</a>
+<a href="#404" id="404">404</a>
+<a href="#405" id="405">405</a>
+<a href="#406" id="406">406</a>
+<a href="#407" id="407">407</a>
+<a href="#408" id="408">408</a>
+<a href="#409" id="409">409</a>
+<a href="#410" id="410">410</a>
+</pre><pre class="rust"><code><span class="doccomment">//! A simple `x64` jit assembler with a minimal runtime to execute emitted code for fun.
+//!
+//! The following is an fibonacci example implementation.
+//! ```rust
+//! use juicebox_asm::prelude::*;
+//! use juicebox_asm::Runtime;
+//!
+//! const fn fib_rs(n: u64) -&gt; u64 {
+//! match n {
+//! 0 =&gt; 0,
+//! 1 =&gt; 1,
+//! _ =&gt; fib_rs(n - 2) + fib_rs(n - 1),
+//! }
+//! }
+//!
+//! fn main() {
+//! let mut asm = Asm::new();
+//!
+//! let mut lp = Label::new();
+//! let mut end = Label::new();
+//!
+//! // Reference implementation:
+//! //
+//! // int fib(int n) {
+//! // int tmp = 0;
+//! // int prv = 1;
+//! // int sum = 0;
+//! // loop:
+//! // if (n == 0) goto end;
+//! // tmp = sum;
+//! // sum += prv;
+//! // prv = tmp;
+//! // --n;
+//! // goto loop;
+//! // end:
+//! // return sum;
+//! // }
+//!
+//! // SystemV abi:
+//! // rdi -&gt; first argument
+//! // rax -&gt; return value
+//! let n = Reg64::rdi;
+//! let sum = Reg64::rax;
+//!
+//! let tmp = Reg64::rcx;
+//! let prv = Reg64::rbx;
+//!
+//! asm.mov(tmp, Imm64::from(0));
+//! asm.mov(prv, Imm64::from(1));
+//! asm.mov(sum, Imm64::from(0));
+//!
+//! asm.bind(&amp;mut lp);
+//! asm.test(n, n);
+//! asm.jz(&amp;mut end);
+//! asm.mov(tmp, sum);
+//! asm.add(sum, prv);
+//! asm.mov(prv, tmp);
+//! asm.dec(n);
+//! asm.jmp(&amp;mut lp);
+//! asm.bind(&amp;mut end);
+//! asm.ret();
+//!
+//! // Move code into executable page and get function pointer to it.
+//! let rt = Runtime::new(&amp;asm.into_code());
+//! let fib = unsafe { rt.as_fn::&lt;extern &quot;C&quot; fn(u64) -&gt; u64&gt;() };
+//!
+//! for n in 0..15 {
+//! let fib_jit = fib(n);
+//! println!(&quot;fib({}) = {}&quot;, n, fib_jit);
+//! assert_eq!(fib_jit, fib_rs(n));
+//! }
+//! }
+//! ```
+
+</span><span class="kw">pub mod </span>prelude;
<span class="kw">mod </span>imm;
<span class="kw">mod </span>insn;
<span class="kw">mod </span>label;
<span class="kw">mod </span>reg;
+<span class="kw">mod </span>rt;
+
+<span class="kw">pub use </span>imm::{Imm16, Imm32, Imm64, Imm8};
+<span class="kw">pub use </span>label::Label;
+<span class="kw">pub use </span>reg::{Reg16, Reg32, Reg64, Reg8};
+<span class="kw">pub use </span>rt::Runtime;
<span class="kw">use </span>imm::Imm;
-<span class="kw">use </span>label::Label;
<span class="kw">use </span>reg::Reg;
-<span class="kw">use </span>reg::{Reg16, Reg32, Reg64, Reg8};
-<span class="kw">pub enum </span>MemOp {
- Indirect(Reg64),
- IndirectDisp(Reg64, i32),
+<span class="doccomment">/// Type representing a memory operand.
+</span><span class="kw">pub enum </span>MemOp {
+ <span class="doccomment">/// An indirect memory operand, eg `mov [rax], rcx`.
+ </span>Indirect(Reg64),
+
+ <span class="doccomment">/// An indirect memory operand with additional displacement, eg `mov [rax + 0x10], rcx`.
+ </span>IndirectDisp(Reg64, i32),
}
<span class="kw">impl </span>MemOp {
- <span class="kw">const fn </span>base(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Reg64 {
+ <span class="doccomment">/// Get the base address register of the memory operand.
+ </span><span class="kw">const fn </span>base(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Reg64 {
<span class="kw">match </span><span class="self">self </span>{
MemOp::Indirect(base) =&gt; <span class="kw-2">*</span>base,
MemOp::IndirectDisp(base, ..) =&gt; <span class="kw-2">*</span>base,
@@ -343,31 +531,42 @@
((mod_ &amp; <span class="number">0b11</span>) &lt;&lt; <span class="number">6</span>) | ((reg &amp; <span class="number">0b111</span>) &lt;&lt; <span class="number">3</span>) | (rm &amp; <span class="number">0b111</span>)
}
-<span class="kw">pub struct </span>Asm {
+<span class="doccomment">/// `x64` jit assembler.
+</span><span class="kw">pub struct </span>Asm {
buf: Vec&lt;u8&gt;,
}
<span class="kw">impl </span>Asm {
- <span class="kw">pub fn </span>new() -&gt; Asm {
- <span class="kw">let </span>buf = Vec::with_capacity(<span class="number">1024</span>);
+ <span class="doccomment">/// Create a new `x64` jit assembler.
+ </span><span class="kw">pub fn </span>new() -&gt; Asm {
+ <span class="comment">// Some random default capacity.
+ </span><span class="kw">let </span>buf = Vec::with_capacity(<span class="number">1024</span>);
Asm { buf }
}
- <span class="kw">pub fn </span>into_code(<span class="self">self</span>) -&gt; Vec&lt;u8&gt; {
+ <span class="doccomment">/// Consume the assembler and get the emitted code.
+ </span><span class="kw">pub fn </span>into_code(<span class="self">self</span>) -&gt; Vec&lt;u8&gt; {
<span class="self">self</span>.buf
}
- <span class="kw">fn </span>emit(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
+ <span class="doccomment">/// Emit a slice of bytes.
+ </span><span class="kw">fn </span>emit(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[u8]) {
<span class="self">self</span>.buf.extend_from_slice(bytes);
}
- <span class="kw">fn </span>emit_optional(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[<span class="prelude-ty">Option</span>&lt;u8&gt;]) {
+ <span class="doccomment">/// Emit a slice of optional bytes.
+ </span><span class="kw">fn </span>emit_optional(<span class="kw-2">&amp;mut </span><span class="self">self</span>, bytes: <span class="kw-2">&amp;</span>[<span class="prelude-ty">Option</span>&lt;u8&gt;]) {
<span class="kw">for </span>byte <span class="kw">in </span>bytes.iter().filter_map(|<span class="kw-2">&amp;</span>b| b) {
<span class="self">self</span>.buf.push(byte);
}
}
- <span class="kw">fn </span>emit_at(<span class="kw-2">&amp;mut </span><span class="self">self</span>, pos: usize, bytes: <span class="kw-2">&amp;</span>[u8]) {
+ <span class="doccomment">/// Emit a slice of bytes at `pos`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if [pos..pos+len] indexes out of bound of the underlying code buffer.
+ </span><span class="kw">fn </span>emit_at(<span class="kw-2">&amp;mut </span><span class="self">self</span>, pos: usize, bytes: <span class="kw-2">&amp;</span>[u8]) {
<span class="kw">if let </span><span class="prelude-val">Some</span>(buf) = <span class="self">self</span>.buf.get_mut(pos..pos + bytes.len()) {
buf.copy_from_slice(bytes);
} <span class="kw">else </span>{
@@ -387,7 +586,8 @@
<span class="doccomment">/// If the [Label] is bound, patch any pending relocation.
</span><span class="kw">pub fn </span>resolve(<span class="kw-2">&amp;mut </span><span class="self">self</span>, label: <span class="kw-2">&amp;mut </span>Label) {
<span class="kw">if let </span><span class="prelude-val">Some</span>(loc) = label.location() {
- <span class="kw">let </span>loc = i32::try_from(loc).expect(<span class="string">&quot;Label location did not fit into i32.&quot;</span>);
+ <span class="comment">// For now we only support disp32 as label location.
+ </span><span class="kw">let </span>loc = i32::try_from(loc).expect(<span class="string">&quot;Label location did not fit into i32.&quot;</span>);
<span class="comment">// Resolve any pending relocations for the label.
</span><span class="kw">for </span>off <span class="kw">in </span>label.offsets_mut().drain() {
@@ -404,6 +604,7 @@
<span class="comment">// -- Encode utilities.
+ </span><span class="doccomment">/// Encode an register-register instruction.
</span><span class="kw">fn </span>encode_rr&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: T, op2: T)
<span class="kw">where
</span><span class="self">Self</span>: EncodeRR&lt;T&gt;,
@@ -424,22 +625,25 @@
<span class="self">self</span>.emit(<span class="kw-2">&amp;</span>[opc, modrm]);
}
- <span class="kw">fn </span>encode_oi&lt;T: Reg, U: Imm&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: T, op2: U)
+ <span class="doccomment">/// Encode an offset-immediate instruction.
+ /// Register idx is encoded in the opcode.
+ </span><span class="kw">fn </span>encode_oi&lt;T: Reg, U: Imm&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: T, op2: U)
<span class="kw">where
- </span><span class="self">Self</span>: EncodeRI&lt;T&gt;,
+ </span><span class="self">Self</span>: EncodeR&lt;T&gt;,
{
<span class="kw">let </span>opc = opc + (op1.idx() &amp; <span class="number">0b111</span>);
- <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::legacy_prefix();
- <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::rex(op1);
+ <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::legacy_prefix();
+ <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::rex(op1);
<span class="self">self</span>.emit_optional(<span class="kw-2">&amp;</span>[prefix, rex]);
<span class="self">self</span>.emit(<span class="kw-2">&amp;</span>[opc]);
<span class="self">self</span>.emit(op2.bytes());
}
- <span class="kw">fn </span>encode_ri&lt;T: Reg, U: Imm&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, opc_ext: u8, op1: T, op2: U)
+ <span class="doccomment">/// Encode a register-immediate instruction.
+ </span><span class="kw">fn </span>encode_ri&lt;T: Reg, U: Imm&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, opc_ext: u8, op1: T, op2: U)
<span class="kw">where
- </span><span class="self">Self</span>: EncodeRI&lt;T&gt;,
+ </span><span class="self">Self</span>: EncodeR&lt;T&gt;,
{
<span class="comment">// MI operand encoding.
// op1 -&gt; modrm.rm
@@ -450,17 +654,18 @@
</span>op1.idx(), <span class="comment">/* rm */
</span>);
- <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::legacy_prefix();
- <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::rex(op1);
+ <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::legacy_prefix();
+ <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::rex(op1);
<span class="self">self</span>.emit_optional(<span class="kw-2">&amp;</span>[prefix, rex]);
<span class="self">self</span>.emit(<span class="kw-2">&amp;</span>[opc, modrm]);
<span class="self">self</span>.emit(op2.bytes());
}
- <span class="kw">fn </span>encode_r&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, opc_ext: u8, op1: T)
+ <span class="doccomment">/// Encode a register instruction.
+ </span><span class="kw">fn </span>encode_r&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, opc_ext: u8, op1: T)
<span class="kw">where
- </span><span class="self">Self</span>: EncodeRI&lt;T&gt;,
+ </span><span class="self">Self</span>: EncodeR&lt;T&gt;,
{
<span class="comment">// M operand encoding.
// op1 -&gt; modrm.rm
@@ -471,14 +676,15 @@
</span>op1.idx(), <span class="comment">/* rm */
</span>);
- <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::legacy_prefix();
- <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeRI&lt;T&gt;&gt;::rex(op1);
+ <span class="kw">let </span>prefix = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::legacy_prefix();
+ <span class="kw">let </span>rex = &lt;<span class="self">Self </span><span class="kw">as </span>EncodeR&lt;T&gt;&gt;::rex(op1);
<span class="self">self</span>.emit_optional(<span class="kw-2">&amp;</span>[prefix, rex]);
<span class="self">self</span>.emit(<span class="kw-2">&amp;</span>[opc, modrm]);
}
- <span class="kw">fn </span>encode_mr&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: MemOp, op2: T)
+ <span class="doccomment">/// Encode a memory-register instruction.
+ </span><span class="kw">fn </span>encode_mr&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: MemOp, op2: T)
<span class="kw">where
</span><span class="self">Self</span>: EncodeMR&lt;T&gt;,
{
@@ -511,7 +717,8 @@
}
}
- <span class="kw">fn </span>encode_rm&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: T, op2: MemOp)
+ <span class="doccomment">/// Encode a register-memory instruction.
+ </span><span class="kw">fn </span>encode_rm&lt;T: Reg&gt;(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: u8, op1: T, op2: MemOp)
<span class="kw">where
</span><span class="self">Self</span>: EncodeMR&lt;T&gt;,
{
@@ -521,7 +728,8 @@
</span><span class="self">self</span>.encode_mr(opc, op2, op1);
}
- <span class="kw">fn </span>encode_jmp_label(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: <span class="kw-2">&amp;</span>[u8], op1: <span class="kw-2">&amp;mut </span>Label) {
+ <span class="doccomment">/// Encode a jump to label instruction.
+ </span><span class="kw">fn </span>encode_jmp_label(<span class="kw-2">&amp;mut </span><span class="self">self</span>, opc: <span class="kw-2">&amp;</span>[u8], op1: <span class="kw-2">&amp;mut </span>Label) {
<span class="comment">// Emit the opcode.
</span><span class="self">self</span>.emit(opc);
@@ -529,6 +737,7 @@
</span>op1.record_offset(<span class="self">self</span>.buf.len());
<span class="comment">// Emit a zeroed disp32, which serves as placeholder for the relocation.
+ // We currently only support disp32 jump targets.
</span><span class="self">self</span>.emit(<span class="kw-2">&amp;</span>[<span class="number">0u8</span>; <span class="number">4</span>]);
<span class="comment">// Resolve any pending relocations for the label.
@@ -538,6 +747,7 @@
<span class="comment">// -- Encoder helper.
+</span><span class="doccomment">/// Encode helper for register-register instructions.
</span><span class="kw">trait </span>EncodeRR&lt;T: Reg&gt; {
<span class="kw">fn </span>legacy_prefix() -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<span class="prelude-val">None
@@ -561,7 +771,8 @@
}
<span class="kw">impl </span>EncodeRR&lt;Reg64&gt; <span class="kw">for </span>Asm {}
-<span class="kw">trait </span>EncodeRI&lt;T: Reg&gt; {
+<span class="doccomment">/// Encode helper for register instructions.
+</span><span class="kw">trait </span>EncodeR&lt;T: Reg&gt; {
<span class="kw">fn </span>legacy_prefix() -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<span class="prelude-val">None
</span>}
@@ -575,16 +786,17 @@
}
}
-<span class="kw">impl </span>EncodeRI&lt;Reg8&gt; <span class="kw">for </span>Asm {}
-<span class="kw">impl </span>EncodeRI&lt;Reg32&gt; <span class="kw">for </span>Asm {}
-<span class="kw">impl </span>EncodeRI&lt;Reg16&gt; <span class="kw">for </span>Asm {
+<span class="kw">impl </span>EncodeR&lt;Reg8&gt; <span class="kw">for </span>Asm {}
+<span class="kw">impl </span>EncodeR&lt;Reg32&gt; <span class="kw">for </span>Asm {}
+<span class="kw">impl </span>EncodeR&lt;Reg16&gt; <span class="kw">for </span>Asm {
<span class="kw">fn </span>legacy_prefix() -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<span class="prelude-val">Some</span>(<span class="number">0x66</span>)
}
}
-<span class="kw">impl </span>EncodeRI&lt;Reg64&gt; <span class="kw">for </span>Asm {}
+<span class="kw">impl </span>EncodeR&lt;Reg64&gt; <span class="kw">for </span>Asm {}
-<span class="kw">trait </span>EncodeMR&lt;T: Reg&gt; {
+<span class="doccomment">/// Encode helper for memory-register instructions.
+</span><span class="kw">trait </span>EncodeMR&lt;T: Reg&gt; {
<span class="kw">fn </span>legacy_prefix() -&gt; <span class="prelude-ty">Option</span>&lt;u8&gt; {
<span class="prelude-val">None
</span>}
diff --git a/src/juicebox_asm/prelude.rs.html b/src/juicebox_asm/prelude.rs.html
index 51df87d..be1334b 100644
--- a/src/juicebox_asm/prelude.rs.html
+++ b/src/juicebox_asm/prelude.rs.html
@@ -6,7 +6,11 @@
<a href="#6" id="6">6</a>
<a href="#7" id="7">7</a>
<a href="#8" id="8">8</a>
-</pre><pre class="rust"><code><span class="kw">pub use </span><span class="kw">crate</span>::Asm;
+<a href="#9" id="9">9</a>
+<a href="#10" id="10">10</a>
+</pre><pre class="rust"><code><span class="doccomment">//! Crate prelude, which can be used to import the most important types at once.
+
+</span><span class="kw">pub use </span><span class="kw">crate</span>::Asm;
<span class="kw">pub use </span><span class="kw">crate</span>::MemOp;
<span class="kw">pub use </span><span class="kw">crate</span>::imm::{Imm16, Imm32, Imm64, Imm8};
diff --git a/src/juicebox_asm/reg.rs.html b/src/juicebox_asm/reg.rs.html
index 65ff29e..8791ddb 100644
--- a/src/juicebox_asm/reg.rs.html
+++ b/src/juicebox_asm/reg.rs.html
@@ -321,7 +321,20 @@
<a href="#321" id="321">321</a>
<a href="#322" id="322">322</a>
<a href="#323" id="323">323</a>
-</pre><pre class="rust"><code><span class="doccomment">/// Trait to interact with register operands.
+<a href="#324" id="324">324</a>
+<a href="#325" id="325">325</a>
+<a href="#326" id="326">326</a>
+<a href="#327" id="327">327</a>
+<a href="#328" id="328">328</a>
+<a href="#329" id="329">329</a>
+<a href="#330" id="330">330</a>
+<a href="#331" id="331">331</a>
+<a href="#332" id="332">332</a>
+<a href="#333" id="333">333</a>
+<a href="#334" id="334">334</a>
+</pre><pre class="rust"><code><span class="doccomment">//! Definition of registers which are used as input operands for various instructions.
+
+/// Trait to interact with register operands.
</span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>Reg {
<span class="doccomment">/// Get the raw x64 register code.
</span><span class="kw">fn </span>idx(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u8;
@@ -358,10 +371,10 @@
</span>}
}
-<span class="macro">macro_rules! </span>impl_reg {
- (ENUM_ONLY, <span class="macro-nonterminal">$name</span>:ident, { $(<span class="macro-nonterminal">$reg</span>:ident),+ $(,)<span class="question-mark">? </span>}) =&gt; {
- <span class="doccomment">/// General purpose register operands.
- </span><span class="attr">#[allow(non_camel_case_types)]
+<span class="macro">macro_rules! </span>enum_reg {
+ (<span class="attr">#[<span class="macro-nonterminal">$doc</span>:meta] </span><span class="macro-nonterminal">$name</span>:ident, { $(<span class="macro-nonterminal">$reg</span>:ident),+ $(,)<span class="question-mark">? </span>}) =&gt; {
+ <span class="attr">#[<span class="macro-nonterminal">$doc</span>]
+ #[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
#[repr(u8)]
</span><span class="kw">pub enum </span><span class="macro-nonterminal">$name </span>{
@@ -376,9 +389,11 @@
}
}
};
+}
- (<span class="macro-nonterminal">$name</span>:ident, <span class="macro-nonterminal">$rexw</span>:expr, { $(<span class="macro-nonterminal">$reg</span>:ident),+ $(,)<span class="question-mark">? </span>}) =&gt; {
- <span class="macro">impl_reg!</span>(ENUM_ONLY, <span class="macro-nonterminal">$name</span>, { $( <span class="macro-nonterminal">$reg</span>, )+ });
+<span class="macro">macro_rules! </span>impl_reg {
+ (<span class="attr">#[<span class="macro-nonterminal">$doc</span>:meta] </span><span class="macro-nonterminal">$name</span>:ident, <span class="macro-nonterminal">$rexw</span>:expr, { $(<span class="macro-nonterminal">$reg</span>:ident),+ $(,)<span class="question-mark">? </span>}) =&gt; {
+ <span class="macro">enum_reg!</span>(<span class="attr">#[<span class="macro-nonterminal">$doc</span>] </span><span class="macro-nonterminal">$name</span>, { $( <span class="macro-nonterminal">$reg</span>, )+ });
<span class="kw">impl </span>Reg <span class="kw">for </span><span class="macro-nonterminal">$name </span>{
<span class="doccomment">/// Get the raw x64 register code.
@@ -394,11 +409,18 @@
}
}
-<span class="macro">impl_reg!</span>(Reg64, <span class="bool-val">true</span>, { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 });
-<span class="macro">impl_reg!</span>(Reg32, <span class="bool-val">false</span>, { eax, ecx, edx, ebx, esp, ebp, esi, edi, r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d });
-<span class="macro">impl_reg!</span>(Reg16, <span class="bool-val">false</span>, { ax, cx, dx, bx, sp, bp, si, di, r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w });
-<span class="macro">impl_reg!</span>(ENUM_ONLY,
- Reg8, { al, cl, dl, bl, spl, bpl, sil, dil, r8l, r9l, r10l, r11l, r12l, r13l, r14l, r15l,
+<span class="macro">impl_reg!</span>(
+ <span class="doccomment">/// Definition of 64 bit registers.
+ </span>Reg64, <span class="bool-val">true</span>, { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 });
+<span class="macro">impl_reg!</span>(
+ <span class="doccomment">/// Definition of 32 bit registers.
+ </span>Reg32, <span class="bool-val">false</span>, { eax, ecx, edx, ebx, esp, ebp, esi, edi, r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d });
+<span class="macro">impl_reg!</span>(
+ <span class="doccomment">/// Definition of 16 bit registers.
+ </span>Reg16, <span class="bool-val">false</span>, { ax, cx, dx, bx, sp, bp, si, di, r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w });
+<span class="macro">enum_reg!</span>(
+ <span class="doccomment">/// Definition of 8 bit registers.
+ </span>Reg8, { al, cl, dl, bl, spl, bpl, sil, dil, r8l, r9l, r10l, r11l, r12l, r13l, r14l, r15l,
ah, ch, dh, bh });
<span class="kw">impl </span>Reg <span class="kw">for </span>Reg8 {
diff --git a/src/juicebox_asm/rt.rs.html b/src/juicebox_asm/rt.rs.html
index a44e465..62ee9b7 100644
--- a/src/juicebox_asm/rt.rs.html
+++ b/src/juicebox_asm/rt.rs.html
@@ -49,7 +49,11 @@
<a href="#49" id="49">49</a>
<a href="#50" id="50">50</a>
<a href="#51" id="51">51</a>
-</pre><pre class="rust"><code><span class="kw">use </span>core::ffi::c_void;
+<a href="#52" id="52">52</a>
+<a href="#53" id="53">53</a>
+</pre><pre class="rust"><code><span class="doccomment">//! A simple runtime which can be used to execute emitted instructions.
+
+</span><span class="kw">use </span>core::ffi::c_void;
<span class="kw">use </span>nix::sys::mman::{mmap, munmap, MapFlags, ProtFlags};
<span class="doccomment">/// A simple `mmap`ed runtime with executable pages.