1use crate::{
34 BasicBlock, ImmediateDesc, Instruction, Op, Operand, RegisterDesc, RegisterFlags, Vip,
35};
36use std::convert::TryInto;
37
38const VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN: usize = 2;
39
40pub struct InstructionBuilder<'a> {
42 pub vip: Vip,
44 pub basic_block: &'a mut BasicBlock,
46}
47
48fn insert_instr(builder: &mut InstructionBuilder, op: Op) {
50 let vip = if builder.vip != Vip::invalid() {
51 let vip = builder.vip;
52 builder.vip = Vip::invalid();
53 vip
54 } else {
55 builder.vip
56 };
57
58 let sp_offset = builder.basic_block.sp_offset;
59 let sp_index = builder.basic_block.sp_index;
60
61 builder.basic_block.instructions.push(Instruction {
62 op,
63 vip,
64 sp_offset,
65 sp_index,
66 sp_reset: false,
67 });
68}
69
70impl<'a> InstructionBuilder<'a> {
71 pub fn from(basic_block: &'a mut BasicBlock) -> InstructionBuilder<'a> {
73 InstructionBuilder {
74 vip: Vip::invalid(),
75 basic_block,
76 }
77 }
78
79 pub fn shift_sp(&mut self, offset: i64) {
81 self.basic_block.sp_offset += offset;
82 }
83
84 pub fn push(&mut self, op1: Operand) -> &mut Self {
86 if let Operand::RegisterDesc(sp) = op1 {
87 if sp.flags.contains(RegisterFlags::STACK_POINTER) {
88 let tmp0 = self.basic_block.tmp(64);
89 self.mov(tmp0, op1).push(tmp0.into());
90 return self;
91 }
92 }
93
94 let misalignment = (op1.size() % VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN) as i64;
95 if misalignment != 0 {
96 let padding_size = VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN as i64 - misalignment;
97 self.shift_sp(-padding_size);
98 self.str(
99 RegisterDesc::SP,
100 self.basic_block.sp_offset.into(),
101 ImmediateDesc::new(0u64, TryInto::<u32>::try_into(padding_size).unwrap() * 8)
102 .into(),
103 );
104 }
105
106 self.shift_sp(-(op1.size() as i64));
107 self.str(RegisterDesc::SP, self.basic_block.sp_offset.into(), op1);
108
109 self
110 }
111
112 pub fn pop(&mut self, op1: RegisterDesc) -> &mut Self {
114 let offset = self.basic_block.sp_offset;
115
116 let misalignment = (op1.size() % VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN) as i64;
117 if misalignment != 0 {
118 self.shift_sp(VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN as i64 - misalignment);
119 }
120
121 self.shift_sp(op1.size() as i64);
122 self.ldd(op1, RegisterDesc::SP, offset.into());
123
124 self
125 }
126
127 pub fn pushf(&mut self) -> &mut Self {
129 self.push(RegisterDesc::FLAGS.into())
130 }
131
132 pub fn popf(&mut self) -> &mut Self {
134 self.push(RegisterDesc::FLAGS.into())
135 }
136
137 pub fn mov(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
139 insert_instr(self, Op::Mov(op1.into(), op2.into()));
140 self
141 }
142
143 pub fn movsx(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
145 insert_instr(self, Op::Movsx(op1.into(), op2.into()));
146 self
147 }
148
149 pub fn str(&mut self, op1: RegisterDesc, op2: ImmediateDesc, op3: Operand) -> &mut Self {
151 insert_instr(self, Op::Str(op1.into(), op2.into(), op3.into()));
152 self
153 }
154
155 pub fn ldd(&mut self, op1: RegisterDesc, op2: RegisterDesc, op3: ImmediateDesc) -> &mut Self {
157 insert_instr(self, Op::Ldd(op1.into(), op2.into(), op3.into()));
158 self
159 }
160
161 pub fn neg(&mut self, op1: RegisterDesc) -> &mut Self {
163 insert_instr(self, Op::Neg(op1.into()));
164 self
165 }
166
167 pub fn add(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
169 insert_instr(self, Op::Add(op1.into(), op2.into()));
170 self
171 }
172
173 pub fn sub(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
175 insert_instr(self, Op::Sub(op1.into(), op2.into()));
176 self
177 }
178
179 pub fn mul(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
181 insert_instr(self, Op::Mul(op1.into(), op2.into()));
182 self
183 }
184
185 pub fn mulhi(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
187 insert_instr(self, Op::Mulhi(op1.into(), op2.into()));
188 self
189 }
190
191 pub fn imul(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
193 insert_instr(self, Op::Imul(op1.into(), op2.into()));
194 self
195 }
196
197 pub fn imulhi(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
199 insert_instr(self, Op::Imulhi(op1.into(), op2.into()));
200 self
201 }
202
203 pub fn div(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
205 insert_instr(self, Op::Div(op1.into(), op2.into(), op3.into()));
206 self
207 }
208
209 pub fn rem(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
211 insert_instr(self, Op::Rem(op1.into(), op2.into(), op3.into()));
212 self
213 }
214
215 pub fn idiv(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
217 insert_instr(self, Op::Idiv(op1.into(), op2.into(), op3.into()));
218 self
219 }
220
221 pub fn irem(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
223 insert_instr(self, Op::Irem(op1.into(), op2.into(), op3.into()));
224 self
225 }
226
227 pub fn popcnt(&mut self, op1: RegisterDesc) -> &mut Self {
229 insert_instr(self, Op::Popcnt(op1.into()));
230 self
231 }
232
233 pub fn bsf(&mut self, op1: RegisterDesc) -> &mut Self {
235 insert_instr(self, Op::Bsf(op1.into()));
236 self
237 }
238
239 pub fn bsr(&mut self, op1: RegisterDesc) -> &mut Self {
241 insert_instr(self, Op::Bsr(op1.into()));
242 self
243 }
244
245 pub fn not(&mut self, op1: RegisterDesc) -> &mut Self {
247 insert_instr(self, Op::Not(op1.into()));
248 self
249 }
250
251 pub fn shr(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
253 insert_instr(self, Op::Shr(op1.into(), op2.into()));
254 self
255 }
256
257 pub fn shl(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
259 insert_instr(self, Op::Shl(op1.into(), op2.into()));
260 self
261 }
262
263 pub fn xor(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
265 insert_instr(self, Op::Xor(op1.into(), op2.into()));
266 self
267 }
268
269 pub fn or(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
271 insert_instr(self, Op::Or(op1.into(), op2.into()));
272 self
273 }
274
275 pub fn and(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
277 insert_instr(self, Op::And(op1.into(), op2.into()));
278 self
279 }
280
281 pub fn ror(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
283 insert_instr(self, Op::Ror(op1.into(), op2.into()));
284 self
285 }
286
287 pub fn rol(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
289 insert_instr(self, Op::Rol(op1.into(), op2.into()));
290 self
291 }
292
293 pub fn tg(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
295 insert_instr(self, Op::Tg(op1.into(), op2.into(), op3.into()));
296 self
297 }
298
299 pub fn tge(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
301 insert_instr(self, Op::Tge(op1.into(), op2.into(), op3.into()));
302 self
303 }
304
305 pub fn te(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
307 insert_instr(self, Op::Te(op1.into(), op2.into(), op3.into()));
308 self
309 }
310
311 pub fn tne(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
313 insert_instr(self, Op::Tne(op1.into(), op2.into(), op3.into()));
314 self
315 }
316
317 pub fn tl(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
319 insert_instr(self, Op::Tl(op1.into(), op2.into(), op3.into()));
320 self
321 }
322
323 pub fn tle(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
325 insert_instr(self, Op::Tle(op1.into(), op2.into(), op3.into()));
326 self
327 }
328
329 pub fn tug(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
331 insert_instr(self, Op::Tug(op1.into(), op2.into(), op3.into()));
332 self
333 }
334
335 pub fn tuge(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
337 insert_instr(self, Op::Tuge(op1.into(), op2.into(), op3.into()));
338 self
339 }
340
341 pub fn tul(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
343 insert_instr(self, Op::Tul(op1.into(), op2.into(), op3.into()));
344 self
345 }
346
347 pub fn tule(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
349 insert_instr(self, Op::Tule(op1.into(), op2.into(), op3.into()));
350 self
351 }
352
353 pub fn ifs(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
355 insert_instr(self, Op::Ifs(op1.into(), op2.into(), op3.into()));
356 self
357 }
358
359 pub fn js(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
361 insert_instr(self, Op::Js(op1.into(), op2.into(), op3.into()));
362 self
363 }
364
365 pub fn jmp(&mut self, op1: Operand) -> &mut Self {
367 insert_instr(self, Op::Jmp(op1.into()));
368 self
369 }
370
371 pub fn vexit(&mut self, op1: Operand) -> &mut Self {
373 insert_instr(self, Op::Vexit(op1.into()));
374 self
375 }
376
377 pub fn vxcall(&mut self, op1: Operand) -> &mut Self {
379 insert_instr(self, Op::Vxcall(op1.into()));
380 self
381 }
382
383 pub fn nop(&mut self) -> &mut Self {
385 insert_instr(self, Op::Nop);
386 self
387 }
388
389 pub fn sfence(&mut self) -> &mut Self {
391 insert_instr(self, Op::Sfence);
392 self
393 }
394
395 pub fn lfence(&mut self) -> &mut Self {
397 insert_instr(self, Op::Lfence);
398 self
399 }
400
401 pub fn vemit(&mut self, op1: ImmediateDesc) -> &mut Self {
403 insert_instr(self, Op::Vemit(op1.into()));
404 self
405 }
406
407 pub fn vpinr(&mut self, op1: RegisterDesc) -> &mut Self {
409 insert_instr(self, Op::Vpinr(op1.into()));
410 self
411 }
412
413 pub fn vpinw(&mut self, op1: RegisterDesc) -> &mut Self {
415 insert_instr(self, Op::Vpinw(op1.into()));
416 self
417 }
418
419 pub fn vpinrm(
421 &mut self,
422 op1: RegisterDesc,
423 op2: ImmediateDesc,
424 op3: ImmediateDesc,
425 ) -> &mut Self {
426 insert_instr(self, Op::Vpinrm(op1.into(), op2.into(), op3.into()));
427 self
428 }
429
430 pub fn vpinwm(
432 &mut self,
433 op1: RegisterDesc,
434 op2: ImmediateDesc,
435 op3: ImmediateDesc,
436 ) -> &mut Self {
437 insert_instr(self, Op::Vpinwm(op1.into(), op2.into(), op3.into()));
438 self
439 }
440}
441
442#[cfg(test)]
443mod test {
444 #[test]
445 fn basic() {
446 use crate::*;
447
448 let mut routine = Routine::new(ArchitectureIdentifier::Virtual);
449 let basic_block = routine.create_block(Vip(0)).unwrap();
450 let tmp0 = basic_block.tmp(64);
451 let mut builder = InstructionBuilder::from(basic_block);
452 builder.mov(tmp0, 0xA57E6F0335298D0u64.into());
453
454 assert_eq!(basic_block.instructions.len(), 1);
455 let instr = &basic_block.instructions[0];
456 assert!(matches!(instr.op, Op::Mov(_, _)));
457 }
458}