1use crate::{
5 access_type_enum, instr_category_enum, instr_descriptor, instr_id_enum, instr_id_type_enum,
6 instr_suffix_enum, operand_type_enum, registers_enum, utils,
7};
8
9#[repr(C)]
10#[derive(Debug, Clone)]
11#[allow(non_camel_case_types)]
12pub struct Instruction {
13 word: u32,
14 _mandatorybits: u32,
15 pub unique_id: instr_id_enum::InstrId,
16 descriptor: *const instr_descriptor::InstrDescriptor,
17 instr_id_type: instr_id_type_enum::InstrIdType,
18 pub vram: u32,
19 _handwritten_category: bool,
20 pub in_handwritten_function: bool,
21 pub category: instr_category_enum::InstrCategory,
22 pub flags: u32,
23}
24
25#[link(name = "rabbitizer", kind = "static")]
26extern "C" {
27 fn RabbitizerInstrId_getOpcodeName(
28 unique_id: instr_id_enum::InstrId,
29 ) -> *const core::ffi::c_char;
30}
31
32extern "C" {
33 fn RabInstrIdType_getName(id_type: instr_id_type_enum::InstrIdType)
34 -> *const core::ffi::c_char;
35}
36
37extern "C" {
38 fn RabbitizerInstruction_init(self_: *mut Instruction, word: u32, vram: u32);
39 fn RabbitizerInstruction_destroy(self_: *mut Instruction);
40
41 fn RabbitizerInstruction_processUniqueId(self_: *mut Instruction);
42}
43
44extern "C" {
45 fn RabbitizerInstructionRsp_init(self_: *mut Instruction, word: u32, vram: u32);
46 fn RabbitizerInstructionRsp_destroy(self_: *mut Instruction);
47
48 fn RabbitizerInstructionRsp_processUniqueId(self_: *mut Instruction);
49}
50
51extern "C" {
52 fn RabbitizerInstructionR3000GTE_init(self_: *mut Instruction, word: u32, vram: u32);
53 fn RabbitizerInstructionR3000GTE_destroy(self_: *mut Instruction);
54
55 fn RabbitizerInstructionR3000GTE_processUniqueId(self_: *mut Instruction);
56}
57
58extern "C" {
59 fn RabbitizerInstructionR5900_init(self_: *mut Instruction, word: u32, vram: u32);
60 fn RabbitizerInstructionR5900_destroy(self_: *mut Instruction);
61
62 fn RabbitizerInstructionR5900_processUniqueId(self_: *mut Instruction);
63}
64
65extern "C" {
66 fn RabbitizerInstructionR4000Allegrex_init(self_: *mut Instruction, word: u32, vram: u32);
67 fn RabbitizerInstructionR4000Allegrex_destroy(self_: *mut Instruction);
68
69 fn RabbitizerInstructionR4000Allegrex_processUniqueId(self_: *mut Instruction);
70}
71
72extern "C" {
73 fn RabbitizerInstruction_getRaw(self_: *const Instruction) -> u32;
74 fn RabbitizerInstruction_getProcessedImmediate(self_: *const Instruction) -> i32;
75 fn RabbitizerInstruction_getInstrIndexAsVram(self_: *const Instruction) -> u32;
76 fn RabbitizerInstruction_getBranchOffset(self_: *const Instruction) -> i32;
77
78 fn RabbitizerInstruction_getBranchOffsetGeneric(self_: *const Instruction) -> i32;
79 fn RabbitizerInstruction_getBranchVramGeneric(self_: *const Instruction) -> u32;
80 fn RabbitizerInstruction_getDestinationGpr(self_: *const Instruction) -> i8;
81 fn RabbitizerInstruction_outputsToGprZero(self_: *const Instruction) -> bool;
82 fn RabbitizerInstruction_blankOut(self_: *mut Instruction);
83 fn RabbitizerInstruction_isImplemented(self_: *const Instruction) -> bool;
84 fn RabbitizerInstruction_isLikelyHandwritten(self_: *const Instruction) -> bool;
85 fn RabbitizerInstruction_isNop(self_: *const Instruction) -> bool;
86 fn RabbitizerInstruction_isUnconditionalBranch(self_: *const Instruction) -> bool;
87 fn RabbitizerInstruction_isFunctionCall(self_: *const Instruction) -> bool;
88 fn RabbitizerInstruction_isReturn(self_: *const Instruction) -> bool;
89 fn RabbitizerInstruction_isJumptableJump(self_: *const Instruction) -> bool;
90
91 fn RabbitizerInstruction_hasDelaySlot(self_: *const Instruction) -> bool;
92
93 fn RabbitizerInstruction_sameOpcode(
94 self_: *const Instruction,
95 other: *const Instruction,
96 ) -> bool;
97 fn RabbitizerInstruction_sameOpcodeButDifferentArguments(
98 self_: *const Instruction,
99 other: *const Instruction,
100 ) -> bool;
101 fn RabbitizerInstruction_hasOperand(
102 self_: *const Instruction,
103 operand: operand_type_enum::OperandType,
104 ) -> bool;
105 fn RabbitizerInstruction_hasOperandAlias(
106 self_: *const Instruction,
107 operand: operand_type_enum::OperandType,
108 ) -> bool;
109
110 fn RabbitizerInstruction_isValid(self_: *const Instruction) -> bool;
111
112 fn RabbitizerInstruction_getSizeForBuffer(
113 self_: *const Instruction,
114 immOverrideLength: utils::SizeT,
115 extraLJust: core::ffi::c_int,
116 ) -> utils::SizeT;
117 fn RabbitizerInstruction_disassemble(
118 self_: *const Instruction,
119 dst: *mut core::ffi::c_char,
120 immOverride: *const core::ffi::c_char,
121 immOverrideLength: utils::SizeT,
122 extraLJust: core::ffi::c_int,
123 ) -> utils::SizeT;
124}
125
126extern "C" {
127 fn RabbitizerInstrDescriptor_instrSuffix(
128 self_: *const instr_descriptor::InstrDescriptor,
129 ) -> instr_suffix_enum::InstrSuffix;
130 fn RabbitizerInstrDescriptor_isBranch(self_: *const instr_descriptor::InstrDescriptor) -> bool;
131 fn RabbitizerInstrDescriptor_isBranchLikely(
132 self_: *const instr_descriptor::InstrDescriptor,
133 ) -> bool;
134 fn RabbitizerInstrDescriptor_isJump(self_: *const instr_descriptor::InstrDescriptor) -> bool;
135 fn RabbitizerInstrDescriptor_isJumpWithAddress(
136 self_: *const instr_descriptor::InstrDescriptor,
137 ) -> bool;
138 fn RabbitizerInstrDescriptor_isTrap(self_: *const instr_descriptor::InstrDescriptor) -> bool;
139 fn RabbitizerInstrDescriptor_isFloat(self_: *const instr_descriptor::InstrDescriptor) -> bool;
140 fn RabbitizerInstrDescriptor_isDouble(self_: *const instr_descriptor::InstrDescriptor) -> bool;
141 fn RabbitizerInstrDescriptor_isUnsigned(
142 self_: *const instr_descriptor::InstrDescriptor,
143 ) -> bool;
144
145 fn RabbitizerInstrDescriptor_modifiesRs(
146 self_: *const instr_descriptor::InstrDescriptor,
147 ) -> bool;
148 fn RabbitizerInstrDescriptor_modifiesRt(
149 self_: *const instr_descriptor::InstrDescriptor,
150 ) -> bool;
151 fn RabbitizerInstrDescriptor_modifiesRd(
152 self_: *const instr_descriptor::InstrDescriptor,
153 ) -> bool;
154 fn RabbitizerInstrDescriptor_readsRs(self_: *const instr_descriptor::InstrDescriptor) -> bool;
155 fn RabbitizerInstrDescriptor_readsRt(self_: *const instr_descriptor::InstrDescriptor) -> bool;
156 fn RabbitizerInstrDescriptor_readsRd(self_: *const instr_descriptor::InstrDescriptor) -> bool;
157
158 fn RabbitizerInstrDescriptor_readsHI(self_: *const instr_descriptor::InstrDescriptor) -> bool;
159 fn RabbitizerInstrDescriptor_readsLO(self_: *const instr_descriptor::InstrDescriptor) -> bool;
160 fn RabbitizerInstrDescriptor_modifiesHI(
161 self_: *const instr_descriptor::InstrDescriptor,
162 ) -> bool;
163 fn RabbitizerInstrDescriptor_modifiesLO(
164 self_: *const instr_descriptor::InstrDescriptor,
165 ) -> bool;
166
167 fn RabbitizerInstrDescriptor_modifiesFs(
168 self_: *const instr_descriptor::InstrDescriptor,
169 ) -> bool;
170 fn RabbitizerInstrDescriptor_modifiesFt(
171 self_: *const instr_descriptor::InstrDescriptor,
172 ) -> bool;
173 fn RabbitizerInstrDescriptor_modifiesFd(
174 self_: *const instr_descriptor::InstrDescriptor,
175 ) -> bool;
176 fn RabbitizerInstrDescriptor_readsFs(self_: *const instr_descriptor::InstrDescriptor) -> bool;
177 fn RabbitizerInstrDescriptor_readsFt(self_: *const instr_descriptor::InstrDescriptor) -> bool;
178 fn RabbitizerInstrDescriptor_readsFd(self_: *const instr_descriptor::InstrDescriptor) -> bool;
179
180 fn RabbitizerInstrDescriptor_notEmittedByCompilers(
181 self_: *const instr_descriptor::InstrDescriptor,
182 ) -> bool;
183 fn RabbitizerInstrDescriptor_canBeHi(self_: *const instr_descriptor::InstrDescriptor) -> bool;
184 fn RabbitizerInstrDescriptor_canBeLo(self_: *const instr_descriptor::InstrDescriptor) -> bool;
185 fn RabbitizerInstrDescriptor_doesLink(self_: *const instr_descriptor::InstrDescriptor) -> bool;
186 fn RabbitizerInstrDescriptor_doesDereference(
187 self_: *const instr_descriptor::InstrDescriptor,
188 ) -> bool;
189 fn RabbitizerInstrDescriptor_doesLoad(self_: *const instr_descriptor::InstrDescriptor) -> bool;
190 fn RabbitizerInstrDescriptor_doesStore(self_: *const instr_descriptor::InstrDescriptor)
191 -> bool;
192 fn RabbitizerInstrDescriptor_maybeIsMove(
193 self_: *const instr_descriptor::InstrDescriptor,
194 ) -> bool;
195 fn RabbitizerInstrDescriptor_isPseudo(self_: *const instr_descriptor::InstrDescriptor) -> bool;
196 fn RabbitizerInstrDescriptor_getAccessType(
197 self_: *const instr_descriptor::InstrDescriptor,
198 ) -> access_type_enum::AccessType;
199 fn RabbitizerInstrDescriptor_doesUnsignedMemoryAccess(
200 self_: *const instr_descriptor::InstrDescriptor,
201 ) -> bool;
202}
203
204impl Drop for Instruction {
205 fn drop(&mut self) {
206 unsafe {
207 match self.category {
208 instr_category_enum::InstrCategory::CPU => {
209 RabbitizerInstruction_destroy(self);
210 }
211 instr_category_enum::InstrCategory::RSP => {
212 RabbitizerInstructionRsp_destroy(self);
213 }
214 instr_category_enum::InstrCategory::R3000GTE => {
215 RabbitizerInstructionR3000GTE_destroy(self);
216 }
217 instr_category_enum::InstrCategory::R5900 => {
218 RabbitizerInstructionR5900_destroy(self);
219 }
220 instr_category_enum::InstrCategory::R4000ALLEGREX => {
221 RabbitizerInstructionR4000Allegrex_destroy(self);
222 }
223 instr_category_enum::InstrCategory::MAX => {
224 core::panic!();
225 }
226 }
227 }
228 }
229}
230
231impl Instruction {
232 pub fn new(word: u32, vram: u32, instr_cat: instr_category_enum::InstrCategory) -> Self {
233 unsafe {
234 let mut instr: std::mem::MaybeUninit<Instruction> = std::mem::MaybeUninit::uninit();
235 match instr_cat {
236 instr_category_enum::InstrCategory::CPU => {
237 RabbitizerInstruction_init(instr.as_mut_ptr(), word, vram);
238 RabbitizerInstruction_processUniqueId(instr.as_mut_ptr());
239 }
240 instr_category_enum::InstrCategory::RSP => {
241 RabbitizerInstructionRsp_init(instr.as_mut_ptr(), word, vram);
242 RabbitizerInstructionRsp_processUniqueId(instr.as_mut_ptr());
243 }
244 instr_category_enum::InstrCategory::R3000GTE => {
245 RabbitizerInstructionR3000GTE_init(instr.as_mut_ptr(), word, vram);
246 RabbitizerInstructionR3000GTE_processUniqueId(instr.as_mut_ptr());
247 }
248 instr_category_enum::InstrCategory::R5900 => {
249 RabbitizerInstructionR5900_init(instr.as_mut_ptr(), word, vram);
250 RabbitizerInstructionR5900_processUniqueId(instr.as_mut_ptr());
251 }
252 instr_category_enum::InstrCategory::R4000ALLEGREX => {
253 RabbitizerInstructionR4000Allegrex_init(instr.as_mut_ptr(), word, vram);
254 RabbitizerInstructionR4000Allegrex_processUniqueId(instr.as_mut_ptr());
255 }
256 instr_category_enum::InstrCategory::MAX => {
257 core::panic!();
258 } }
260 instr.assume_init()
261 }
262 }
263
264 pub fn get_opcode(&self) -> u32 {
265 utils::shiftr(self.word, 26, 6)
266 }
267
268 pub fn get_rs(&self) -> u32 {
269 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_rs) {
270 core::panic!();
271 }
272
273 utils::shiftr(self.word, 21, 5)
274 }
275
276 pub fn get_rs_o32(&self) -> registers_enum::registers::GprO32 {
277 self.get_rs().try_into().unwrap()
278 }
279
280 pub fn get_rs_n32(&self) -> registers_enum::registers::GprN32 {
281 self.get_rs().try_into().unwrap()
282 }
283
284 pub fn get_rt(&self) -> u32 {
285 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_rt) {
286 core::panic!();
287 }
288
289 utils::shiftr(self.word, 16, 5)
290 }
291
292 pub fn get_rt_o32(&self) -> registers_enum::registers::GprO32 {
293 self.get_rt().try_into().unwrap()
294 }
295
296 pub fn get_rt_n32(&self) -> registers_enum::registers::GprN32 {
297 self.get_rt().try_into().unwrap()
298 }
299
300 pub fn get_rd(&self) -> u32 {
301 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_rd) {
302 core::panic!();
303 }
304
305 utils::shiftr(self.word, 11, 5)
306 }
307
308 pub fn get_rd_o32(&self) -> registers_enum::registers::GprO32 {
309 self.get_rd().try_into().unwrap()
310 }
311
312 pub fn get_rd_n32(&self) -> registers_enum::registers::GprN32 {
313 self.get_rd().try_into().unwrap()
314 }
315
316 pub fn get_sa(&self) -> u32 {
317 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_sa) {
318 core::panic!();
319 }
320
321 utils::shiftr(self.word, 6, 5)
322 }
323
324 pub fn get_function(&self) -> u32 {
325 utils::shiftr(self.word, 0, 6)
330 }
331
332 pub fn get_cop0d(&self) -> u32 {
333 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_cop0d) {
334 core::panic!();
335 }
336
337 utils::shiftr(self.word, 11, 5)
338 }
339
340 pub fn get_cop0d_cop0(&self) -> registers_enum::registers::Cop0 {
341 self.get_cop0d().try_into().unwrap()
342 }
343
344 pub fn get_instr_index(&self) -> u32 {
345 utils::shiftr(self.word, 0, 26)
346 }
347
348 pub fn get_immediate(&self) -> u16 {
349 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_immediate) {
350 core::panic!();
351 }
352
353 utils::shiftr(self.word, 0, 16).try_into().unwrap()
354 }
355
356 pub fn get_code(&self) -> u32 {
357 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_code) {
358 core::panic!();
359 }
360
361 utils::shiftr(self.word, 6, 20)
362 }
363
364 pub fn get_code_upper(&self) -> u32 {
365 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_code) {
366 core::panic!();
367 }
368
369 utils::shiftr(self.word, 16, 10)
370 }
371
372 pub fn get_code_lower(&self) -> u32 {
373 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_code_lower) {
374 core::panic!();
375 }
376
377 utils::shiftr(self.word, 6, 10)
378 }
379
380 pub fn get_copraw(&self) -> u32 {
381 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_copraw) {
382 core::panic!();
383 }
384
385 utils::shiftr(self.word, 0, 25)
386 }
387
388 pub fn get_fs(&self) -> u32 {
389 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_fs) {
390 core::panic!();
391 }
392
393 utils::shiftr(self.word, 11, 5)
394 }
395
396 pub fn get_fs_o32(&self) -> registers_enum::registers::Cop1O32 {
397 self.get_fs().try_into().unwrap()
398 }
399
400 pub fn get_fs_n32(&self) -> registers_enum::registers::Cop1N32 {
401 self.get_fs().try_into().unwrap()
402 }
403
404 pub fn get_fs_n64(&self) -> registers_enum::registers::Cop1N64 {
405 self.get_fs().try_into().unwrap()
406 }
407
408 pub fn get_ft(&self) -> u32 {
409 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_ft) {
410 core::panic!();
411 }
412
413 utils::shiftr(self.word, 16, 5)
414 }
415
416 pub fn get_ft_o32(&self) -> registers_enum::registers::Cop1O32 {
417 self.get_ft().try_into().unwrap()
418 }
419
420 pub fn get_ft_n32(&self) -> registers_enum::registers::Cop1N32 {
421 self.get_ft().try_into().unwrap()
422 }
423
424 pub fn get_ft_n64(&self) -> registers_enum::registers::Cop1N64 {
425 self.get_ft().try_into().unwrap()
426 }
427
428 pub fn get_fd(&self) -> u32 {
429 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_fd) {
430 core::panic!();
431 }
432
433 utils::shiftr(self.word, 6, 5)
434 }
435
436 pub fn get_fd_o32(&self) -> registers_enum::registers::Cop1O32 {
437 self.get_fd().try_into().unwrap()
438 }
439
440 pub fn get_fd_n32(&self) -> registers_enum::registers::Cop1N32 {
441 self.get_fd().try_into().unwrap()
442 }
443
444 pub fn get_fd_n64(&self) -> registers_enum::registers::Cop1N64 {
445 self.get_fd().try_into().unwrap()
446 }
447
448 pub fn get_cop1cs(&self) -> u32 {
449 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_cop1cs) {
450 core::panic!();
451 }
452
453 utils::shiftr(self.word, 11, 5)
454 }
455
456 pub fn get_cop1cs_cop1control(&self) -> registers_enum::registers::Cop1Control {
457 self.get_cop1cs().try_into().unwrap()
458 }
459
460 pub fn get_cop2t(&self) -> u32 {
461 if !self.has_operand_alias(operand_type_enum::OperandType::cpu_cop2t) {
462 core::panic!();
463 }
464
465 utils::shiftr(self.word, 16, 5)
466 }
467
468 pub fn get_cop2t_cop2(&self) -> registers_enum::registers::Cop2 {
469 self.get_cop2t().try_into().unwrap()
470 }
471
472 pub fn flags_get_r5900_disasm_as_data(&self) -> utils::TrinaryValue {
473 utils::shiftr(self.flags, 0, 2).try_into().unwrap()
474 }
475 pub fn flags_set_r5900_disasm_as_data(&mut self, value: utils::TrinaryValue) {
476 self.flags = utils::bitrepack(self.flags, value.into(), 0, 2);
477 }
478
479 pub fn flags_get_r5900_use_dollar(&self) -> utils::TrinaryValue {
480 utils::shiftr(self.flags, 2, 2).try_into().unwrap()
481 }
482 pub fn flags_set_r5900_use_dollar(&mut self, value: utils::TrinaryValue) {
483 self.flags = utils::bitrepack(self.flags, value.into(), 2, 2);
484 }
485
486 pub fn instr_id_type_name(&self) -> &'static str {
487 unsafe { std::ffi::CStr::from_ptr(RabInstrIdType_getName(self.instr_id_type)) }
488 .to_str()
489 .unwrap()
490 }
491
492 pub fn raw(&self) -> u32 {
493 unsafe { RabbitizerInstruction_getRaw(self) }
494 }
495 pub fn processed_immediate(&self) -> i32 {
496 unsafe { RabbitizerInstruction_getProcessedImmediate(self) }
497 }
498 pub fn instr_index_as_vram(&self) -> u32 {
499 unsafe { RabbitizerInstruction_getInstrIndexAsVram(self) }
500 }
501 pub fn branch_offset(&self) -> i32 {
502 unsafe { RabbitizerInstruction_getBranchOffset(self) }
503 }
504
505 pub fn branch_offset_generic(&self) -> i32 {
506 unsafe { RabbitizerInstruction_getBranchOffsetGeneric(self) }
507 }
508
509 pub fn branch_vram_generic(&self) -> u32 {
510 unsafe { RabbitizerInstruction_getBranchVramGeneric(self) }
511 }
512 pub fn destination_gpr(&self) -> Option<u32> {
513 unsafe {
514 let reg: i8 = RabbitizerInstruction_getDestinationGpr(self);
515
516 if reg < 0 {
517 return None;
518 }
519 Some(reg as u32)
520 }
521 }
522 pub fn outputs_to_gpr_zero(&self) -> bool {
523 unsafe { RabbitizerInstruction_outputsToGprZero(self) }
524 }
525 pub fn opcode_name(&self) -> &'static str {
526 unsafe {
527 std::ffi::CStr::from_ptr(RabbitizerInstrId_getOpcodeName(self.unique_id))
528 .to_str()
529 .unwrap()
530 }
531 }
532
533 pub fn blank_out(mut self) {
534 unsafe { RabbitizerInstruction_blankOut(&mut self) }
535 }
536
537 #[deprecated(since = "1.8.4", note = "please use `is_valid` instead")]
538 pub fn is_implemented(&self) -> bool {
539 unsafe { RabbitizerInstruction_isImplemented(self) }
540 }
541 pub fn is_likely_handwritten(&self) -> bool {
542 unsafe { RabbitizerInstruction_isLikelyHandwritten(self) }
543 }
544 pub fn is_nop(&self) -> bool {
545 unsafe { RabbitizerInstruction_isNop(self) }
546 }
547 pub fn is_unconditional_branch(&self) -> bool {
548 unsafe { RabbitizerInstruction_isUnconditionalBranch(self) }
549 }
550 pub fn is_function_call(&self) -> bool {
551 unsafe { RabbitizerInstruction_isFunctionCall(self) }
552 }
553
554 pub fn is_return(&self) -> bool {
555 unsafe { RabbitizerInstruction_isReturn(self) }
556 }
557 pub fn is_jumptable_jump(&self) -> bool {
558 unsafe { RabbitizerInstruction_isJumptableJump(self) }
559 }
560
561 pub fn has_delay_slot(&self) -> bool {
562 unsafe { RabbitizerInstruction_hasDelaySlot(self) }
563 }
564
565 pub fn same_opcode(&self, other: &Instruction) -> bool {
566 unsafe { RabbitizerInstruction_sameOpcode(self, other) }
567 }
568 pub fn same_opcode_but_different_arguments(&self, other: &Instruction) -> bool {
569 unsafe { RabbitizerInstruction_sameOpcodeButDifferentArguments(self, other) }
570 }
571
572 pub fn has_operand(&self, operand: operand_type_enum::OperandType) -> bool {
573 unsafe { RabbitizerInstruction_hasOperand(self, operand) }
574 }
575 pub fn has_operand_alias(&self, operand: operand_type_enum::OperandType) -> bool {
576 unsafe { RabbitizerInstruction_hasOperandAlias(self, operand) }
577 }
578
579 pub fn is_valid(&self) -> bool {
580 unsafe { RabbitizerInstruction_isValid(self) }
581 }
582
583 pub fn get_operand_type(&self, index: usize) -> operand_type_enum::OperandType {
584 unsafe { &*self.descriptor }.get_operand_type(index)
585 }
586
587 pub fn get_operands_slice(&self) -> &[operand_type_enum::OperandType] {
588 unsafe { &*self.descriptor }.operands_slice()
589 }
590
591 pub fn instr_suffix(&self) -> instr_suffix_enum::InstrSuffix {
592 unsafe { RabbitizerInstrDescriptor_instrSuffix(self.descriptor) }
593 }
594 pub fn is_branch(&self) -> bool {
595 unsafe { RabbitizerInstrDescriptor_isBranch(self.descriptor) }
596 }
597 pub fn is_branch_likely(&self) -> bool {
598 unsafe { RabbitizerInstrDescriptor_isBranchLikely(self.descriptor) }
599 }
600 pub fn is_jump(&self) -> bool {
601 unsafe { RabbitizerInstrDescriptor_isJump(self.descriptor) }
602 }
603 pub fn is_jump_with_address(&self) -> bool {
604 unsafe { RabbitizerInstrDescriptor_isJumpWithAddress(self.descriptor) }
605 }
606 pub fn is_trap(&self) -> bool {
607 unsafe { RabbitizerInstrDescriptor_isTrap(self.descriptor) }
608 }
609 pub fn is_float(&self) -> bool {
610 unsafe { RabbitizerInstrDescriptor_isFloat(self.descriptor) }
611 }
612 pub fn is_double(&self) -> bool {
613 unsafe { RabbitizerInstrDescriptor_isDouble(self.descriptor) }
614 }
615 pub fn is_unsigned(&self) -> bool {
616 unsafe { RabbitizerInstrDescriptor_isUnsigned(self.descriptor) }
617 }
618 pub fn modifies_rs(&self) -> bool {
619 unsafe { RabbitizerInstrDescriptor_modifiesRs(self.descriptor) }
620 }
621 pub fn modifies_rt(&self) -> bool {
622 unsafe { RabbitizerInstrDescriptor_modifiesRt(self.descriptor) }
623 }
624 pub fn modifies_rd(&self) -> bool {
625 unsafe { RabbitizerInstrDescriptor_modifiesRd(self.descriptor) }
626 }
627 pub fn reads_rs(&self) -> bool {
628 unsafe { RabbitizerInstrDescriptor_readsRs(self.descriptor) }
629 }
630 pub fn reads_rt(&self) -> bool {
631 unsafe { RabbitizerInstrDescriptor_readsRt(self.descriptor) }
632 }
633 pub fn reads_rd(&self) -> bool {
634 unsafe { RabbitizerInstrDescriptor_readsRd(self.descriptor) }
635 }
636 pub fn reads_hi(&self) -> bool {
637 unsafe { RabbitizerInstrDescriptor_readsHI(self.descriptor) }
638 }
639 pub fn reads_lo(&self) -> bool {
640 unsafe { RabbitizerInstrDescriptor_readsLO(self.descriptor) }
641 }
642 pub fn modifies_hi(&self) -> bool {
643 unsafe { RabbitizerInstrDescriptor_modifiesHI(self.descriptor) }
644 }
645 pub fn modifies_lo(&self) -> bool {
646 unsafe { RabbitizerInstrDescriptor_modifiesLO(self.descriptor) }
647 }
648 pub fn modifies_fs(&self) -> bool {
649 unsafe { RabbitizerInstrDescriptor_modifiesFs(self.descriptor) }
650 }
651 pub fn modifies_ft(&self) -> bool {
652 unsafe { RabbitizerInstrDescriptor_modifiesFt(self.descriptor) }
653 }
654 pub fn modifies_fd(&self) -> bool {
655 unsafe { RabbitizerInstrDescriptor_modifiesFd(self.descriptor) }
656 }
657 pub fn reads_fs(&self) -> bool {
658 unsafe { RabbitizerInstrDescriptor_readsFs(self.descriptor) }
659 }
660 pub fn reads_ft(&self) -> bool {
661 unsafe { RabbitizerInstrDescriptor_readsFt(self.descriptor) }
662 }
663 pub fn reads_fd(&self) -> bool {
664 unsafe { RabbitizerInstrDescriptor_readsFd(self.descriptor) }
665 }
666
667 pub fn not_emited_by_compilers(&self) -> bool {
669 unsafe { RabbitizerInstrDescriptor_notEmittedByCompilers(self.descriptor) }
670 }
671 pub fn not_emitted_by_compilers(&self) -> bool {
672 unsafe { RabbitizerInstrDescriptor_notEmittedByCompilers(self.descriptor) }
673 }
674 pub fn can_be_hi(&self) -> bool {
675 unsafe { RabbitizerInstrDescriptor_canBeHi(self.descriptor) }
676 }
677 pub fn can_be_lo(&self) -> bool {
678 unsafe { RabbitizerInstrDescriptor_canBeLo(self.descriptor) }
679 }
680 pub fn does_link(&self) -> bool {
681 unsafe { RabbitizerInstrDescriptor_doesLink(self.descriptor) }
682 }
683 pub fn does_dereference(&self) -> bool {
684 unsafe { RabbitizerInstrDescriptor_doesDereference(self.descriptor) }
685 }
686 pub fn does_load(&self) -> bool {
687 unsafe { RabbitizerInstrDescriptor_doesLoad(self.descriptor) }
688 }
689 pub fn does_store(&self) -> bool {
690 unsafe { RabbitizerInstrDescriptor_doesStore(self.descriptor) }
691 }
692 pub fn maybe_is_move(&self) -> bool {
693 unsafe { RabbitizerInstrDescriptor_maybeIsMove(self.descriptor) }
694 }
695 pub fn is_pseudo(&self) -> bool {
696 unsafe { RabbitizerInstrDescriptor_isPseudo(self.descriptor) }
697 }
698 pub fn access_type(&self) -> access_type_enum::AccessType {
699 unsafe { RabbitizerInstrDescriptor_getAccessType(self.descriptor) }
700 }
701 pub fn does_unsigned_memory_access(&self) -> bool {
702 unsafe { RabbitizerInstrDescriptor_doesUnsignedMemoryAccess(self.descriptor) }
703 }
704
705 pub fn disassemble(
706 &self,
707 imm_override: Option<&str>,
708 extra_l_just: core::ffi::c_int,
709 ) -> String {
710 let (imm_override_ptr, imm_override_len) = utils::c_string_from_str(imm_override);
711
712 unsafe {
713 let buffer_size =
714 RabbitizerInstruction_getSizeForBuffer(self, imm_override_len, extra_l_just);
715
716 let mut buffer: Vec<u8> = vec![0; buffer_size + 1];
717 let disassembled_size = RabbitizerInstruction_disassemble(
718 self,
719 buffer.as_mut_ptr() as *mut core::ffi::c_char,
720 imm_override_ptr,
721 imm_override_len,
722 extra_l_just,
723 );
724 buffer.truncate(disassembled_size);
725
726 String::from_utf8(buffer).unwrap()
727 }
728 }
729}