1#![allow(dead_code, clippy::all)]
2use super::features::base::MovEmitter;
3use super::opcodes::ALT_TAB;
4use super::operands::*;
5use crate::{
6 core::{
7 buffer::{
8 CodeBuffer, CodeOffset, ConstantData, LabelUse, Reloc, RelocDistance, RelocTarget,
9 },
10 emitter::Emitter,
11 operand::*,
12 patch::{PatchBlockId, PatchSiteId},
13 },
14 X86Error,
15};
16
17pub struct Assembler<'a> {
19 pub buffer: &'a mut CodeBuffer,
20 flags: u64,
21 extra_reg: Reg,
22 last_error: Option<X86Error>,
23}
24
25const RC_RN: u64 = 0x0000000;
26const RC_RD: u64 = 0x0800000;
27const RC_RU: u64 = 0x1000000;
28const RC_RZ: u64 = 0x1800000;
29const SEG_MASK: u64 = 0xe0000000;
30const ADDR32: u64 = 0x10000000;
31const LONG: u64 = 0x100000000;
32
33const OPC_66: u64 = 0x80000;
34const OPC_F2: u64 = 0x100000;
35const OPC_F3: u64 = 0x200000;
36const OPC_REXW: u64 = 0x400000;
37const OPC_LOCK: u64 = 0x800000;
38const OPC_VEXL0: u64 = 0x1000000;
39const OPC_VEXL1: u64 = 0x1800000;
40const OPC_EVEXL0: u64 = 0x2000000;
41const OPC_EVEXL1: u64 = 0x2800000;
42const OPC_EVEXL2: u64 = 0x3000000;
43const OPC_EVEXL3: u64 = 0x3800000;
44const OPC_EVEXB: u64 = 0x4000000;
45const OPC_VSIB: u64 = 0x8000000;
46const OPC_67: u64 = ADDR32;
47const OPC_SEG_MSK: u64 = 0xe0000000;
48const OPC_JMPL: u64 = 0x100000000; const OPC_MASK_MSK: u64 = 0xe00000000;
50const OPC_EVEXZ: u64 = 0x1000000000;
51const OPC_USER_MSK: u64 = OPC_67 | OPC_SEG_MSK | OPC_MASK_MSK;
52const OPC_FORCE_SIB: u64 = 0x2000000000;
53const OPC_DOWNGRADE_VEX: u64 = 0x4000000000;
54const OPC_DOWNGRADE_VEX_FLIPW: u64 = 0x40000000000;
55const OPC_EVEX_DISP8SCALE: u64 = 0x38000000000;
56const OPC_GPH_OP0: u64 = 0x200000000000;
57const OPC_GPH_OP1: u64 = 0x400000000000;
58const EPFX_REX_MSK: u64 = 0x43f;
59const EPFX_REX: u64 = 0x20;
60const EPFX_EVEX: u64 = 0x40;
61const EPFX_REXR: u64 = 0x10;
62const EPFX_REXX: u64 = 0x08;
63const EPFX_REXB: u64 = 0x04;
64const EPFX_REXR4: u64 = 0x02;
65const EPFX_REXB4: u64 = 0x01;
66const EPFX_REXX4: u64 = 0x400;
67const EPFX_VVVV_IDX: u64 = 11;
68
69fn op_imm_n(imm: Operand, immsz: usize) -> bool {
70 if !imm.is_imm() {
71 return false;
72 }
73 let imm = imm.as_::<Imm>();
74 if immsz == 0 && imm.value() == 0 {
75 return true;
76 }
77
78 if immsz == 1 && imm.is_int8() {
79 return true;
80 }
81 if immsz == 2 && imm.is_int16() {
82 return true;
83 }
84 if immsz == 3 && (imm.value() & 0xffffff) == imm.value() {
85 return true;
86 }
87 if immsz == 4 && imm.is_int32() {
88 return true;
89 }
90 if immsz == 8 {
91 return true;
92 }
93
94 false
95}
96
97fn opc_size(opc: u64, epfx: u64) -> usize {
98 let mut res = 1;
99
100 if (opc & OPC_EVEXL0) != 0 {
101 res += 4;
102 } else if (opc & OPC_VEXL0) != 0 {
103 if (opc & (OPC_REXW | 0x20000)) != 0 || (epfx & (EPFX_REXX | EPFX_REXB)) != 0 {
104 res += 3;
105 } else {
106 res += 2;
107 }
108 } else {
109 if (opc & OPC_LOCK) != 0 {
110 res += 1;
111 }
112 if (opc & OPC_66) != 0 {
113 res += 1;
114 }
115 if (opc & (OPC_F2 | OPC_F3)) != 0 {
116 res += 1;
117 }
118 if (opc & OPC_REXW) != 0 || (epfx & EPFX_REX_MSK) != 0 {
119 res += 1;
120 }
121 if (opc & 0x30000) != 0 {
122 res += 1;
123 }
124 if (opc & 0x20000) != 0 {
125 res += 1;
126 }
127 }
128 if (opc & OPC_SEG_MSK) != 0 {
129 res += 1;
130 }
131 if (opc & OPC_67) != 0 {
132 res += 1;
133 }
134 if (opc & 0x8000) != 0 {
135 res += 1;
136 }
137
138 res
139}
140
141#[derive(Copy, Clone, PartialEq, Eq, Debug)]
142enum Encoding {
143 NP,
144 M,
145 R,
146 M1,
147 MC,
148 MR,
149 RM,
150 RMA,
151 MRC,
152 AM,
153 MA,
154 I,
155 O,
156 OA,
157 S,
158 A,
159 D,
160 FD,
161 TD,
162 IM,
163 RVM,
164 RVMR,
165 RMV,
166 VM,
167 MVR,
168 MRV,
169 MAX,
170}
171#[repr(C)]
172#[derive(Copy, Clone, Debug)]
173struct EncodingInfo {
174 modrm: u8,
175 modreg: u8,
176 vexreg: u8,
177 immidx: u8,
178 immctl: u8,
179 zregidx: u8,
180 zregval: u8,
181}
182
183impl EncodingInfo {
184 pub const fn new() -> Self {
185 Self {
186 modreg: 0,
187 modrm: 0,
188 vexreg: 0,
189 immctl: 0,
190 immidx: 0,
191 zregidx: 0,
192 zregval: 0,
193 }
194 }
195}
196
197const ENCODING_INFOS: [EncodingInfo; Encoding::MAX as usize] = [
198 EncodingInfo::new(),
199 EncodingInfo {
200 modrm: 0x0 ^ 3,
201 immidx: 1,
202 ..EncodingInfo::new()
203 },
204 EncodingInfo {
205 modreg: 0x0 ^ 3,
206 ..EncodingInfo::new()
207 },
208 EncodingInfo {
209 modrm: 0x0 ^ 3,
210 immctl: 1,
211 immidx: 1,
212 ..EncodingInfo::new()
213 },
214 EncodingInfo {
215 modrm: 0x0 ^ 3,
216 zregidx: 0x1 ^ 3,
217 zregval: 1,
218 ..EncodingInfo::new()
219 },
220 EncodingInfo {
221 modrm: 0x0 ^ 3,
222 modreg: 0x1 ^ 3,
223 immidx: 2,
224 ..EncodingInfo::new()
225 },
226 EncodingInfo {
227 modrm: 0x1 ^ 3,
228 modreg: 0x0 ^ 3,
229 immidx: 2,
230 ..EncodingInfo::new()
231 },
232 EncodingInfo {
233 modrm: 0x1 ^ 3,
234 modreg: 0x0 ^ 3,
235 zregidx: 0x2 ^ 3,
236 zregval: 0,
237 ..EncodingInfo::new()
238 },
239 EncodingInfo {
240 modrm: 0x0 ^ 3,
241 modreg: 0x1 ^ 3,
242 zregidx: 0x2 ^ 3,
243 zregval: 1,
244 ..EncodingInfo::new()
245 },
246 EncodingInfo {
247 modrm: 0x1 ^ 3,
248 zregidx: 0x0 ^ 3,
249 zregval: 0,
250 ..EncodingInfo::new()
251 },
252 EncodingInfo {
253 modrm: 0x0 ^ 3,
254 zregidx: 0x1 ^ 3,
255 zregval: 0,
256 ..EncodingInfo::new()
257 },
258 EncodingInfo {
259 immidx: 0,
260 ..EncodingInfo::new()
261 },
262 EncodingInfo {
263 modreg: 0x0 ^ 3,
264 immidx: 1,
265 ..EncodingInfo::new()
266 },
267 EncodingInfo {
268 modreg: 0x0 ^ 3,
269 zregidx: 0x1 ^ 3,
270 zregval: 0,
271 ..EncodingInfo::new()
272 },
273 EncodingInfo::new(),
274 EncodingInfo {
275 zregidx: 0x0 ^ 3,
276 zregval: 0,
277 immidx: 1,
278 ..EncodingInfo::new()
279 },
280 EncodingInfo {
281 immidx: 0,
282 ..EncodingInfo::new()
283 },
284 EncodingInfo {
285 zregidx: 0x0 ^ 3,
286 zregval: 0,
287 immctl: 2,
288 immidx: 1,
289 ..EncodingInfo::new()
290 },
291 EncodingInfo {
292 zregidx: 0x1 ^ 3,
293 zregval: 0,
294 immctl: 2,
295 immidx: 0,
296 ..EncodingInfo::new()
297 },
298 EncodingInfo {
299 modrm: 0x1 ^ 3,
300 immidx: 0,
301 ..EncodingInfo::new()
302 },
303 EncodingInfo {
304 modrm: 0x2 ^ 3,
305 modreg: 0x0 ^ 3,
306 vexreg: 0x1 ^ 3,
307 immidx: 3,
308 ..EncodingInfo::new()
309 },
310 EncodingInfo {
311 modrm: 0x2 ^ 3,
312 modreg: 0x0 ^ 3,
313 vexreg: 0x1 ^ 3,
314 immctl: 3,
315 immidx: 3,
316 ..EncodingInfo::new()
317 },
318 EncodingInfo {
319 modrm: 0x1 ^ 3,
320 modreg: 0x0 ^ 3,
321 vexreg: 0x2 ^ 3,
322 ..EncodingInfo::new()
323 },
324 EncodingInfo {
325 modrm: 0x1 ^ 3,
326 vexreg: 0x0 ^ 3,
327 immidx: 2,
328 ..EncodingInfo::new()
329 },
330 EncodingInfo {
331 modrm: 0x0 ^ 3,
332 modreg: 0x2 ^ 3,
333 vexreg: 0x1 ^ 3,
334 ..EncodingInfo::new()
335 },
336 EncodingInfo {
337 modrm: 0x0 ^ 3,
338 modreg: 0x1 ^ 3,
339 vexreg: 0x2 ^ 3,
340 ..EncodingInfo::new()
341 },
342];
343
344impl<'a> Assembler<'a> {
345 pub fn new(buf: &'a mut CodeBuffer) -> Self {
346 Self {
347 buffer: buf,
348 extra_reg: Reg::new(),
349 flags: 0,
350 last_error: None,
351 }
352 }
353
354 pub fn last_error(&self) -> Option<X86Error> {
356 self.last_error.clone()
357 }
358
359 pub fn clear_error(&mut self) {
361 self.last_error = None;
362 }
363
364 pub fn sae(&mut self) -> &mut Self {
365 self.flags |= 0x4000000;
366 self
367 }
368
369 pub fn rn_sae(&mut self) -> &mut Self {
370 self.flags |= 0x4000000 | RC_RN;
371 self
372 }
373
374 pub fn rd_sae(&mut self) -> &mut Self {
375 self.flags |= 0x4000000 | RC_RD;
376 self
377 }
378 pub fn ru_sae(&mut self) -> &mut Self {
379 self.flags |= 0x4000000 | RC_RU;
380 self
381 }
382
383 pub fn rz_sae(&mut self) -> &mut Self {
384 self.flags |= 0x4000000 | RC_RZ;
385 self
386 }
387
388 pub fn seg(&mut self, sreg: SReg) -> &mut Self {
389 self.flags |= ((sreg.id() & 0x7) as u64) << 29;
390 self
391 }
392
393 pub fn fs(&mut self) -> &mut Self {
394 self.seg(FS)
395 }
396
397 pub fn gs(&mut self) -> &mut Self {
398 self.seg(GS)
399 }
400
401 pub fn k(&mut self, k: KReg) -> &mut Self {
402 self.flags |= ((k.id() & 0x7) as u64) << 33;
403
404 self
405 }
406
407 pub fn rep(&mut self) -> &mut Self {
408 self.flags |= 0x200000;
409 self
410 }
411
412 pub fn repnz(&mut self) -> &mut Self {
413 self.flags |= 0x100000;
414 self
415 }
416
417 pub fn repz(&mut self) -> &mut Self {
418 self.rep()
419 }
420
421 pub fn lock(&mut self) -> &mut Self {
422 self.flags |= 0x800000;
423 self
424 }
425
426 pub fn long(&mut self) -> &mut Self {
427 self.flags |= LONG;
428 self
429 }
430
431 pub fn get_label(&mut self) -> Label {
432 self.buffer.get_label()
433 }
434
435 pub fn bind_label(&mut self, label: Label) {
436 self.buffer.bind_label(label);
437 }
438
439 pub fn add_constant(&mut self, c: impl Into<ConstantData>) -> Label {
440 let c = self.buffer.add_constant(c);
441 self.buffer.get_label_for_constant(c)
442 }
443
444 pub fn label_offset(&self, label: Label) -> CodeOffset {
445 self.buffer.label_offset(label)
446 }
447
448 pub fn patchable_jmp(&mut self, label: Label) -> PatchSiteId {
449 self.jmp(label);
450 let offset = self
451 .buffer
452 .cur_offset()
453 .saturating_sub(LabelUse::X86JmpRel32.patch_size() as u32);
454 self.buffer
455 .record_label_patch_site(offset, label, LabelUse::X86JmpRel32)
456 }
457
458 pub fn patchable_call(&mut self, label: Label) -> PatchSiteId {
459 self.call(label);
460 let offset = self
461 .buffer
462 .cur_offset()
463 .saturating_sub(LabelUse::X86JmpRel32.patch_size() as u32);
464 self.buffer
465 .record_label_patch_site(offset, label, LabelUse::X86JmpRel32)
466 }
467
468 pub fn patchable_mov<A, B>(&mut self, dst: A, src: B) -> PatchBlockId
469 where
470 A: OperandCast + Copy,
471 B: OperandCast + Copy,
472 Self: MovEmitter<A, B>,
473 {
474 let dst_op = *dst.as_operand();
475 let src_op = *src.as_operand();
476 if !src_op.is_imm() {
477 unreachable!("patchable_mov currently only supports immediate sources");
478 }
479
480 self.mov::<A, B>(dst, src);
481
482 if dst_op.is_reg_type_of(RegType::Gp64) {
483 let offset = self.buffer.cur_offset().saturating_sub(8);
484 self.buffer.record_patch_block(offset, 8, 1)
485 } else if dst_op.is_reg_type_of(RegType::Gp32) {
486 self.mov::<A, B>(dst, src);
487 let offset = self.buffer.cur_offset().saturating_sub(4);
488 self.buffer.record_patch_block(offset, 4, 1)
489 } else {
490 unreachable!("patchable_mov currently only supports Gp64 and Gp32 destinations");
491 }
492 }
493
494 fn enc_opc(&mut self, opc: u64, epfx: u64) -> bool {
495 if opc & OPC_SEG_MSK != 0 {
496 self.buffer
497 .put1(((0x65643e362e2600u64 >> (8 * ((opc >> 29) & 7))) & 0xff) as u8);
498 }
499
500 if opc & OPC_67 != 0 {
501 self.buffer.put1(0x67);
502 }
503
504 if opc & OPC_EVEXL0 != 0 {
505 self.buffer.put1(0x62);
506 let mut b1 = (opc >> 16 & 7) as u8;
507 if (epfx & EPFX_REXR) == 0 {
508 b1 |= 0x80;
509 }
510 if (epfx & EPFX_REXX) == 0 {
511 b1 |= 0x40;
512 }
513 if (epfx & EPFX_REXB) == 0 {
514 b1 |= 0x20;
515 }
516 if (epfx & EPFX_REXR4) == 0 {
517 b1 |= 0x10;
518 }
519 if (epfx & EPFX_REXB4) != 0 {
520 b1 |= 0x08;
521 }
522 self.buffer.put1(b1);
523
524 let mut b2 = (opc >> 20 & 3) as u8;
525 if (epfx & EPFX_REXX4) == 0 {
526 b2 |= 0x04;
527 }
528 b2 |= ((!(epfx >> EPFX_VVVV_IDX) & 0xf) << 3) as u8;
529 if opc & OPC_REXW != 0 {
530 b2 |= 0x80;
531 }
532 self.buffer.put1(b2);
533
534 let mut b3 = (opc >> 33 & 7) as u8;
535 b3 |= ((!(epfx >> EPFX_VVVV_IDX) & 0x10) >> 1) as u8;
536 if opc & OPC_EVEXB != 0 {
537 b3 |= 0x10;
538 }
539 b3 |= ((opc >> 23 & 3) << 5) as u8;
540 if opc & OPC_EVEXZ != 0 {
541 b3 |= 0x80;
542 }
543 self.buffer.put1(b3);
544 } else if opc & OPC_VEXL0 != 0 {
545 if (epfx & (EPFX_REXR4 | EPFX_REXX4 | EPFX_REXB4 | (0x10 << EPFX_VVVV_IDX))) != 0 {
546 self.last_error = Some(X86Error::InvalidVEX {
547 field: "prefix",
548 reason: "VEX prefix has invalid extended register bits",
549 });
550 return true;
551 }
552
553 let vex3 = (opc & (OPC_REXW | 0x20000)) != 0 || (epfx & (EPFX_REXX | EPFX_REXB)) != 0;
554 let pp = (opc >> 20 & 3) as u8;
555 self.buffer.put1(0xc4 | !vex3 as u8);
556
557 let mut b2 = pp | if (opc & 0x800000) != 0 { 0x4 } else { 0 };
558
559 if vex3 {
560 let mut b1 = (opc >> 16 & 3) as u8;
561 if (epfx & EPFX_REXR) == 0 {
562 b1 |= 0x80;
563 }
564 if (epfx & EPFX_REXX) == 0 {
565 b1 |= 0x40;
566 }
567 if (epfx & EPFX_REXB) == 0 {
568 b1 |= 0x20;
569 }
570 self.buffer.put1(b1);
571
572 if (opc & OPC_REXW) != 0 {
573 b2 |= 0x80;
574 }
575 } else {
576 if (epfx & EPFX_REXR) == 0 {
577 b2 |= 0x80;
578 }
579 }
580
581 b2 |= ((!(epfx >> EPFX_VVVV_IDX) & 0xf) << 3) as u8;
582 self.buffer.put1(b2);
583 } else {
584 if opc & OPC_LOCK != 0 {
585 self.buffer.put1(0xF0);
586 }
587 if opc & OPC_66 != 0 {
588 self.buffer.put1(0x66);
589 }
590 if opc & OPC_F2 != 0 {
591 self.buffer.put1(0xF2);
592 }
593 if opc & OPC_F3 != 0 {
594 self.buffer.put1(0xF3);
595 }
596 if opc & OPC_REXW != 0 || epfx & EPFX_REX_MSK != 0 {
597 let mut rex = 0x40;
598 if opc & OPC_REXW != 0 {
599 rex |= 0x08;
600 }
601 if epfx & EPFX_REXR != 0 {
602 rex |= 0x04;
603 }
604 if epfx & EPFX_REXX != 0 {
605 rex |= 0x02;
606 }
607 if epfx & EPFX_REXB != 0 {
608 rex |= 0x01;
609 }
610 self.buffer.put1(rex);
611 }
612 if opc & 0x30000 != 0 {
613 self.buffer.put1(0x0F);
614 }
615 if opc & 0x30000 == 0x20000 {
616 self.buffer.put1(0x38);
617 }
618 if opc & 0x30000 == 0x30000 {
619 self.buffer.put1(0x3A);
620 }
621 }
622
623 self.buffer.put1((opc & 0xff) as u8);
624 if (opc & 0x8000) != 0 {
625 self.buffer.put1(((opc >> 8) & 0xff) as u8);
626 }
627 false
628 }
629
630 fn encode_imm(&mut self, imm: Operand, immsz: usize) -> bool {
631 if !op_imm_n(imm, immsz) {
632 self.last_error = Some(X86Error::InvalidImmediate {
633 value: imm.as_::<Imm>().value() as i64,
634 size: immsz,
635 reason: "immediate value does not fit in specified size",
636 });
637 return true;
638 }
639 let imm = imm.as_::<Imm>().value() as u64;
640 for i in 0..immsz {
641 self.buffer.put1((imm >> 8 * i) as u8);
642 }
643
644 false
645 }
646
647 fn enc_o(&mut self, opc: u64, mut epfx: u64, op0: Operand) -> bool {
648 if op0.id() & 0x8 != 0 {
649 epfx |= EPFX_REXB;
650 }
651
652 if self.enc_opc(opc, epfx) {
653 return true;
654 }
655
656 let ix = self.buffer.cur_offset() as usize - 1;
657 let byte = self.buffer.data()[ix];
658
659 self.buffer.data_mut()[ix] = (byte & 0xf8) | (op0.id() & 0x7) as u8;
660 false
661 }
662
663 fn enc_mr(
664 &mut self,
665 mut opc: u64,
666 mut epfx: u64,
667 op0: Operand,
668 op1: Operand,
669 immsz: usize,
670 ) -> bool {
671 if op0.is_reg() && op0.id() & 0x8 != 0 {
672 epfx |= EPFX_REXB;
673 }
674
675 if op0.is_reg() && op0.id() & 0x10 != 0 {
676 epfx |= EPFX_REXX | EPFX_EVEX;
677 }
678
679 if op0.is_mem() && op0.as_::<Mem>().base_id() & 0x8 != 0 {
680 epfx |= EPFX_REXB;
681 }
682
683 if op0.is_mem() && op0.as_::<Mem>().base_id() & 0x10 != 0 {
684 epfx |= EPFX_REXB4;
685 }
686
687 if op0.is_mem() && op0.as_::<Mem>().index_id() & 0x8 != 0 {
688 epfx |= EPFX_REXX;
689 }
690
691 if op0.is_mem() && op0.as_::<Mem>().index_id() & 0x10 != 0 {
692 epfx |= if opc & OPC_VSIB != 0 {
693 0x10 << EPFX_VVVV_IDX
694 } else {
695 EPFX_REXX4
696 };
697 }
698 if op1.is_reg() && op1.id() & 0x8 != 0 {
699 epfx |= EPFX_REXR;
700 }
701
702 if op1.is_reg() && op1.id() & 0x10 != 0 {
703 epfx |= EPFX_REXR4;
704 }
705
706 let has_rex =
707 (opc & (OPC_REXW | OPC_VEXL0 | OPC_EVEXL0) != 0) || (epfx & EPFX_REX_MSK) != 0;
708
709 if has_rex && (op0.is_reg_type_of(RegType::Gp8Hi) || op1.is_reg_type_of(RegType::Gp8Hi)) {
710 self.last_error = Some(X86Error::InvalidOperand {
711 operand_index: if op0.is_reg_type_of(RegType::Gp8Hi) {
712 0
713 } else {
714 1
715 },
716 reason: "high-byte registers cannot be used with REX prefix",
717 });
718 return true;
719 }
720
721 if epfx & (EPFX_EVEX | EPFX_REXB4 | EPFX_REXX4 | EPFX_REXR4 | (0x10 << EPFX_VVVV_IDX)) != 0
722 {
723 if (opc & OPC_EVEXL0) == 0 {
724 self.last_error = Some(X86Error::InvalidEVEX {
725 field: "prefix",
726 reason: "EVEX-specific bits set but EVEX prefix not present",
727 });
728 return true;
729 }
730 } else if opc & OPC_DOWNGRADE_VEX != 0 {
731 opc = (opc & !(OPC_EVEXL0 | OPC_EVEX_DISP8SCALE)) | OPC_VEXL0;
732 if opc & OPC_DOWNGRADE_VEX_FLIPW != 0 {
733 opc ^= OPC_REXW;
734 }
735 }
736
737 if op0.is_reg() {
738 if self.enc_opc(opc, epfx) {
739 return true;
740 }
741
742 self.buffer
743 .put1(0xc0 | ((op1.id() & 7) << 3) as u8 | (op0.id() & 7) as u8);
744 return false;
745 }
746
747 let opcsz = opc_size(opc, epfx);
748
749 let mut mod_ = 0;
750 let reg = op1.id() & 7;
751 let mut rm;
752 let mut scale = 0;
753 let mut idx = 4;
754 let mut base = 0;
755 let mut off = op0.as_::<Mem>().offset();
756 let mut withsib = opc & OPC_FORCE_SIB != 0;
757 let mem = op0.as_::<Mem>();
758
759 if mem.has_index() {
760 if opc & OPC_VSIB != 0 {
761 if mem.index_type() != RegType::X86Xmm {
762 self.last_error = Some(X86Error::InvalidVSIB {
763 index_reg: mem.index_id(),
764 reason: "VSIB requires XMM register as index",
765 });
766 return true;
767 }
768
769 if opc & OPC_EVEXL0 != 0 && opc & OPC_MASK_MSK == 0 {
770 self.last_error = Some(X86Error::InvalidMasking {
771 mask_reg: 0,
772 reason: "VSIB with EVEX requires masking",
773 });
774 return true;
775 }
776 } else {
777 if !matches!(mem.index_type(), RegType::Gp32 | RegType::Gp64) {
778 self.last_error = Some(X86Error::InvalidMemoryOperand {
779 base: Some(mem.base_id()),
780 index: Some(mem.index_id()),
781 scale: mem.shift() as _,
782 offset: mem.offset(),
783 reason: "index register must be Gp32 or Gp64",
784 });
785 return true;
786 }
787
788 if mem.index_id() == 4 {
789 self.last_error = Some(X86Error::InvalidSIB {
790 sib: 0,
791 reason: "index register cannot be RSP/R12",
792 });
793 return true;
794 }
795 }
796
797 idx = mem.index_id() & 7;
798 let scalabs = mem.shift();
799 if scalabs & (scalabs.wrapping_sub(1)) != 0 {
800 self.last_error = Some(X86Error::InvalidSIB {
801 sib: 0,
802 reason: "scale must be 1, 2, 4, or 8",
803 });
804 return true;
805 }
806
807 scale = if scalabs & 0xA != 0 { 1 } else { 0 } | if scalabs & 0xC != 0 { 2 } else { 0 };
808 withsib = true;
809 }
810
811 let mut dispsz = 0;
812 let mut label_use = None;
813 let mut reloc = None;
814
815 if !mem.has_base() {
816 base = 5;
817 rm = 4;
818 dispsz = 4;
819 } else if mem.has_base_reg() && mem.base_reg().is_rip() {
820 rm = 5;
821 dispsz = 4;
822 off -= (opcsz + 5 + immsz) as i64;
823 if withsib {
824 self.last_error = Some(X86Error::InvalidRIPRelative {
825 offset: off,
826 reason: "RIP-relative addressing cannot be used with SIB",
827 });
828 return true;
829 }
830 } else if mem.has_base_label() {
831 rm = 5;
832 if withsib {
833 self.last_error = Some(X86Error::InvalidLabel {
834 label_id: mem.base_id(),
835 reason: "label base cannot be used with SIB",
836 });
837 return true;
838 }
839 dispsz = 4;
840 label_use = Some((mem.base_id(), LabelUse::X86JmpRel32));
841 } else if mem.has_base_sym() {
842 rm = 5;
843 if withsib {
844 self.last_error = Some(X86Error::InvalidSymbol {
845 symbol_id: mem.base_id(),
846 reason: "symbol base cannot be used with SIB",
847 });
848 return true;
849 }
850 dispsz = 4;
851 let sym = Sym::from_id(mem.base_id());
852 let distance = self.buffer.symbol_distance(sym);
853
854 if distance == RelocDistance::Near {
855 reloc = Some((sym, Reloc::X86PCRel4));
856 } else {
857 reloc = Some((sym, Reloc::X86GOTPCRel4))
858 }
859 } else {
860 if !matches!(mem.base_type(), RegType::Gp32 | RegType::Gp64) {
861 self.last_error = Some(X86Error::InvalidMemoryOperand {
862 base: Some(mem.base_id()),
863 index: Some(mem.index_id()),
864 scale: mem.shift() as _,
865 offset: mem.offset(),
866 reason: "base register must be Gp32 or Gp64",
867 });
868 return true;
869 }
870
871 rm = mem.base_id() & 0x7;
872
873 if withsib || rm == 4 {
874 base = rm;
875 rm = 4;
876 }
877
878 if off != 0 {
879 let disp8scale = (opc & OPC_EVEX_DISP8SCALE) >> 39;
880
881 if (off & ((1 << (disp8scale)) - 1)) == 0
882 && op_imm_n(*imm(off >> disp8scale).as_operand(), 1)
883 && opc & LONG == 0
884 {
885 mod_ = 0x40;
886 dispsz = 1;
887 off >>= disp8scale;
888 } else {
889 mod_ = 0x80;
890 dispsz = 1;
891 }
892 } else if rm == 5 {
893 mod_ = 0x40;
894 dispsz = 1;
895 }
896 }
897
898 if opcsz + 1 + (rm == 4) as usize + dispsz + immsz > 15 {
899 self.last_error = Some(X86Error::TooLongInstruction {
900 length: opcsz + 1 + (rm == 4) as usize + dispsz + immsz,
901 max_length: 15,
902 });
903 return true;
904 }
905
906 if self.enc_opc(opc, epfx) {
907 return true;
908 }
909
910 self.buffer.put1(mod_ as u8 | (reg << 3) as u8 | rm as u8);
911 if rm == 4 {
912 self.buffer
913 .put1((scale << 6) as u8 | (idx << 3) as u8 | base as u8);
914 }
915 let offset = self.buffer.cur_offset();
916 if let Some((label, label_use)) = label_use {
917 self.buffer
918 .use_label_at_offset(offset, Label::from_id(label), label_use);
919 }
920
921 if let Some((sym, reloc)) = reloc {
922 self.buffer
923 .add_reloc_at_offset(offset, reloc, RelocTarget::Sym(sym), -4);
924 }
925 self.encode_imm(*imm(off).as_operand(), dispsz)
926 }
927}
928
929impl<'a> Emitter for Assembler<'a> {
930 fn emit(&mut self, opcode: i64, op0: &Operand, op1: &Operand, op2: &Operand, op3: &Operand) {
931 let mut opc = opcode as u64;
932 opc |= self.flags;
933 self.flags = 0;
934 let ops = &[*op0, *op1, *op2, *op3];
935
936 let mut epfx = 0;
937
938 if opc & OPC_GPH_OP0 != 0 && op0.is_reg() && op0.id() >= Gp::SP {
939 epfx |= EPFX_REX;
940 } else if opc & OPC_GPH_OP0 == 0 && op0.is_reg_type_of(RegType::Gp8Hi) {
941 self.last_error = Some(X86Error::InvalidRegister {
942 reg_id: op0.id(),
943 reg_type: "Gp8Hi",
944 reason: "high-byte register not allowed in this context",
945 });
946 return;
947 }
948
949 if opc & OPC_GPH_OP1 != 0 && op1.is_reg() && op1.id() >= Gp::SP {
950 epfx |= EPFX_REX;
951 } else if opc & OPC_GPH_OP1 == 0 && op1.is_reg_type_of(RegType::Gp8Hi) {
952 self.last_error = Some(X86Error::InvalidRegister {
953 reg_id: op1.id(),
954 reg_type: "Gp8Hi",
955 reason: "high-byte register not allowed in this context",
956 });
957 return;
958 }
959 let mut label_use = None;
960 let mut reloc = None;
961
962 loop {
963 macro_rules! next {
964 () => {
965 let alt = opc >> 56;
966 if alt != 0 {
967 opc = ALT_TAB[alt as usize] as u64 | (opc & OPC_USER_MSK);
968 continue;
969 }
970 };
971 }
972
973 let enc = (opc >> 51) & 0x1f;
974 let ei = &ENCODING_INFOS[enc as usize];
975 let mut imm = 0xcci64;
976 let mut immsz = (opc >> 47) & 0xf;
977
978 if ei.zregidx != 0 && ops[ei.zregidx as usize ^ 3].id() != 0 {
979 next!();
980 }
981
982 if enc == Encoding::S as u64 {
983 if ((op0.id() as u64) << 3 & 0x20) != (opc & 0x20) {
984 next!();
985 }
986
987 opc |= (op0.id() << 3) as u64;
988 }
989
990 if immsz != 0 {
991 imm = ops[ei.immidx as usize].as_::<Imm>().value() as i64;
992
993 if ei.immctl != 0 {
994 if ei.immctl == 2 {
995 immsz = if opc & OPC_67 != 0 { 4 } else { 8 };
996 if immsz == 4 {
997 imm = imm as i32 as i64; }
999 } else if ei.immctl == 3 {
1000 if !ops[ei.immidx as usize].is_reg_type_of(RegType::X86Xmm) {
1001 self.last_error = Some(X86Error::InvalidRegister {
1002 reg_id: ops[ei.immidx as usize].id(),
1003 reg_type: "X86Xmm",
1004 reason: "expected XMM register for immediate encoding",
1005 });
1006 return;
1007 }
1008 imm = (ops[ei.immidx as usize].id() << 4) as i64;
1009 if !op_imm_n(*crate::core::operand::imm(imm).as_operand(), 1) {
1010 self.last_error = Some(X86Error::InvalidImmediate {
1011 value: imm,
1012 size: 1,
1013 reason: "XMM register index does not fit in 1 byte",
1014 });
1015 return;
1016 }
1017 } else if ei.immctl == 1 {
1018 if imm != 1 {
1019 next!();
1020 }
1021
1022 immsz = 0;
1023 }
1024 } else if enc == Encoding::D as u64 {
1025 let has_alt = opc >> 56 != 0;
1026 let imm_op = ops[ei.immidx as usize];
1028 if imm_op.is_label() {
1029 if immsz == 1 && has_alt {
1030 immsz = 4;
1031 if opc & 0x80 != 0 {
1032 opc -= 2;
1033 } else {
1034 opc += 0x10010;
1035 }
1036 } else if immsz == 1 {
1037 self.last_error = Some(X86Error::InvalidLabel {
1038 label_id: imm_op.id(),
1039 reason: "label requires 32-bit displacement, 8-bit not supported",
1040 });
1041 return;
1042 }
1043 label_use = Some((imm_op.id(), LabelUse::X86JmpRel32));
1044 } else if imm_op.is_sym() {
1045 let sym = imm_op.as_::<Sym>();
1046 if immsz == 1 && has_alt {
1047 immsz = 4;
1048 if opc & 0x80 != 0 {
1049 opc -= 2;
1050 } else {
1051 opc += 0x10010;
1052 }
1053 } else if immsz == 1 {
1054 self.last_error = Some(X86Error::InvalidSymbol {
1055 symbol_id: sym.id(),
1056 reason: "symbol requires 32-bit displacement, 8-bit not supported",
1057 });
1058 return;
1059 }
1060
1061 let distance = self.buffer.symbol_distance(sym);
1062 reloc = Some((
1063 sym,
1064 if distance == RelocDistance::Near {
1065 Reloc::X86PCRel4
1066 } else {
1067 Reloc::X86GOTPCRel4
1068 },
1069 ));
1070 }
1071 } else {
1072 if !op_imm_n(*crate::core::operand::imm(imm).as_operand(), immsz as _) {
1073 next!();
1074 }
1075 }
1076 }
1077
1078 if (opc & 0xfffffff) == 0x90 && ops[0].id() == 0 {
1079 next!();
1080 }
1081
1082 if enc == Encoding::R as u64 {
1083 if self.enc_mr(opc, epfx, Operand::new(), ops[0], immsz as _) {
1084 return;
1085 }
1086 } else if ei.modrm != 0 {
1087 let modreg = if ei.modreg != 0 {
1088 ops[ei.modreg as usize ^ 3]
1089 } else {
1090 *crate::x86::operands::Reg::from_type_and_id(
1091 RegType::Gp64,
1092 ((opc & 0xff00) >> 8) as u32,
1093 )
1094 .as_operand()
1095 };
1096
1097 if ei.vexreg != 0 {
1098 epfx |= (ops[ei.vexreg as usize ^ 3].id() as u64) << EPFX_VVVV_IDX;
1099 }
1100
1101 if self.enc_mr(opc, epfx, ops[(ei.modrm ^ 3) as usize], modreg, immsz as _) {
1102 next!();
1103 }
1104 } else if ei.modreg != 0 {
1105 if self.enc_o(opc, epfx, ops[(ei.modreg ^ 3) as usize]) {
1106 return;
1107 }
1108 } else {
1109 if self.enc_opc(opc, epfx) {
1110 return;
1111 }
1112 }
1113
1114 if immsz != 0 {
1115 let offset = self.buffer.cur_offset();
1116 if let Some((sym, reloc)) = reloc {
1117 self.buffer
1118 .add_reloc_at_offset(offset, reloc, RelocTarget::Sym(sym), -4);
1119 }
1120 if let Some((label_id, label_use)) = label_use {
1121 self.buffer
1122 .use_label_at_offset(offset, Label::from_id(label_id), label_use);
1123 }
1124
1125 if self.encode_imm(*crate::core::operand::imm(imm).as_operand(), immsz as _) {
1126 return;
1127 }
1128 }
1129
1130 self.flags = 0;
1131
1132 break;
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1138pub enum CondCode {
1139 O = 0x0,
1140 NO = 0x1,
1141 C = 0x2,
1142 NC = 0x3,
1143 Z = 0x4,
1144 NZ = 0x5,
1145 BE = 0x6,
1146 A = 0x7,
1147 S = 0x8,
1148 NS = 0x9,
1149 P = 0xa,
1150
1151 NP = 0xb,
1152 L = 0xc,
1153 GE = 0xd,
1154 LE = 0xe,
1155 G = 0xf,
1156}
1157
1158impl CondCode {
1159 pub const B: Self = Self::C;
1160 pub const NAE: Self = Self::C;
1161 pub const AE: Self = Self::NC;
1162 pub const NB: Self = Self::NC;
1163 pub const E: Self = Self::Z;
1164 pub const NE: Self = Self::NZ;
1165 pub const NA: Self = Self::BE;
1166 pub const NBE: Self = Self::A;
1167 pub const PO: Self = Self::NP;
1168 pub const NGE: Self = Self::L;
1169 pub const NL: Self = Self::GE;
1170 pub const NG: Self = Self::LE;
1171 pub const NLE: Self = Self::G;
1172 pub const PE: Self = Self::P;
1173
1174 pub const fn code(self) -> u8 {
1175 self as u8
1176 }
1177
1178 pub fn invert(self) -> Self {
1179 match self {
1180 Self::O => Self::NO,
1181 Self::NO => Self::O,
1182 Self::C => Self::NC,
1183 Self::NC => Self::C,
1184 Self::Z => Self::NZ,
1185 Self::NZ => Self::Z,
1186 Self::BE => Self::A,
1187 Self::A => Self::BE,
1188 Self::S => Self::NS,
1189 Self::NS => Self::S,
1190 Self::P => Self::NP,
1191 Self::NP => Self::P,
1192 Self::L => Self::GE,
1193 Self::GE => Self::L,
1194 Self::LE => Self::G,
1195 Self::G => Self::LE,
1196 }
1197 }
1198}