1use crate::imm::Imm;
8use crate::mem::{AddrMode, Mem, Mem16, Mem32, Mem64, Mem8};
9use crate::reg::{Reg, Reg16, Reg32, Reg64, Reg8};
10use crate::Label;
11
12pub(crate) const fn rex(w: bool, r: u8, x: u8, b: u8) -> u8 {
14 let w = if w { 1 } else { 0 };
15 let r = (r >> 3) & 1;
16 let x = (x >> 3) & 1;
17 let b = (b >> 3) & 1;
18 0b0100_0000 | ((w & 1) << 3) | (r << 2) | (x << 1) | b
19}
20
21pub(crate) const fn modrm(mod_: u8, reg: u8, rm: u8) -> u8 {
23 ((mod_ & 0b11) << 6) | ((reg & 0b111) << 3) | (rm & 0b111)
24}
25
26const fn sib(scale: u8, index: u8, base: u8) -> u8 {
28 ((scale & 0b11) << 6) | ((index & 0b111) << 3) | (base & 0b111)
29}
30
31pub struct Asm {
33 buf: Vec<u8>,
34}
35
36impl Asm {
37 pub fn new() -> Asm {
39 let buf = Vec::with_capacity(1024);
41 Asm { buf }
42 }
43
44 pub fn into_code(self) -> Vec<u8> {
46 self.buf
47 }
48
49 pub fn disasm(&self) {
59 crate::disasm::disasm(&self.buf);
60 }
61
62 pub(crate) fn emit(&mut self, bytes: &[u8]) {
64 self.buf.extend_from_slice(bytes);
65 }
66
67 pub(crate) fn emit_optional(&mut self, bytes: &[Option<u8>]) {
69 for byte in bytes.iter().filter_map(|&b| b) {
70 self.buf.push(byte);
71 }
72 }
73
74 fn emit_at(&mut self, pos: usize, bytes: &[u8]) {
80 if let Some(buf) = self.buf.get_mut(pos..pos + bytes.len()) {
81 buf.copy_from_slice(bytes);
82 } else {
83 unimplemented!();
84 }
85 }
86
87 pub fn bind(&mut self, label: &mut Label) {
89 label.bind(self.buf.len());
91
92 self.resolve(label);
94 }
95
96 fn resolve(&mut self, label: &mut Label) {
98 if let Some(loc) = label.location() {
99 for off in label.offsets_mut().drain() {
101 let disp = {
103 let loc = isize::try_from(loc).expect("loc does not fit into isize");
104 let off = isize::try_from(off).expect("off does not fit into isize");
105
106 loc - (off + 4)
109 };
110
111 let disp32 = i32::try_from(disp).expect("Label offset did not fit into i32");
113
114 self.emit_at(off, &disp32.to_ne_bytes());
116 }
117 }
118 }
119
120 pub(crate) fn encode_oi<T: Reg, U: Imm>(&mut self, opc: u8, op1: T, op2: U)
125 where
126 Self: EncodeR<T>,
127 {
128 let opc = opc + (op1.idx() & 0b111);
129 let prefix = <Self as EncodeR<T>>::legacy_prefix();
130 let rex = <Self as EncodeR<T>>::rex(op1);
131
132 self.emit_optional(&[prefix, rex]);
133 self.emit(&[opc]);
134 self.emit(op2.bytes());
135 }
136
137 pub(crate) fn encode_r<T: Reg>(&mut self, opc: &[u8], opc_ext: u8, op1: T)
139 where
140 Self: EncodeR<T>,
141 {
142 let modrm = modrm(
146 0b11, opc_ext, op1.idx(), );
150
151 let prefix = <Self as EncodeR<T>>::legacy_prefix();
152 let rex = <Self as EncodeR<T>>::rex(op1);
153
154 self.emit_optional(&[prefix, rex]);
155 self.emit(opc);
156 self.emit(&[modrm]);
157 }
158
159 pub(crate) fn encode_rr_mr<T: Reg, U: Reg>(&mut self, opc: &[u8], op1: T, op2: U)
162 where
163 Self: EncodeRR<T, U>,
164 {
165 let modrm = modrm(
171 0b11, op2.idx(), op1.idx(), );
175
176 let prefix = <Self as EncodeRR<T, U>>::legacy_prefix();
177 let rex = <Self as EncodeRR<T, U>>::rex(op1, op2);
178
179 self.emit_optional(&[prefix, rex]);
180 self.emit(opc);
181 self.emit(&[modrm]);
182 }
183
184 pub(crate) fn encode_rr_rm<T: Reg, U: Reg>(&mut self, opc: &[u8], op1: T, op2: U)
187 where
188 Self: EncodeRR<U, T>,
189 {
190 self.encode_rr_mr::<U, T>(opc, op2, op1);
192 }
193
194 pub(crate) fn encode_ri<T: Reg, U: Imm>(&mut self, opc: u8, opc_ext: u8, op1: T, op2: U)
196 where
197 Self: EncodeR<T>,
198 {
199 let modrm = modrm(
200 0b11, opc_ext, op1.idx(), );
204
205 let prefix = <Self as EncodeR<T>>::legacy_prefix();
206 let rex = <Self as EncodeR<T>>::rex(op1);
207
208 self.emit_optional(&[prefix, rex]);
209 self.emit(&[opc, modrm]);
210 self.emit(op2.bytes());
211 }
212
213 pub(crate) fn encode_m<T: Mem>(&mut self, opc: u8, opc_ext: u8, op1: T)
215 where
216 Self: EncodeM<T>,
217 {
218 let (mode, rm) = match op1.mode() {
221 AddrMode::Indirect => {
222 assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
223 (0b00, op1.base().idx())
224 }
225 AddrMode::IndirectDisp => {
226 assert!(!op1.base().need_sib());
227 (0b10, op1.base().idx())
228 }
229 AddrMode::IndirectBaseIndex => {
230 assert!(!op1.base().is_pc_rel());
231 assert!(!matches!(op1.index(), Reg64::rsp));
235 (0b00, 0b100)
236 }
237 };
238
239 let modrm = modrm(
240 mode, opc_ext, rm, );
244
245 let prefix = <Self as EncodeM<T>>::legacy_prefix();
246 let rex = <Self as EncodeM<T>>::rex(&op1);
247
248 self.emit_optional(&[prefix, rex]);
249 self.emit(&[opc, modrm]);
250 match op1.mode() {
251 AddrMode::Indirect => {}
252 AddrMode::IndirectDisp => self.emit(&op1.disp().to_ne_bytes()),
253 AddrMode::IndirectBaseIndex => {
254 self.emit(&[sib(0, op1.index().idx(), op1.base().idx())])
255 }
256 }
257 }
258
259 pub(crate) fn encode_mi<M: Mem, T: Imm>(&mut self, opc: u8, opc_ext: u8, op1: M, op2: T)
261 where
262 Self: EncodeM<M>,
263 {
264 let (mode, rm) = match op1.mode() {
268 AddrMode::Indirect => {
269 assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
270 (0b00, op1.base().idx())
271 }
272 AddrMode::IndirectDisp => {
273 assert!(!op1.base().need_sib());
274 (0b10, op1.base().idx())
275 }
276 AddrMode::IndirectBaseIndex => {
277 assert!(!op1.base().is_pc_rel());
278 assert!(!matches!(op1.index(), Reg64::rsp));
282 (0b00, 0b100)
283 }
284 };
285
286 let modrm = modrm(
287 mode, opc_ext, rm, );
291
292 let prefix = <Self as EncodeM<M>>::legacy_prefix();
293 let rex = <Self as EncodeM<M>>::rex(&op1);
294
295 self.emit_optional(&[prefix, rex]);
296 self.emit(&[opc, modrm]);
297 match op1.mode() {
298 AddrMode::Indirect => {}
299 AddrMode::IndirectDisp => self.emit(&op1.disp().to_ne_bytes()),
300 AddrMode::IndirectBaseIndex => {
301 self.emit(&[sib(0, op1.index().idx(), op1.base().idx())])
302 }
303 }
304 self.emit(op2.bytes());
305 }
306
307 pub(crate) fn encode_mr<M: Mem, T: Reg>(&mut self, opc: &[u8], op1: M, op2: T)
309 where
310 Self: EncodeMR<M>,
311 {
312 let (mode, rm) = match op1.mode() {
316 AddrMode::Indirect => {
317 assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
318 (0b00, op1.base().idx())
319 }
320 AddrMode::IndirectDisp => {
321 assert!(!op1.base().need_sib());
322 (0b10, op1.base().idx())
323 }
324 AddrMode::IndirectBaseIndex => {
325 assert!(!op1.base().is_pc_rel());
326 assert!(!matches!(op1.index(), Reg64::rsp));
330 (0b00, 0b100)
331 }
332 };
333
334 let modrm = modrm(
335 mode, op2.idx(), rm, );
339
340 let prefix = <Self as EncodeMR<M>>::legacy_prefix();
341 let rex = <Self as EncodeMR<M>>::rex(&op1, op2);
342
343 self.emit_optional(&[prefix, rex]);
344 self.emit(opc);
345 self.emit(&[modrm]);
346 match op1.mode() {
347 AddrMode::Indirect => {}
348 AddrMode::IndirectDisp => self.emit(&op1.disp().to_ne_bytes()),
349 AddrMode::IndirectBaseIndex => {
350 self.emit(&[sib(0, op1.index().idx(), op1.base().idx())])
351 }
352 }
353 }
354
355 pub(crate) fn encode_rm<T: Reg, M: Mem>(&mut self, opc: &[u8], op1: T, op2: M)
357 where
358 Self: EncodeMR<M>,
359 {
360 self.encode_mr(opc, op2, op1);
364 }
365
366 pub(crate) fn encode_jmp_label(&mut self, opc: &[u8], op1: &mut Label) {
368 self.emit(opc);
370
371 op1.record_offset(self.buf.len());
373
374 self.emit(&[0u8; 4]);
377
378 self.resolve(op1);
380 }
381}
382
383pub(crate) trait EncodeRR<T: Reg, U: Reg> {
387 fn legacy_prefix() -> Option<u8> {
388 None
389 }
390
391 fn rex(op1: T, op2: U) -> Option<u8> {
392 if op1.need_rex() || op2.need_rex() {
393 Some(rex(op1.rexw(), op2.idx(), 0, op1.idx()))
394 } else {
395 None
396 }
397 }
398}
399
400impl EncodeRR<Reg8, Reg8> for Asm {}
401impl EncodeRR<Reg16, Reg16> for Asm {
402 fn legacy_prefix() -> Option<u8> {
403 Some(0x66)
404 }
405}
406impl EncodeRR<Reg32, Reg32> for Asm {}
407impl EncodeRR<Reg64, Reg64> for Asm {}
408
409impl EncodeRR<Reg8, Reg32> for Asm {}
410impl EncodeRR<Reg32, Reg8> for Asm {}
411
412pub(crate) trait EncodeR<T: Reg> {
414 fn legacy_prefix() -> Option<u8> {
415 None
416 }
417
418 fn rex(op1: T) -> Option<u8> {
419 if op1.need_rex() {
420 Some(rex(op1.rexw(), 0, 0, op1.idx()))
421 } else {
422 None
423 }
424 }
425}
426
427impl EncodeR<Reg8> for Asm {}
428impl EncodeR<Reg16> for Asm {
429 fn legacy_prefix() -> Option<u8> {
430 Some(0x66)
431 }
432}
433impl EncodeR<Reg32> for Asm {}
434impl EncodeR<Reg64> for Asm {}
435
436pub(crate) trait EncodeMR<M: Mem> {
438 fn legacy_prefix() -> Option<u8> {
439 None
440 }
441
442 fn rex<T: Reg>(op1: &M, op2: T) -> Option<u8> {
443 if M::is_64() || T::is_64() || op2.is_ext() || op1.base().is_ext() || op1.index().is_ext() {
444 Some(rex(
445 M::is_64() || T::is_64(),
446 op2.idx(),
447 op1.index().idx(),
448 op1.base().idx(),
449 ))
450 } else {
451 None
452 }
453 }
454}
455
456impl EncodeMR<Mem8> for Asm {}
457impl EncodeMR<Mem16> for Asm {
458 fn legacy_prefix() -> Option<u8> {
459 Some(0x66)
460 }
461}
462impl EncodeMR<Mem32> for Asm {}
463impl EncodeMR<Mem64> for Asm {}
464
465pub(crate) trait EncodeM<M: Mem> {
467 fn legacy_prefix() -> Option<u8> {
468 None
469 }
470
471 fn rex(op1: &M) -> Option<u8> {
472 if M::is_64() || op1.base().is_ext() || op1.index().is_ext() {
473 Some(rex(M::is_64(), 0, op1.index().idx(), op1.base().idx()))
474 } else {
475 None
476 }
477 }
478}
479
480impl EncodeM<Mem8> for Asm {}
481impl EncodeM<Mem16> for Asm {
482 fn legacy_prefix() -> Option<u8> {
483 Some(0x66)
484 }
485}
486impl EncodeM<Mem32> for Asm {}
487impl EncodeM<Mem64> for Asm {}