diff options
Diffstat (limited to 'src/juicebox_asm')
-rw-r--r-- | src/juicebox_asm/imm.rs.html | 44 | ||||
-rw-r--r-- | src/juicebox_asm/insn.rs.html | 6 | ||||
-rw-r--r-- | src/juicebox_asm/label.rs.html | 28 | ||||
-rw-r--r-- | src/juicebox_asm/lib.rs.html | 286 | ||||
-rw-r--r-- | src/juicebox_asm/prelude.rs.html | 6 | ||||
-rw-r--r-- | src/juicebox_asm/reg.rs.html | 46 | ||||
-rw-r--r-- | src/juicebox_asm/rt.rs.html | 6 |
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">&</span><span class="self">self</span>) -> <span class="kw-2">&</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>) => { - <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>}) => { + <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">&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">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><usize> { + <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">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><usize> { <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">&mut </span><span class="self">self</span>) -> <span class="kw-2">&mut </span>HashSet<usize> { + <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">&mut </span><span class="self">self</span>) -> <span class="kw-2">&mut </span>HashSet<usize> { <span class="kw-2">&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) -> u64 { +//! match n { +//! 0 => 0, +//! 1 => 1, +//! _ => 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 -> first argument +//! // rax -> 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(&mut lp); +//! asm.test(n, n); +//! asm.jz(&mut end); +//! asm.mov(tmp, sum); +//! asm.add(sum, prv); +//! asm.mov(prv, tmp); +//! asm.dec(n); +//! asm.jmp(&mut lp); +//! asm.bind(&mut end); +//! asm.ret(); +//! +//! // Move code into executable page and get function pointer to it. +//! let rt = Runtime::new(&asm.into_code()); +//! let fib = unsafe { rt.as_fn::<extern "C" fn(u64) -> u64>() }; +//! +//! for n in 0..15 { +//! let fib_jit = fib(n); +//! println!("fib({}) = {}", 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">&</span><span class="self">self</span>) -> 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">&</span><span class="self">self</span>) -> Reg64 { <span class="kw">match </span><span class="self">self </span>{ MemOp::Indirect(base) => <span class="kw-2">*</span>base, MemOp::IndirectDisp(base, ..) => <span class="kw-2">*</span>base, @@ -343,31 +531,42 @@ ((mod_ & <span class="number">0b11</span>) << <span class="number">6</span>) | ((reg & <span class="number">0b111</span>) << <span class="number">3</span>) | (rm & <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<u8>, } <span class="kw">impl </span>Asm { - <span class="kw">pub fn </span>new() -> 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() -> 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>) -> Vec<u8> { + <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>) -> Vec<u8> { <span class="self">self</span>.buf } - <span class="kw">fn </span>emit(<span class="kw-2">&mut </span><span class="self">self</span>, bytes: <span class="kw-2">&</span>[u8]) { + <span class="doccomment">/// Emit a slice of bytes. + </span><span class="kw">fn </span>emit(<span class="kw-2">&mut </span><span class="self">self</span>, bytes: <span class="kw-2">&</span>[u8]) { <span class="self">self</span>.buf.extend_from_slice(bytes); } - <span class="kw">fn </span>emit_optional(<span class="kw-2">&mut </span><span class="self">self</span>, bytes: <span class="kw-2">&</span>[<span class="prelude-ty">Option</span><u8>]) { + <span class="doccomment">/// Emit a slice of optional bytes. + </span><span class="kw">fn </span>emit_optional(<span class="kw-2">&mut </span><span class="self">self</span>, bytes: <span class="kw-2">&</span>[<span class="prelude-ty">Option</span><u8>]) { <span class="kw">for </span>byte <span class="kw">in </span>bytes.iter().filter_map(|<span class="kw-2">&</span>b| b) { <span class="self">self</span>.buf.push(byte); } } - <span class="kw">fn </span>emit_at(<span class="kw-2">&mut </span><span class="self">self</span>, pos: usize, bytes: <span class="kw-2">&</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">&mut </span><span class="self">self</span>, pos: usize, bytes: <span class="kw-2">&</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">&mut </span><span class="self">self</span>, label: <span class="kw-2">&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">"Label location did not fit into i32."</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">"Label location did not fit into i32."</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<T: Reg>(<span class="kw-2">&mut </span><span class="self">self</span>, opc: u8, op1: T, op2: T) <span class="kw">where </span><span class="self">Self</span>: EncodeRR<T>, @@ -424,22 +625,25 @@ <span class="self">self</span>.emit(<span class="kw-2">&</span>[opc, modrm]); } - <span class="kw">fn </span>encode_oi<T: Reg, U: Imm>(<span class="kw-2">&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<T: Reg, U: Imm>(<span class="kw-2">&mut </span><span class="self">self</span>, opc: u8, op1: T, op2: U) <span class="kw">where - </span><span class="self">Self</span>: EncodeRI<T>, + </span><span class="self">Self</span>: EncodeR<T>, { <span class="kw">let </span>opc = opc + (op1.idx() & <span class="number">0b111</span>); - <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::legacy_prefix(); - <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::rex(op1); + <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::legacy_prefix(); + <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::rex(op1); <span class="self">self</span>.emit_optional(<span class="kw-2">&</span>[prefix, rex]); <span class="self">self</span>.emit(<span class="kw-2">&</span>[opc]); <span class="self">self</span>.emit(op2.bytes()); } - <span class="kw">fn </span>encode_ri<T: Reg, U: Imm>(<span class="kw-2">&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<T: Reg, U: Imm>(<span class="kw-2">&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<T>, + </span><span class="self">Self</span>: EncodeR<T>, { <span class="comment">// MI operand encoding. // op1 -> modrm.rm @@ -450,17 +654,18 @@ </span>op1.idx(), <span class="comment">/* rm */ </span>); - <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::legacy_prefix(); - <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::rex(op1); + <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::legacy_prefix(); + <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::rex(op1); <span class="self">self</span>.emit_optional(<span class="kw-2">&</span>[prefix, rex]); <span class="self">self</span>.emit(<span class="kw-2">&</span>[opc, modrm]); <span class="self">self</span>.emit(op2.bytes()); } - <span class="kw">fn </span>encode_r<T: Reg>(<span class="kw-2">&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<T: Reg>(<span class="kw-2">&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<T>, + </span><span class="self">Self</span>: EncodeR<T>, { <span class="comment">// M operand encoding. // op1 -> modrm.rm @@ -471,14 +676,15 @@ </span>op1.idx(), <span class="comment">/* rm */ </span>); - <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::legacy_prefix(); - <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeRI<T>>::rex(op1); + <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::legacy_prefix(); + <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeR<T>>::rex(op1); <span class="self">self</span>.emit_optional(<span class="kw-2">&</span>[prefix, rex]); <span class="self">self</span>.emit(<span class="kw-2">&</span>[opc, modrm]); } - <span class="kw">fn </span>encode_mr<T: Reg>(<span class="kw-2">&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<T: Reg>(<span class="kw-2">&mut </span><span class="self">self</span>, opc: u8, op1: MemOp, op2: T) <span class="kw">where </span><span class="self">Self</span>: EncodeMR<T>, { @@ -511,7 +717,8 @@ } } - <span class="kw">fn </span>encode_rm<T: Reg>(<span class="kw-2">&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<T: Reg>(<span class="kw-2">&mut </span><span class="self">self</span>, opc: u8, op1: T, op2: MemOp) <span class="kw">where </span><span class="self">Self</span>: EncodeMR<T>, { @@ -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">&mut </span><span class="self">self</span>, opc: <span class="kw-2">&</span>[u8], op1: <span class="kw-2">&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">&mut </span><span class="self">self</span>, opc: <span class="kw-2">&</span>[u8], op1: <span class="kw-2">&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">&</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<T: Reg> { <span class="kw">fn </span>legacy_prefix() -> <span class="prelude-ty">Option</span><u8> { <span class="prelude-val">None @@ -561,7 +771,8 @@ } <span class="kw">impl </span>EncodeRR<Reg64> <span class="kw">for </span>Asm {} -<span class="kw">trait </span>EncodeRI<T: Reg> { +<span class="doccomment">/// Encode helper for register instructions. +</span><span class="kw">trait </span>EncodeR<T: Reg> { <span class="kw">fn </span>legacy_prefix() -> <span class="prelude-ty">Option</span><u8> { <span class="prelude-val">None </span>} @@ -575,16 +786,17 @@ } } -<span class="kw">impl </span>EncodeRI<Reg8> <span class="kw">for </span>Asm {} -<span class="kw">impl </span>EncodeRI<Reg32> <span class="kw">for </span>Asm {} -<span class="kw">impl </span>EncodeRI<Reg16> <span class="kw">for </span>Asm { +<span class="kw">impl </span>EncodeR<Reg8> <span class="kw">for </span>Asm {} +<span class="kw">impl </span>EncodeR<Reg32> <span class="kw">for </span>Asm {} +<span class="kw">impl </span>EncodeR<Reg16> <span class="kw">for </span>Asm { <span class="kw">fn </span>legacy_prefix() -> <span class="prelude-ty">Option</span><u8> { <span class="prelude-val">Some</span>(<span class="number">0x66</span>) } } -<span class="kw">impl </span>EncodeRI<Reg64> <span class="kw">for </span>Asm {} +<span class="kw">impl </span>EncodeR<Reg64> <span class="kw">for </span>Asm {} -<span class="kw">trait </span>EncodeMR<T: Reg> { +<span class="doccomment">/// Encode helper for memory-register instructions. +</span><span class="kw">trait </span>EncodeMR<T: Reg> { <span class="kw">fn </span>legacy_prefix() -> <span class="prelude-ty">Option</span><u8> { <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">&</span><span class="self">self</span>) -> 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>}) => { - <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>}) => { + <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>}) => { - <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>}) => { + <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. |