diff options
author | johannst <johannst@users.noreply.github.com> | 2024-12-07 01:01:45 +0000 |
---|---|---|
committer | johannst <johannst@users.noreply.github.com> | 2024-12-07 01:01:45 +0000 |
commit | 5289cbf5331dfd0d0c2242a7e7c8030aa4032c7e (patch) | |
tree | 418e8eebbfe7129d5082efa730e161edd3743161 /src/juicebox_asm/asm.rs.html | |
parent | 52a0308e18fbbec25f0e9f31ec8f11589a35f351 (diff) | |
download | juicebox-asm-5289cbf5331dfd0d0c2242a7e7c8030aa4032c7e.tar.gz juicebox-asm-5289cbf5331dfd0d0c2242a7e7c8030aa4032c7e.zip |
deploy: 9c3c3fd923d894d2351eb22129ea693eb98fa8ff
Diffstat (limited to 'src/juicebox_asm/asm.rs.html')
-rw-r--r-- | src/juicebox_asm/asm.rs.html | 281 |
1 files changed, 254 insertions, 27 deletions
diff --git a/src/juicebox_asm/asm.rs.html b/src/juicebox_asm/asm.rs.html index 4418397..3f24ae2 100644 --- a/src/juicebox_asm/asm.rs.html +++ b/src/juicebox_asm/asm.rs.html @@ -1,5 +1,5 @@ -<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `src/asm.rs`."><title>asm.rs - source</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/FiraSans-Regular-018c141bf0843ffd.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/FiraSans-Medium-8f9a781e4970d388.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2"><link rel="stylesheet" href="../../static.files/normalize-76eba96aa4d2e634.css"><link rel="stylesheet" href="../../static.files/rustdoc-ac92e1bbe349e143.css"><meta name="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.76.0 (07dca489a 2024-02-04)" data-channel="1.76.0" data-search-js="search-2b6ce74ff89ae146.js" data-settings-js="settings-4313503d2e1961c2.js" ><script src="../../static.files/storage-f2adc0d6ca4d09fb.js"></script><script defer src="../../static.files/src-script-39ed315d46fb705f.js"></script><script defer src="../../src-files.js"></script><script defer src="../../static.files/main-305769736d49e732.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-feafe1bb7466e4bd.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-16x16-8b506e7a72182f1c.png"><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-422f7d1d52889060.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-2c020d218678b618.svg"></head><body class="rustdoc src"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"></nav><div class="sidebar-resizer"></div> - <main><nav class="sub"><form class="search-form"><span></span><input class="search-input" name="search" aria-label="Run search in the documentation" autocomplete="off" spellcheck="false" placeholder="Click or press ‘S’ to search, ‘?’ for more options…" type="search"><div id="help-button" tabindex="-1"><a href="../../help.html" title="help">?</a></div><div id="settings-menu" tabindex="-1"><a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../static.files/wheel-7b819b6101059cd0.svg"></a></div></form></nav><section id="main-content" class="content"><div class="example-wrap"><div data-nosnippet><pre class="src-line-numbers"><a href="#1" id="1">1</a> +<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `src/asm.rs`."><title>asm.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2,SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-76eba96aa4d2e634.css"><link rel="stylesheet" href="../../static.files/rustdoc-b0742ba02757f159.css"><meta name="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.83.0 (90b35a623 2024-11-26)" data-channel="1.83.0" data-search-js="search-f0d225181b97f9a4.js" data-settings-js="settings-805db61a62df4bd2.js" ><script src="../../static.files/storage-1d39b6787ed640ff.js"></script><script defer src="../../static.files/src-script-e66d777a5a92e9b2.js"></script><script defer src="../../src-files.js"></script><script defer src="../../static.files/main-f070b9041d14864c.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-0111fcff984fae8f.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-422f7d1d52889060.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-2c020d218678b618.svg"></head><body class="rustdoc src"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer"></div><main><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><h1><div class="sub-heading">juicebox_asm/</div>asm.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap"><div data-nosnippet><pre class="src-line-numbers"> +<a href="#1" id="1">1</a> <a href="#2" id="2">2</a> <a href="#3" id="3">3</a> <a href="#4" id="4">4</a> @@ -344,7 +344,120 @@ <a href="#343" id="343">343</a> <a href="#344" id="344">344</a> <a href="#345" id="345">345</a> -</pre></div><pre class="rust"><code><span class="doccomment">//! The `x64` jit assembler. +<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> +<a href="#411" id="411">411</a> +<a href="#412" id="412">412</a> +<a href="#413" id="413">413</a> +<a href="#414" id="414">414</a> +<a href="#415" id="415">415</a> +<a href="#416" id="416">416</a> +<a href="#417" id="417">417</a> +<a href="#418" id="418">418</a> +<a href="#419" id="419">419</a> +<a href="#420" id="420">420</a> +<a href="#421" id="421">421</a> +<a href="#422" id="422">422</a> +<a href="#423" id="423">423</a> +<a href="#424" id="424">424</a> +<a href="#425" id="425">425</a> +<a href="#426" id="426">426</a> +<a href="#427" id="427">427</a> +<a href="#428" id="428">428</a> +<a href="#429" id="429">429</a> +<a href="#430" id="430">430</a> +<a href="#431" id="431">431</a> +<a href="#432" id="432">432</a> +<a href="#433" id="433">433</a> +<a href="#434" id="434">434</a> +<a href="#435" id="435">435</a> +<a href="#436" id="436">436</a> +<a href="#437" id="437">437</a> +<a href="#438" id="438">438</a> +<a href="#439" id="439">439</a> +<a href="#440" id="440">440</a> +<a href="#441" id="441">441</a> +<a href="#442" id="442">442</a> +<a href="#443" id="443">443</a> +<a href="#444" id="444">444</a> +<a href="#445" id="445">445</a> +<a href="#446" id="446">446</a> +<a href="#447" id="447">447</a> +<a href="#448" id="448">448</a> +<a href="#449" id="449">449</a> +<a href="#450" id="450">450</a> +<a href="#451" id="451">451</a> +<a href="#452" id="452">452</a> +<a href="#453" id="453">453</a> +<a href="#454" id="454">454</a> +<a href="#455" id="455">455</a> +<a href="#456" id="456">456</a> +<a href="#457" id="457">457</a> +<a href="#458" id="458">458</a> +<a href="#459" id="459">459</a></pre></div><pre class="rust"><code><span class="doccomment">//! The `x64` jit assembler. </span><span class="kw">use crate</span>::<span class="kw-2">*</span>; <span class="kw">use </span>imm::Imm; @@ -364,6 +477,11 @@ ((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="doccomment">/// Encode the `SIB` byte. +</span><span class="kw">const fn </span>sib(scale: u8, index: u8, base: u8) -> u8 { + ((scale & <span class="number">0b11</span>) << <span class="number">6</span>) | ((index & <span class="number">0b111</span>) << <span class="number">3</span>) | (base & <span class="number">0b111</span>) +} + <span class="doccomment">/// `x64` jit assembler. </span><span class="kw">pub struct </span>Asm { buf: Vec<u8>, @@ -495,6 +613,52 @@ <span class="self">self</span>.emit(<span class="kw-2">&</span>[opc, modrm]); } + <span class="doccomment">/// Encode a memory operand instruction. + </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>encode_m<T: MemOpSized>(<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>: EncodeM<T>, + { + <span class="kw">let </span>op1 = op1.mem_op(); + + <span class="comment">// M operand encoding. + // op1 -> modrm.rm + </span><span class="kw">let </span>(mode, rm) = <span class="kw">match </span>op1 { + MemOp::Indirect(..) => { + <span class="macro">assert!</span>(!op1.base().need_sib() && !op1.base().is_pc_rel()); + (<span class="number">0b00</span>, op1.base().idx()) + } + MemOp::IndirectDisp(..) => { + <span class="macro">assert!</span>(!op1.base().need_sib()); + (<span class="number">0b10</span>, op1.base().idx()) + } + MemOp::IndirectBaseIndex(..) => { + <span class="macro">assert!</span>(!op1.base().is_pc_rel()); + <span class="comment">// Using rsp as index register is interpreted as just base w/o offset. + // https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 + // Disallow this case, as guard for the user. + </span><span class="macro">assert!</span>(!<span class="macro">matches!</span>(op1.index(), Reg64::rsp)); + (<span class="number">0b00</span>, <span class="number">0b100</span>) + } + }; + + <span class="kw">let </span>modrm = modrm( + mode, <span class="comment">/* mode */ + </span>opc_ext, <span class="comment">/* reg */ + </span>rm, <span class="comment">/* rm */ + </span>); + + <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeM<T>>::legacy_prefix(); + <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeM<T>>::rex(<span class="kw-2">&</span>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">match </span>op1 { + MemOp::Indirect(..) => {} + MemOp::IndirectDisp(<span class="kw">_</span>, disp) => <span class="self">self</span>.emit(<span class="kw-2">&</span>disp.to_ne_bytes()), + MemOp::IndirectBaseIndex(base, index) => <span class="self">self</span>.emit(<span class="kw-2">&</span>[sib(<span class="number">0</span>, index.idx(), base.idx())]), + } + } + <span class="doccomment">/// Encode a memory-immediate instruction. </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>encode_mi<T: Imm>(<span class="kw-2">&mut </span><span class="self">self</span>, opc: u8, opc_ext: u8, op1: MemOp, op2: T) <span class="kw">where @@ -503,21 +667,29 @@ <span class="comment">// MI operand encoding. // op1 -> modrm.rm // op2 -> imm - </span><span class="kw">let </span>mode = <span class="kw">match </span>op1 { + </span><span class="kw">let </span>(mode, rm) = <span class="kw">match </span>op1 { MemOp::Indirect(..) => { <span class="macro">assert!</span>(!op1.base().need_sib() && !op1.base().is_pc_rel()); - <span class="number">0b00 - </span>} + (<span class="number">0b00</span>, op1.base().idx()) + } MemOp::IndirectDisp(..) => { <span class="macro">assert!</span>(!op1.base().need_sib()); - <span class="number">0b10 - </span>} + (<span class="number">0b10</span>, op1.base().idx()) + } + MemOp::IndirectBaseIndex(..) => { + <span class="macro">assert!</span>(!op1.base().is_pc_rel()); + <span class="comment">// Using rsp as index register is interpreted as just base w/o offset. + // https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 + // Disallow this case, as guard for the user. + </span><span class="macro">assert!</span>(!<span class="macro">matches!</span>(op1.index(), Reg64::rsp)); + (<span class="number">0b00</span>, <span class="number">0b100</span>) + } }; <span class="kw">let </span>modrm = modrm( - mode, <span class="comment">/* mode */ - </span>opc_ext, <span class="comment">/* reg */ - </span>op1.base().idx(), <span class="comment">/* rm */ + mode, <span class="comment">/* mode */ + </span>opc_ext, <span class="comment">/* reg */ + </span>rm, <span class="comment">/* rm */ </span>); <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeMI<T>>::legacy_prefix(); @@ -525,8 +697,10 @@ <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">if let </span>MemOp::IndirectDisp(<span class="kw">_</span>, disp) = op1 { - <span class="self">self</span>.emit(<span class="kw-2">&</span>disp.to_ne_bytes()); + <span class="kw">match </span>op1 { + MemOp::Indirect(..) => {} + MemOp::IndirectDisp(<span class="kw">_</span>, disp) => <span class="self">self</span>.emit(<span class="kw-2">&</span>disp.to_ne_bytes()), + MemOp::IndirectBaseIndex(base, index) => <span class="self">self</span>.emit(<span class="kw-2">&</span>[sib(<span class="number">0</span>, index.idx(), base.idx())]), } <span class="self">self</span>.emit(op2.bytes()); } @@ -539,29 +713,40 @@ <span class="comment">// MR operand encoding. // op1 -> modrm.rm // op2 -> modrm.reg - </span><span class="kw">let </span>mode = <span class="kw">match </span>op1 { + </span><span class="kw">let </span>(mode, rm) = <span class="kw">match </span>op1 { MemOp::Indirect(..) => { <span class="macro">assert!</span>(!op1.base().need_sib() && !op1.base().is_pc_rel()); - <span class="number">0b00 - </span>} + (<span class="number">0b00</span>, op1.base().idx()) + } MemOp::IndirectDisp(..) => { <span class="macro">assert!</span>(!op1.base().need_sib()); - <span class="number">0b10 - </span>} + (<span class="number">0b10</span>, op1.base().idx()) + } + MemOp::IndirectBaseIndex(..) => { + <span class="macro">assert!</span>(!op1.base().is_pc_rel()); + <span class="comment">// Using rsp as index register is interpreted as just base w/o offset. + // https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 + // Disallow this case, as guard for the user. + </span><span class="macro">assert!</span>(!<span class="macro">matches!</span>(op1.index(), Reg64::rsp)); + (<span class="number">0b00</span>, <span class="number">0b100</span>) + } }; <span class="kw">let </span>modrm = modrm( - mode, <span class="comment">/* mode */ - </span>op2.idx(), <span class="comment">/* reg */ - </span>op1.base().idx(), <span class="comment">/* rm */ + mode, <span class="comment">/* mode */ + </span>op2.idx(), <span class="comment">/* reg */ + </span>rm, <span class="comment">/* rm */ </span>); + <span class="kw">let </span>prefix = <<span class="self">Self </span><span class="kw">as </span>EncodeMR<T>>::legacy_prefix(); <span class="kw">let </span>rex = <<span class="self">Self </span><span class="kw">as </span>EncodeMR<T>>::rex(<span class="kw-2">&</span>op1, op2); <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">if let </span>MemOp::IndirectDisp(<span class="kw">_</span>, disp) = op1 { - <span class="self">self</span>.emit(<span class="kw-2">&</span>disp.to_ne_bytes()); + <span class="kw">match </span>op1 { + MemOp::Indirect(..) => {} + MemOp::IndirectDisp(<span class="kw">_</span>, disp) => <span class="self">self</span>.emit(<span class="kw-2">&</span>disp.to_ne_bytes()), + MemOp::IndirectBaseIndex(base, index) => <span class="self">self</span>.emit(<span class="kw-2">&</span>[sib(<span class="number">0</span>, index.idx(), base.idx())]), } } @@ -650,8 +835,13 @@ </span>} <span class="kw">fn </span>rex(op1: <span class="kw-2">&</span>MemOp, op2: T) -> <span class="prelude-ty">Option</span><u8> { - <span class="kw">if </span>op2.need_rex() || (op1.base().is_ext()) { - <span class="prelude-val">Some</span>(rex(op2.rexw(), op2.idx(), <span class="number">0</span>, op1.base().idx())) + <span class="kw">if </span>op2.need_rex() || op1.base().is_ext() || op1.index().is_ext() { + <span class="prelude-val">Some</span>(rex( + op2.rexw(), + op2.idx(), + op1.index().idx(), + op1.base().idx(), + )) } <span class="kw">else </span>{ <span class="prelude-val">None </span>} @@ -674,8 +864,8 @@ </span>} <span class="kw">fn </span>rex(op1: <span class="kw-2">&</span>MemOp) -> <span class="prelude-ty">Option</span><u8> { - <span class="kw">if </span>op1.base().is_ext() { - <span class="prelude-val">Some</span>(rex(<span class="bool-val">false</span>, <span class="number">0</span>, <span class="number">0</span>, op1.base().idx())) + <span class="kw">if </span>op1.base().is_ext() || op1.index().is_ext() { + <span class="prelude-val">Some</span>(rex(<span class="bool-val">false</span>, <span class="number">0</span>, op1.index().idx(), op1.base().idx())) } <span class="kw">else </span>{ <span class="prelude-val">None </span>} @@ -689,4 +879,41 @@ } } <span class="kw">impl </span>EncodeMI<Imm32> <span class="kw">for </span>Asm {} + +<span class="doccomment">/// Encode helper for memory operand instructions. +</span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">trait </span>EncodeM<T: MemOpSized> { + <span class="kw">fn </span>legacy_prefix() -> <span class="prelude-ty">Option</span><u8> { + <span class="prelude-val">None + </span>} + + <span class="kw">fn </span>rex(op1: <span class="kw-2">&</span>MemOp) -> <span class="prelude-ty">Option</span><u8> { + <span class="kw">if </span>op1.base().is_ext() || op1.index().is_ext() || <span class="self">Self</span>::is_64bit() { + <span class="prelude-val">Some</span>(rex( + <span class="self">Self</span>::is_64bit(), + <span class="number">0</span>, + op1.index().idx(), + op1.base().idx(), + )) + } <span class="kw">else </span>{ + <span class="prelude-val">None + </span>} + } + + <span class="kw">fn </span>is_64bit() -> bool { + <span class="bool-val">false + </span>} +} + +<span class="kw">impl </span>EncodeM<MemOp8> <span class="kw">for </span>Asm {} +<span class="kw">impl </span>EncodeM<MemOp16> <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>EncodeM<MemOp32> <span class="kw">for </span>Asm {} +<span class="kw">impl </span>EncodeM<MemOp64> <span class="kw">for </span>Asm { + <span class="kw">fn </span>is_64bit() -> bool { + <span class="bool-val">true + </span>} +} </code></pre></div></section></main></body></html>
\ No newline at end of file |