1use super::types::*;
2use crate::ext::io::*;
3use crate::types::*;
4use crate::utils::struct_pack::*;
5use anyhow::Result;
6use std::collections::HashMap;
7use std::io::{Seek, Write};
8
9fn escape_string(s: &str) -> String {
10 s.replace("\\", "\\\\")
11 .replace("\r", "\\r")
12 .replace("\n", "\\n")
13 .replace("\t", "\\t")
14}
15
16#[allow(dead_code)]
17pub struct ECSExecutionImageDisassembler<'a> {
18 pub stream: MemReaderRef<'a>,
19 function: &'a SectionFunction,
20 func_info: &'a SectionFuncInfo,
21 import_native_func: &'a SectionImportNativeFunc,
22 class_info: &'a SectionClassInfo,
23 const_string: &'a SectionConstString,
24 pub assembly: ECSExecutionImageAssembly,
25 writer: Option<Box<dyn Write + 'a>>,
26 addr: u32,
27 code: CSInstructionCode,
28 pub func_map: HashMap<u32, &'a FuncInfoEntry>,
29}
30
31impl<'a> ECSExecutionImageDisassembler<'a> {
32 pub fn new(
33 stream: MemReaderRef<'a>,
34 function: &'a SectionFunction,
35 func_info: &'a SectionFuncInfo,
36 import_native_func: &'a SectionImportNativeFunc,
37 class_info: &'a SectionClassInfo,
38 const_string: &'a SectionConstString,
39 writer: Option<Box<dyn Write + 'a>>,
40 ) -> Self {
41 Self {
42 stream,
43 function,
44 func_info,
45 import_native_func,
46 class_info,
47 const_string,
48 assembly: ECSExecutionImageAssembly {
49 commands: Vec::new(),
50 },
51 writer,
52 addr: 0,
53 code: CsicNew,
54 func_map: func_info
55 .functions
56 .iter()
57 .map_while(|x| {
58 if x.header.bytes == 0 {
59 None
60 } else {
61 Some((x.header.address, x))
62 }
63 })
64 .collect(),
65 }
66 }
67
68 pub fn execute(&mut self) -> Result<()> {
69 let mut ordered = self.func_info.functions.clone();
70 ordered.sort_by_key(|f| f.header.address);
71 let img_len = self.stream.data.len() as u32;
72 let mut pre_end = 0;
73 for e in ordered {
74 if e.header.flags == 0x11 {
76 eprintln!(
77 "Skipping inline function at {:#x}, {}",
78 e.header.address, e.name.0
79 );
80 continue;
81 }
82 let start = e.header.address;
83 if e.header.bytes == u32::MAX {
84 continue;
86 }
87 let end = start + e.header.bytes;
88 if end > img_len {
89 eprintln!(
90 "Warning: function end {:#x} exceeds image length {:#x}",
91 end, img_len
92 );
93 crate::COUNTER.inc_warning();
94 continue;
95 }
96 if pre_end != 0 && pre_end < start {
97 self.assembly.push(ECSExecutionImageCommandRecord {
98 code: CodeSystemReserved,
99 addr: pre_end,
100 size: start - pre_end,
101 new_addr: pre_end,
102 internal: true,
103 });
104 }
105 self.execute_range(start, end)?;
106 pre_end = end;
107 }
108 if pre_end != 0 && pre_end < img_len {
109 self.assembly.push(ECSExecutionImageCommandRecord {
110 code: CodeSystemReserved,
111 addr: pre_end,
112 size: img_len - pre_end,
113 new_addr: pre_end,
114 internal: true,
115 });
116 }
117 if self.func_info.functions.is_empty() {
118 self.execute_range(0, img_len)?;
122 }
123 Ok(())
124 }
125
126 fn line<S: AsRef<str> + ?Sized>(&mut self, line: &S) -> anyhow::Result<()> {
127 if let Some(writer) = &mut self.writer {
128 writeln!(writer, "{:08x} {}", self.addr, line.as_ref())?;
129 }
130 Ok(())
131 }
132
133 fn execute_range(&mut self, start: u32, end: u32) -> Result<()> {
134 self.stream.pos = start as usize;
135 let end = end as usize;
136 while self.stream.pos < end {
138 self.addr = self.stream.pos as u32;
139 let code = self.stream.read_u8()?;
140 self.code = CSInstructionCode::try_from(code).map_err(|_| {
141 anyhow::anyhow!(
142 "Invalid CSInstructionCode value: {} at {:08x}",
143 code,
144 self.addr
145 )
146 })?;
147 match self.code {
148 CsicNew => self.command_new()?,
149 CsicFree => self.command_free()?,
150 CsicLoad => self.command_load()?,
151 CsicStore => self.command_store()?,
152 CsicEnter => self.command_enter()?,
153 CsicLeave => self.command_leave()?,
154 CsicJump => self.command_jump()?,
155 CsicCJump => self.command_cjump()?,
156 CsicCall => self.command_call()?,
157 CsicReturn => self.command_return()?,
158 CsicElement => self.command_element()?,
159 CsicElementIndirect => self.command_element_indirect()?,
160 CsicOperate => self.command_operate()?,
161 CsicUniOperate => self.command_uni_operate()?,
162 CsicCompare => self.command_compare()?,
163 CsicExOperate => self.command_ex_operate()?,
164 CsicExUniOperate => self.command_ex_uni_operate()?,
165 CsicExCall => self.command_ex_call()?,
166 CsicExReturn => self.command_ex_return()?,
167 CsicCallMember => self.command_call_member()?,
168 CsicCallNativeMember => self.command_call_native_member()?,
169 CsicSwap => self.command_swap()?,
170 CsicCreateBufferVSize => self.command_create_buffer_vsize()?,
171 CsicPointerToObject => self.command_pointer_to_object()?,
172 CsicReferenceForPointer => self.command_reference_for_pointer()?,
173 CsicCallNativeFunction => self.command_call_native_function()?,
174 CodeLoadMem => self.shell_command_load_mem()?,
175 CodeLoadMemBaseImm32 => self.shell_command_load_mem_base_imm32()?,
176 CodeLoadMemBaseIndex => self.shell_command_load_mem_base_index()?,
177 CodeLoadMemBaseIndexImm32 => self.shell_command_load_mem_base_index_imm32()?,
178 CodeStoreMem => self.shell_command_store_mem()?,
179 CodeStoreMemBaseImm32 => self.shell_command_store_mem_base_imm32()?,
180 CodeStoreMemBaseIndex => self.shell_command_store_mem_base_index()?,
181 CodeStoreMemBaseIndexImm32 => self.shell_command_store_mem_base_index_imm32()?,
182 CodeLoadLocal => self.shell_command_load_local()?,
183 CodeLoadLocalIndexImm32 => self.shell_command_load_local_index_imm32()?,
184 CodeStoreLocal => self.shell_command_store_local()?,
185 CodeStoreLocalIndexImm32 => self.shell_command_store_local_index_imm32()?,
186 CodeMoveReg => self.shell_command_move_reg()?,
187 CodeCvtFloat2Int => self.shell_command_cvt_float_2_int()?,
188 CodeCvtInt2Float => self.shell_command_cvt_int_2_float()?,
189 CodeSrlImm8 => self.shell_command_srl_imm8()?,
190 CodeSraImm8 => self.shell_command_sra_imm8()?,
191 CodeSllImm8 => self.shell_command_sll_imm8()?,
192 CodeMaskMove => self.shell_command_mask_move()?,
193 CodeAddImm32 => self.shell_command_add_imm32()?,
194 CodeMulImm32 => self.shell_command_mul_imm32()?,
195 CodeAddSPImm32 => self.shell_command_add_sp_imm32()?,
196 CodeLoadImm64 => self.shell_command_load_imm64()?,
197 CodeNegInt => self.shell_command_neg_int()?,
198 CodeNotInt => self.shell_command_not_int()?,
199 CodeNegFloat => self.shell_command_neg_float()?,
200 CodeAddReg => self.shell_command_add_reg()?,
201 CodeSubReg => self.shell_command_sub_reg()?,
202 CodeMulReg => self.shell_command_mul_reg()?,
203 CodeDivReg => self.shell_command_div_reg()?,
204 CodeModReg => self.shell_command_mod_reg()?,
205 CodeAndReg => self.shell_command_and_reg()?,
206 CodeOrReg => self.shell_command_or_reg()?,
207 CodeXorReg => self.shell_command_xor_reg()?,
208 CodeSrlReg => self.shell_command_srl_reg()?,
209 CodeSraReg => self.shell_command_sra_reg()?,
210 CodeSllReg => self.shell_command_sll_reg()?,
211 CodeMoveSx32Reg => self.shell_command_move_sx32_reg()?,
212 CodeMoveSx16Reg => self.shell_command_move_sx16_reg()?,
213 CodeMoveSx8Reg => self.shell_command_move_sx8_reg()?,
214 CodeFAddReg => self.shell_command_f_add_reg()?,
215 CodeFSubReg => self.shell_command_f_sub_reg()?,
216 CodeFMulReg => self.shell_command_f_mul_reg()?,
217 CodeFDivReg => self.shell_command_f_div_reg()?,
218 CodeMul32Reg => self.shell_command_mul32_reg()?,
219 CodeIMul32Reg => self.shell_command_i_mul32_reg()?,
220 CodeDiv32Reg => self.shell_command_div32_reg()?,
221 CodeIDiv32Reg => self.shell_command_i_div32_reg()?,
222 CodeMod32Reg => self.shell_command_mod32_reg()?,
223 CodeIMod32Reg => self.shell_command_i_mod32_reg()?,
224 CodeCmpNeReg => self.shell_command_cmp_ne_reg()?,
225 CodeCmpEqReg => self.shell_command_cmp_eq_reg()?,
226 CodeCmpLtReg => self.shell_command_cmp_lt_reg()?,
227 CodeCmpLeReg => self.shell_command_cmp_le_reg()?,
228 CodeCmpGtReg => self.shell_command_cmp_gt_reg()?,
229 CodeCmpGeReg => self.shell_command_cmp_ge_reg()?,
230 CodeCmpCReg => self.shell_command_cmp_c_reg()?,
231 CodeCmpCZReg => self.shell_command_cmp_cz_reg()?,
232 CodeFCmpNeReg => self.shell_command_f_cmp_ne_reg()?,
233 CodeFCmpEqReg => self.shell_command_f_cmp_eq_reg()?,
234 CodeFCmpLtReg => self.shell_command_f_cmp_lt_reg()?,
235 CodeFCmpLeReg => self.shell_command_f_cmp_le_reg()?,
236 CodeFCmpGtReg => self.shell_command_f_cmp_gt_reg()?,
237 CodeFCmpGeReg => self.shell_command_f_cmp_ge_reg()?,
238 CodeJumpOffset32 => self.shell_command_jump_offset32()?,
239 CodeJumpReg => self.shell_command_jump_reg()?,
240 CodeCNJumpOffset32 => self.shell_command_cn_jump_offset32()?,
241 CodeCJumpOffset32 => self.shell_command_c_jump_offset32()?,
242 CodeCallImm32 => self.shell_command_call_imm32()?,
243 CodeCallReg => self.shell_command_call_reg()?,
244 CodeSysCallImm32 => self.shell_command_sys_call_imm32()?,
245 CodeSysCallReg => self.shell_command_sys_call_reg()?,
246 CodeReturn => self.shell_command_return()?,
247 CodePushReg => self.shell_command_push_reg()?,
248 CodePopReg => self.shell_command_pop_reg()?,
249 CodePushRegs => self.shell_command_push_regs()?,
250 CodePopRegs => self.shell_command_pop_regs()?,
251 CodeMemoryHint => self.shell_command_memory_hint()?,
252 CodeFloatExtension => self.shell_command_float_extension()?,
253 CodeSIMD64Extension2Op => self.shell_command_simd64_extension_2op()?,
254 CodeSIMD64Extension3Op => self.shell_command_simd64_extension_3op()?,
255 CodeSIMD128Extension2Op => self.shell_command_simd128_extension_2op()?,
256 CodeSIMD128Extension3Op => self.shell_command_simd128_extension_3op()?,
257 CodeEscape => self.shell_command_escape()?,
258 CodeNoOperation => self.shell_command_no_operation()?,
259 CodeSystemReserved => self.shell_command_system_reserved()?,
260 }
261 let size = self.stream.pos as u32 - self.addr;
262 self.assembly.push(ECSExecutionImageCommandRecord {
263 code: self.code,
264 addr: self.addr,
265 size,
266 new_addr: self.addr,
267 internal: false,
268 });
269 }
270 Ok(())
271 }
272
273 fn get_string_literal2(&mut self) -> Result<(Option<usize>, String)> {
274 let length = self.stream.read_u32()?;
275 if length != 0x80000000 {
276 self.stream.seek_relative(-4)?;
277 let s = WideString::unpack(&mut self.stream, false, Encoding::Utf16LE, &None)?.0;
278 Ok((None, s))
279 } else {
280 let index = self.stream.read_u32()? as usize;
281 match self.const_string.strings.get(index) {
282 Some(s) => Ok((Some(index), s.string.0.clone())),
283 None => Err(anyhow::anyhow!(
284 "Invalid string literal index: {} (max {})",
285 index,
286 self.const_string.strings.len()
287 )),
288 }
289 }
290 }
291
292 pub fn get_string_literal(&mut self) -> Result<String> {
293 let (_, s) = self.get_string_literal2()?;
294 Ok(s)
295 }
296
297 fn read_csct(&mut self) -> Result<CSCompareType> {
298 let value = self.stream.read_u8()?;
299 CSCompareType::try_from(value).map_err(|_| {
300 anyhow::anyhow!(
301 "Invalid CSCompareType value: {} at {:08x}",
302 value,
303 self.addr
304 )
305 })
306 }
307
308 pub fn read_csom(&mut self) -> Result<CSObjectMode> {
309 let value = self.stream.read_u8()?;
310 CSObjectMode::try_from(value).map_err(|_| {
311 anyhow::anyhow!("Invalid CSObjectMode value: {} at {:08x}", value, self.addr)
312 })
313 }
314
315 pub fn read_csot(&mut self) -> Result<CSOperatorType> {
316 let value = self.stream.read_u8()?;
317 CSOperatorType::try_from(value).map_err(|_| {
318 anyhow::anyhow!(
319 "Invalid CSOperatorType value: {} at {:08x}",
320 value,
321 self.addr
322 )
323 })
324 }
325
326 fn read_csuot(&mut self) -> Result<CSUnaryOperatorType> {
327 let value = self.stream.read_u8()?;
328 CSUnaryOperatorType::try_from(value).map_err(|_| {
329 anyhow::anyhow!(
330 "Invalid CSUnaryOperatorType value: {} at {:08x}",
331 value,
332 self.addr
333 )
334 })
335 }
336
337 pub fn read_csvt(&mut self) -> Result<CSVariableType> {
338 let value = self.stream.read_u8()?;
339 CSVariableType::try_from(value).map_err(|_| {
340 anyhow::anyhow!(
341 "Invalid CSVariableType value: {} at {:08x}",
342 value,
343 self.addr
344 )
345 })
346 }
347
348 fn read_csxot(&mut self) -> Result<CSExtraOperatorType> {
349 let value = self.stream.read_u8()?;
350 CSExtraOperatorType::try_from(value).map_err(|_| {
351 anyhow::anyhow!(
352 "Invalid CSExtraOperatorType value: {} at {:08x}",
353 value,
354 self.addr
355 )
356 })
357 }
358
359 fn read_csxuot(&mut self) -> Result<CSExtraUniOperatorType> {
360 let value = self.stream.read_u8()?;
361 CSExtraUniOperatorType::try_from(value).map_err(|_| {
362 anyhow::anyhow!(
363 "Invalid CSExtraUniOperatorType value: {} at {:08x}",
364 value,
365 self.addr
366 )
367 })
368 }
369
370 fn command_new(&mut self) -> Result<()> {
371 let csom = self.read_csom()?;
372 let csvt = self.read_csvt()?;
373 let class_name = if csvt == CsvtClassObject {
374 let class_index = self.stream.read_u32()?;
375 match self.class_info.names.get(class_index as usize) {
376 Some(c) => c.0.clone(),
377 None => {
378 return Err(anyhow::anyhow!(
379 "Invalid class index: {} (max {}) at {:08x}",
380 class_index,
381 self.class_info.names.len(),
382 self.addr
383 ));
384 }
385 }
386 } else if csvt == CsvtObject {
387 self.get_string_literal()?
388 } else {
389 String::new()
390 };
391 let var_name = self.get_string_literal()?;
392 let mode = match csom {
393 CsomStack => "stack",
394 CsomThis => "this",
395 _ => {
396 return Err(anyhow::anyhow!(
397 "Unexpected CSObjectMode in command_new: {:?} at {:08x}",
398 csom,
399 self.addr
400 ));
401 }
402 };
403 if class_name.is_empty() {
404 self.line(&format!("New {mode} \"{var_name}\""))?;
405 } else {
406 self.line(&format!("New {mode} \"{class_name}\" \"{var_name}\""))?;
407 }
408 Ok(())
409 }
410
411 fn command_free(&mut self) -> Result<()> {
412 self.line("Free")
413 }
414
415 fn command_load(&mut self) -> Result<()> {
416 let csom = self.read_csom()?;
417 let csvt = self.read_csvt()?;
418 if csom == CsomImmediate {
419 match csvt {
420 CsvtObject => {
421 let class_name = self.get_string_literal()?;
422 self.line(&format!("Load New \"{class_name}\""))?;
423 }
424 CsvtReference => {
425 self.line("Load New \"ECSReference\"")?;
426 }
427 CsvtArray => {
428 self.line("Load New \"ECSArray\"")?;
429 }
430 CsvtHash => {
431 self.line("Load New \"ECSHash\"")?;
432 }
433 CsvtInteger => {
434 let value = self.stream.read_u32()?;
435 self.line(&format!("Load Integer {value}"))?;
436 }
437 CsvtReal => {
438 let value = self.stream.read_f64()?;
439 self.line(&format!("Load Real {value}"))?;
440 }
441 CsvtString => {
442 let t = self.get_string_literal2()?;
443 let escaped = escape_string(&t.1);
444 if let Some(index) = t.0 {
445 self.line(&format!("Load Const String \"{escaped}\" ({index})"))?;
446 } else {
447 self.line(&format!("Load String \"{escaped}\""))?;
448 }
449 }
450 CsvtInteger64 => {
451 let value = self.stream.read_u64()?;
452 self.line(&format!("Load Integer64 {value}"))?;
453 }
454 CsvtPointer => {
455 let point = self.stream.read_u32()?;
456 self.line(&format!("Load Pointer {point}"))?;
457 }
458 CsvtClassObject => {
459 let class_index = self.stream.read_u32()?;
460 let class_name = match self.class_info.names.get(class_index as usize) {
461 Some(c) => c.0.clone(),
462 None => {
463 return Err(anyhow::anyhow!(
464 "Invalid class index: {} (max {}) at {:08x}",
465 class_index,
466 self.class_info.names.len(),
467 self.addr
468 ));
469 }
470 };
471 self.line(&format!("Load New \"{class_name}\""))?;
472 }
473 CsvtBoolean => {
474 let value = self.stream.read_u8()?;
475 self.line(&format!("Load Boolean {value}"))?;
476 }
477 _ => {
478 return Err(anyhow::anyhow!(
479 "Unexpected variable type in Load Immediate: {:?} at {:08x}",
480 csvt,
481 self.addr
482 ));
483 }
484 }
485 } else {
486 let mode = match csom {
487 CsomStack => "stack",
488 CsomThis => "this",
489 CsomGlobal => "global",
490 CsomData => "data",
491 CsomAuto => "auto",
492 _ => {
493 return Err(anyhow::anyhow!(
494 "Unexpected CSObjectMode in command_load: {:?} at {:08x}",
495 csom,
496 self.addr
497 ));
498 }
499 };
500 match csvt {
501 CsvtReference => {
502 self.line(&format!("Load {mode}"))?;
503 }
504 CsvtInteger => {
505 let index = self.stream.read_i32()?;
506 self.line(&format!("Load {mode} [{index}]"))?;
507 }
508 CsvtString => {
509 let name = self.get_string_literal()?;
510 self.line(&format!("Load {mode} [\"{name}\"]"))?;
511 }
512 _ => {
513 return Err(anyhow::anyhow!(
514 "Unexpected variable type in Load: {:?} at {:08x}",
515 csvt,
516 self.addr
517 ));
518 }
519 }
520 }
521 Ok(())
522 }
523
524 fn command_store(&mut self) -> Result<()> {
525 let csot = self.read_csot()?;
526 match csot {
527 CsotNop => {
528 self.line("Store")?;
529 }
530 CsotAdd => {
531 self.line("Store.Add")?;
532 }
533 CsotSub => {
534 self.line("Store.Sub")?;
535 }
536 CsotMul => {
537 self.line("Store.Mul")?;
538 }
539 CsotDiv => {
540 self.line("Store.Div")?;
541 }
542 CsotMod => {
543 self.line("Store.Mod")?;
544 }
545 CsotAnd => {
546 self.line("Store.And")?;
547 }
548 CsotOr => {
549 self.line("Store.Or")?;
550 }
551 CsotXor => {
552 self.line("Store.Xor")?;
553 }
554 CsotLogicalAnd => {
555 self.line("Store.LAnd")?;
556 }
557 CsotLogicalOr => {
558 self.line("Store.LOr")?;
559 }
560 _ => {
561 return Err(anyhow::anyhow!(
562 "Unexpected CSOperatorType in command_store: {:?} at {:08x}",
563 csot,
564 self.addr
565 ));
566 }
567 }
568 Ok(())
569 }
570
571 fn command_enter(&mut self) -> Result<()> {
572 let name = self.get_string_literal()?;
573 let num_args = self.stream.read_i32()?;
574 if num_args != -1 {
575 let mut sb = String::new();
576 sb.push('(');
577 for i in 0..num_args {
578 let csvt = self.read_csvt()?;
579 let class_name = if csvt == CsvtClassObject {
580 let class_index = self.stream.read_u32()?;
581 match self.class_info.names.get(class_index as usize) {
582 Some(c) => c.0.clone(),
583 None => {
584 return Err(anyhow::anyhow!(
585 "Invalid class index: {} (max {}) at {:08x}",
586 class_index,
587 self.class_info.names.len(),
588 self.addr
589 ));
590 }
591 }
592 } else if csvt == CsvtObject {
593 self.get_string_literal()?
594 } else {
595 String::new()
596 };
597 let var_name = self.get_string_literal()?;
598 if class_name.is_empty() {
599 sb.push_str(&var_name);
600 } else {
601 sb.push_str(&format!("{{{class_name}:{var_name}}}"));
602 }
603 if i < num_args - 1 {
604 sb.push_str(", ");
605 }
606 }
607 sb.push(')');
608 self.line(&format!("Enter \"{}\" {}", name, sb))?;
609 } else {
610 let flag = self.stream.read_u8()?;
611 if flag != 0 {
612 return Err(anyhow::anyhow!(
613 "Invalid flag for variable argument 'enter' instruction: {} at {:08x}",
614 flag,
615 self.addr
616 ));
617 }
618 let catch_addr = self.stream.read_i32()? as i64 + self.stream.pos as i64;
619 self.line(&format!("Enter \"{}\" Try-Catch {:08x}", name, catch_addr))?;
620 }
621 Ok(())
622 }
623
624 fn command_leave(&mut self) -> Result<()> {
625 self.line("Leave")
626 }
627
628 fn command_jump(&mut self) -> Result<()> {
629 let addr = self.stream.read_i32()? as i64 + self.stream.pos as i64;
630 self.line(&format!("Jump {addr:08x}"))
631 }
632
633 fn command_cjump(&mut self) -> Result<()> {
634 let cond = self.stream.read_u8()?;
635 let addr = self.stream.read_i32()? as i64 + self.stream.pos as i64;
636 self.line(&format!("CJump {cond} {addr:08x}"))
637 }
638
639 fn command_call(&mut self) -> Result<()> {
640 let csom = self.read_csom()?;
641 let num_args = self.stream.read_i32()?;
642 let func_name = self.get_string_literal()?;
643 let mode = match csom {
644 CsomImmediate if func_name == "@CATCH" => "",
645 CsomThis => "This",
646 CsomGlobal => "Global",
647 CsomAuto => "Auto",
648 _ => {
649 return Err(anyhow::anyhow!(
650 "Invalid CSObjectMode for 'call' instruction: {:?} {} at {:08x}",
651 csom,
652 func_name,
653 self.addr
654 ));
655 }
656 };
657 self.line(&format!("Call {mode} \"{func_name}\" <{num_args}>"))
658 }
659
660 fn command_return(&mut self) -> Result<()> {
661 let free_stack = self.stream.read_u8()?;
662 if free_stack == 1 {
663 self.line("Return Void")
664 } else {
665 self.line("Return")
666 }
667 }
668
669 fn command_element(&mut self) -> Result<()> {
670 let csvt = self.read_csvt()?;
671 match csvt {
672 CsvtInteger => {
673 let index = self.stream.read_i32()?;
674 self.line(&format!("Element [{index}]"))
675 }
676 CsvtString => {
677 let name = self.get_string_literal()?;
678 self.line(&format!("Element [\"{name}\"]"))
679 }
680 _ => Err(anyhow::anyhow!(
681 "Unexpected variable type in Element: {:?} at {:08x}",
682 csvt,
683 self.addr
684 )),
685 }
686 }
687
688 fn command_element_indirect(&mut self) -> Result<()> {
689 self.line("ElementIndirect")
690 }
691
692 fn command_operate(&mut self) -> Result<()> {
693 let csot = self.read_csot()?;
694 match csot {
695 CsotNop => self.line("Operate.Nop"),
696 CsotAdd => self.line("Operate.Add"),
697 CsotSub => self.line("Operate.Sub"),
698 CsotMul => self.line("Operate.Mul"),
699 CsotDiv => self.line("Operate.Div"),
700 CsotMod => self.line("Operate.Mod"),
701 CsotAnd => self.line("Operate.And"),
702 CsotOr => self.line("Operate.Or"),
703 CsotXor => self.line("Operate.Xor"),
704 CsotLogicalAnd => self.line("Operate.LAnd"),
705 CsotLogicalOr => self.line("Operate.LOr"),
706 CsotShiftRight => self.line("Operate.ShiftRight"),
707 CsotShiftLeft => self.line("Operate.ShiftLeft"),
708 }
709 }
710
711 fn command_uni_operate(&mut self) -> Result<()> {
712 let csuot = self.read_csuot()?;
713 match csuot {
714 CsuotPlus => self.line("UnaryOperate.Plus"),
715 CsuotNegate => self.line("UnaryOperate.Negate"),
716 CsuotBitnot => self.line("UnaryOperate.Bitnot"),
717 CsuotLogicalNot => self.line("UnaryOperate.LogicalNot"),
718 }
719 }
720
721 fn command_compare(&mut self) -> Result<()> {
722 let csct = self.read_csct()?;
723 match csct {
724 CsctEqual => self.line("Compare.Equal"),
725 CsctNotEqual => self.line("Compare.NotEqual"),
726 CsctLessThan => self.line("Compare.LessThan"),
727 CsctLessEqual => self.line("Compare.LessEqual"),
728 CsctGreaterThan => self.line("Compare.GreaterThan"),
729 CsctGreaterEqual => self.line("Compare.GreaterEqual"),
730 CsctNotEqualPointer => self.line("Compare.NotEqualPointer"),
731 CsctEqualPointer => self.line("Compare.EqualPointer"),
732 }
733 }
734
735 fn command_ex_operate(&mut self) -> Result<()> {
736 let csxot = self.read_csxot()?;
737 match csxot {
738 CsxotArrayDim => {
739 let dim = self.stream.read_i32()?;
740 let mut dims = Vec::with_capacity(dim as usize);
741 for _ in 0..dim {
742 let size = self.stream.read_i32()?;
743 dims.push(format!("{size}"));
744 }
745 let text = dims.join(", ");
746 self.line(&format!("ExOperate.ArrayDim {{ {text} }}"))
747 }
748 CsxotHashContainer => self.line("ExOperate.HashContainer"),
749 CsxotMoveReference => self.line("ExOperate.MoveReference"),
750 }
751 }
752
753 fn command_ex_uni_operate(&mut self) -> Result<()> {
754 let csxuot = self.read_csxuot()?;
755 match csxuot {
756 CsxuotDeselect => self.line("ExUnaryOperate.Deselect"),
757 CsxuotBoolean => self.line("ExUnaryOperate.Boolean"),
758 CsxuotSizeOf => self.line("ExUnaryOperate.SizeOf"),
759 CsxuotTypeOf => self.line("ExUnaryOperate.TypeOf"),
760 CsxuotStaticCast => {
761 let var_offset = self.stream.read_i32()?;
762 let var_bounds = self.stream.read_i32()?;
763 let func_offset = self.stream.read_i32()?;
764 self.line(&format!(
765 "ExUnaryOperate.StaticCast {var_offset}, {var_bounds}, {func_offset}"
766 ))
767 }
768 CsxuotDynamicCast => {
769 let cast_type = self.get_string_literal()?;
770 self.line(&format!("ExUnaryOperate.DynamicCast \"{cast_type}\""))
771 }
772 CsxuotDuplicate => self.line("ExUnaryOperate.Duplicate"),
773 CsxuotDelete => self.line("ExUnaryOperate.Delete"),
774 CsxuotDeleteArray => self.line("ExUnaryOperate.DeleteArray"),
775 CsxuotLoadAddress => self.line("ExUnaryOperate.LoadAddress"),
776 CsxuotRefAddress => self.line("ExUnaryOperate.RefAddress"),
777 }
778 }
779
780 fn command_ex_call(&mut self) -> Result<()> {
781 let arg_count = self.stream.read_i32()?;
782 let csom = self.read_csom()?;
783 let csvt = self.read_csvt()?;
784 match csom {
785 CsomImmediate => match csvt {
786 CsvtString => {
787 let func_name = self.get_string_literal()?;
788 self.line(&format!("ExCall \"{func_name}\" <{arg_count}>"))
789 }
790 CsvtInteger => {
791 let func_address = self.stream.read_u32()?;
792 if let Some(func) = self.func_map.get(&func_address) {
793 self.line(&format!("ExCall \"{}\" <{arg_count}>", func.name.0))
794 } else {
795 self.line(&format!("ExCall {func_address:08x} <{arg_count}>"))
796 }
797 }
798 _ => {
799 return Err(anyhow::anyhow!(
800 "Unexpected CSVariableType in ExCall: {:?} at {:08x}",
801 csvt,
802 self.addr
803 ));
804 }
805 },
806 _ => {
807 return Err(anyhow::anyhow!(
808 "Unexpected CSObjectMode in ExCall: {:?} at {:08x}",
809 csom,
810 self.addr
811 ));
812 }
813 }
814 }
815
816 fn command_ex_return(&mut self) -> Result<()> {
817 let free_stack = self.stream.read_u8()?;
818 if free_stack == 1 {
819 self.line("ExReturn Void")
820 } else {
821 self.line("ExReturn")
822 }
823 }
824
825 fn command_call_member(&mut self) -> Result<()> {
826 let arg_count = self.stream.read_i32()?;
827 let class_index = self.stream.read_u32()?;
828 let class = self
829 .class_info
830 .infos
831 .get(class_index as usize)
832 .ok_or_else(|| {
833 anyhow::anyhow!(
834 "Invalid class info index: {} (max {}) at {:08x}",
835 class_index,
836 self.class_info.infos.len(),
837 self.addr
838 )
839 })?;
840 let func_index = self.stream.read_u32()?;
841 let func = class.method_info.get(func_index as usize).ok_or_else(|| {
842 anyhow::anyhow!(
843 "Invalid method info index: {} (max {}) at {:08x}",
844 func_index,
845 class.method_info.len(),
846 self.addr
847 )
848 })?;
849 self.line(&format!(
850 "CallMember \"{}\" <{arg_count}>",
851 func.prototype_info.global_name.0
852 ))
853 }
854
855 fn command_call_native_member(&mut self) -> Result<()> {
856 let arg_count = self.stream.read_i32()?;
857 let class_index = self.stream.read_u32()?;
858 let class = self
859 .class_info
860 .infos
861 .get(class_index as usize)
862 .ok_or_else(|| {
863 anyhow::anyhow!(
864 "Invalid class info index: {} (max {}) at {:08x}",
865 class_index,
866 self.class_info.infos.len(),
867 self.addr
868 )
869 })?;
870 let func_index = self.stream.read_u32()?;
871 let func = class.method_info.get(func_index as usize).ok_or_else(|| {
872 anyhow::anyhow!(
873 "Invalid method info index: {} (max {}) at {:08x}",
874 func_index,
875 class.method_info.len(),
876 self.addr
877 )
878 })?;
879 self.line(&format!(
880 "CallNativeMember \"{}\" <{arg_count}>",
881 func.prototype_info.global_name.0
882 ))
883 }
884
885 fn command_swap(&mut self) -> Result<()> {
886 let _byt_sub_code = self.stream.read_u8()?;
887 let index1 = self.stream.read_i32()?;
888 let index2 = self.stream.read_i32()?;
889 self.line(&format!("Swap #{index1} #{index2}"))
890 }
891
892 fn command_create_buffer_vsize(&mut self) -> Result<()> {
893 self.line("CreateBufferVSize")
894 }
895
896 fn command_pointer_to_object(&mut self) -> Result<()> {
897 let var_type = self.stream.read_i32()?;
898 self.line(&format!("PointerToObject {var_type}"))
899 }
900
901 fn command_reference_for_pointer(&mut self) -> Result<()> {
902 let csvt = self.read_csvt()?;
903 self.line(&format!("ReferenceForPointer {:?}", csvt))
904 }
905
906 fn command_call_native_function(&mut self) -> Result<()> {
907 let arg_count = self.stream.read_i32()?;
908 let func_index = self.stream.read_u32()?;
909 let native_func = self
910 .import_native_func
911 .native_func
912 .names
913 .get(func_index as usize)
914 .ok_or_else(|| {
915 anyhow::anyhow!(
916 "Invalid native function index: {} (max {}) at {:08x}",
917 func_index,
918 self.import_native_func.native_func.names.len(),
919 self.addr
920 )
921 })?;
922 self.line(&format!(
923 "CallNativeFunction \"{}\" <{arg_count}>",
924 native_func.0
925 ))
926 }
927
928 fn shell_command_load_mem(&mut self) -> Result<()> {
929 let base = self.stream.read_u8()?;
930 let reg = self.stream.read_u8()?;
931 self.line(&format!("LoadMem {base}, %{reg}"))
932 }
933
934 fn shell_command_load_mem_base_imm32(&mut self) -> Result<()> {
935 let base = self.stream.read_u8()?;
936 let reg = self.stream.read_u8()?;
937 let mem = self.stream.read_i32()?;
938 self.line(&format!("LoadMemBaseImm32 %{base}, %{reg}, {mem}"))
939 }
940
941 fn shell_command_load_mem_base_index(&mut self) -> Result<()> {
942 let data_type = self.stream.read_u8()?;
943 let index = self.stream.read_u8()?;
944 let reg = self.stream.read_u8()?;
945 self.line(&format!("LoadMemBaseIndex {data_type}, %{reg}, {index}"))
946 }
947
948 fn shell_command_load_mem_base_index_imm32(&mut self) -> Result<()> {
949 let data_type = self.stream.read_u8()?;
950 let index = self.stream.read_u8()?;
951 let reg = self.stream.read_u8()?;
952 let imm32 = self.stream.read_i32()?;
953 self.line(&format!(
954 "LoadMemBaseIndexImm32 {data_type}, %{reg}, {index}, {imm32}"
955 ))
956 }
957
958 fn shell_command_store_mem(&mut self) -> Result<()> {
959 let data_type = self.stream.read_u8()?;
960 let reg = self.stream.read_u8()?;
961 self.line(&format!("StoreMem {data_type}, %{reg}"))
962 }
963
964 fn shell_command_store_mem_base_imm32(&mut self) -> Result<()> {
965 let base = self.stream.read_u8()?;
966 let reg = self.stream.read_u8()?;
967 let mem = self.stream.read_i32()?;
968 self.line(&format!("StoreMemBaseImm32 %{base}, %{reg}, {mem}"))
969 }
970
971 fn shell_command_store_mem_base_index(&mut self) -> Result<()> {
972 let data_type = self.stream.read_u8()?;
973 let index = self.stream.read_u8()?;
974 let reg = self.stream.read_u8()?;
975 self.line(&format!("StoreMemBaseIndex {data_type}, %{reg}, {index}"))
976 }
977
978 fn shell_command_store_mem_base_index_imm32(&mut self) -> Result<()> {
979 let data_type = self.stream.read_u8()?;
980 let index = self.stream.read_u8()?;
981 let reg = self.stream.read_u8()?;
982 let imm32 = self.stream.read_i32()?;
983 self.line(&format!(
984 "StoreMemBaseIndexImm32 {data_type}, %{reg}, {index}, {imm32}"
985 ))
986 }
987
988 fn shell_command_load_local(&mut self) -> Result<()> {
989 let data_type = self.stream.read_u8()?;
990 let reg = self.stream.read_u8()?;
991 let mem = self.stream.read_i32()?;
992 self.line(&format!("LoadLocal {data_type}, %{reg}, {mem}"))
993 }
994
995 fn shell_command_load_local_index_imm32(&mut self) -> Result<()> {
996 let data_type = self.stream.read_u8()?;
997 let index = self.stream.read_u8()?;
998 let reg = self.stream.read_u8()?;
999 let imm32 = self.stream.read_i32()?;
1000 self.line(&format!(
1001 "LoadLocalIndexImm32 {data_type}, %{reg}, {index}, {imm32}"
1002 ))
1003 }
1004
1005 fn shell_command_store_local(&mut self) -> Result<()> {
1006 let data_type = self.stream.read_u8()?;
1007 let reg = self.stream.read_u8()?;
1008 let mem = self.stream.read_i32()?;
1009 self.line(&format!("StoreLocal {data_type}, %{reg}, {mem}"))
1010 }
1011
1012 fn shell_command_store_local_index_imm32(&mut self) -> Result<()> {
1013 let data_type = self.stream.read_u8()?;
1014 let index = self.stream.read_u8()?;
1015 let reg = self.stream.read_u8()?;
1016 let imm32 = self.stream.read_i32()?;
1017 self.line(&format!(
1018 "StoreLocalIndexImm32 {data_type}, %{reg}, {index}, {imm32}"
1019 ))
1020 }
1021
1022 fn shell_command_move_reg(&mut self) -> Result<()> {
1023 let dst = self.stream.read_u8()?;
1024 let src = self.stream.read_u8()?;
1025 self.line(&format!("MoveReg %{dst}, %{src}"))
1026 }
1027
1028 fn shell_command_cvt_float_2_int(&mut self) -> Result<()> {
1029 let dst = self.stream.read_u8()?;
1030 let src = self.stream.read_u8()?;
1031 self.line(&format!("CvtFloat2Int %{dst}, %{src}"))
1032 }
1033
1034 fn shell_command_cvt_int_2_float(&mut self) -> Result<()> {
1035 let dst = self.stream.read_u8()?;
1036 let src = self.stream.read_u8()?;
1037 self.line(&format!("CvtInt2Float %{dst}, %{src}"))
1038 }
1039
1040 fn shell_command_srl_imm8(&mut self) -> Result<()> {
1041 let dst = self.stream.read_u8()?;
1042 let src = self.stream.read_u8()?;
1043 let imm = self.stream.read_u8()?;
1044 self.line(&format!("SrlImm8 %{dst}, %{src}, {imm}"))
1045 }
1046
1047 fn shell_command_sra_imm8(&mut self) -> Result<()> {
1048 let dst = self.stream.read_u8()?;
1049 let src = self.stream.read_u8()?;
1050 let imm = self.stream.read_u8()?;
1051 self.line(&format!("SraImm8 %{dst}, %{src}, {imm}"))
1052 }
1053
1054 fn shell_command_sll_imm8(&mut self) -> Result<()> {
1055 let dst = self.stream.read_u8()?;
1056 let src = self.stream.read_u8()?;
1057 let imm = self.stream.read_u8()?;
1058 self.line(&format!("SllImm8 %{dst}, %{src}, {imm}"))
1059 }
1060
1061 fn shell_command_mask_move(&mut self) -> Result<()> {
1062 let dst = self.stream.read_u8()?;
1063 let src1 = self.stream.read_u8()?;
1064 let src2 = self.stream.read_u8()?;
1065 self.line(&format!("MaskMove %{dst}, %{src1}, %{src2}"))
1066 }
1067
1068 fn shell_command_add_imm32(&mut self) -> Result<()> {
1069 let dst = self.stream.read_u8()?;
1070 let src = self.stream.read_u8()?;
1071 let imm = self.stream.read_i32()?;
1072 self.line(&format!("AddImm32 %{dst}, %{src}, {imm}"))
1073 }
1074
1075 fn shell_command_mul_imm32(&mut self) -> Result<()> {
1076 let dst = self.stream.read_u8()?;
1077 let src = self.stream.read_u8()?;
1078 let imm = self.stream.read_i32()?;
1079 self.line(&format!("MulImm32 %{dst}, %{src}, {imm}"))
1080 }
1081
1082 fn shell_command_add_sp_imm32(&mut self) -> Result<()> {
1083 let val = self.stream.read_i32()?;
1084 self.line(&format!("AddSPImm32 {val}"))
1085 }
1086
1087 fn shell_command_load_imm64(&mut self) -> Result<()> {
1088 let reg = self.stream.read_u8()?;
1089 let imm = self.stream.read_i64()?;
1090 self.line(&format!("LoadImm64 %{reg}, {imm}"))
1091 }
1092
1093 fn shell_command_neg_int(&mut self) -> Result<()> {
1094 let dst = self.stream.read_u8()?;
1095 self.line(&format!("NegInt %{dst}"))
1096 }
1097
1098 fn shell_command_not_int(&mut self) -> Result<()> {
1099 let dst = self.stream.read_u8()?;
1100 self.line(&format!("NotInt %{dst}"))
1101 }
1102
1103 fn shell_command_neg_float(&mut self) -> Result<()> {
1104 let dst = self.stream.read_u8()?;
1105 self.line(&format!("NegFloat %{dst}"))
1106 }
1107
1108 fn shell_command_add_reg(&mut self) -> Result<()> {
1109 let dst = self.stream.read_u8()?;
1110 let src = self.stream.read_u8()?;
1111 self.line(&format!("AddReg %{dst}, %{src}"))
1112 }
1113
1114 fn shell_command_sub_reg(&mut self) -> Result<()> {
1115 let dst = self.stream.read_u8()?;
1116 let src = self.stream.read_u8()?;
1117 self.line(&format!("SubReg %{dst}, %{src}"))
1118 }
1119
1120 fn shell_command_mul_reg(&mut self) -> Result<()> {
1121 let dst = self.stream.read_u8()?;
1122 let src = self.stream.read_u8()?;
1123 self.line(&format!("MulReg %{dst}, %{src}"))
1124 }
1125
1126 fn shell_command_div_reg(&mut self) -> Result<()> {
1127 let dst = self.stream.read_u8()?;
1128 let src = self.stream.read_u8()?;
1129 self.line(&format!("DivReg %{dst}, %{src}"))
1130 }
1131
1132 fn shell_command_mod_reg(&mut self) -> Result<()> {
1133 let dst = self.stream.read_u8()?;
1134 let src = self.stream.read_u8()?;
1135 self.line(&format!("ModReg %{dst}, %{src}"))
1136 }
1137
1138 fn shell_command_and_reg(&mut self) -> Result<()> {
1139 let dst = self.stream.read_u8()?;
1140 let src = self.stream.read_u8()?;
1141 self.line(&format!("AndReg %{dst}, %{src}"))
1142 }
1143
1144 fn shell_command_or_reg(&mut self) -> Result<()> {
1145 let dst = self.stream.read_u8()?;
1146 let src = self.stream.read_u8()?;
1147 self.line(&format!("OrReg %{dst}, %{src}"))
1148 }
1149
1150 fn shell_command_xor_reg(&mut self) -> Result<()> {
1151 let dst = self.stream.read_u8()?;
1152 let src = self.stream.read_u8()?;
1153 self.line(&format!("XorReg %{dst}, %{src}"))
1154 }
1155
1156 fn shell_command_srl_reg(&mut self) -> Result<()> {
1157 let dst = self.stream.read_u8()?;
1158 let src = self.stream.read_u8()?;
1159 self.line(&format!("SrlReg %{dst}, %{src}"))
1160 }
1161
1162 fn shell_command_sra_reg(&mut self) -> Result<()> {
1163 let dst = self.stream.read_u8()?;
1164 let src = self.stream.read_u8()?;
1165 self.line(&format!("SraReg %{dst}, %{src}"))
1166 }
1167
1168 fn shell_command_sll_reg(&mut self) -> Result<()> {
1169 let dst = self.stream.read_u8()?;
1170 let src = self.stream.read_u8()?;
1171 self.line(&format!("SllReg %{dst}, %{src}"))
1172 }
1173
1174 fn shell_command_move_sx32_reg(&mut self) -> Result<()> {
1175 let dst = self.stream.read_u8()?;
1176 let src = self.stream.read_u8()?;
1177 self.line(&format!("MoveSx32Reg %{dst}, %{src}"))
1178 }
1179
1180 fn shell_command_move_sx16_reg(&mut self) -> Result<()> {
1181 let dst = self.stream.read_u8()?;
1182 let src = self.stream.read_u8()?;
1183 self.line(&format!("MoveSx16Reg %{dst}, %{src}"))
1184 }
1185
1186 fn shell_command_move_sx8_reg(&mut self) -> Result<()> {
1187 let dst = self.stream.read_u8()?;
1188 let src = self.stream.read_u8()?;
1189 self.line(&format!("MoveSx8Reg %{dst}, %{src}"))
1190 }
1191
1192 fn shell_command_f_add_reg(&mut self) -> Result<()> {
1193 let dst = self.stream.read_u8()?;
1194 let src = self.stream.read_u8()?;
1195 self.line(&format!("FAddReg %{dst}, %{src}"))
1196 }
1197
1198 fn shell_command_f_sub_reg(&mut self) -> Result<()> {
1199 let dst = self.stream.read_u8()?;
1200 let src = self.stream.read_u8()?;
1201 self.line(&format!("FSubReg %{dst}, %{src}"))
1202 }
1203
1204 fn shell_command_f_mul_reg(&mut self) -> Result<()> {
1205 let dst = self.stream.read_u8()?;
1206 let src = self.stream.read_u8()?;
1207 self.line(&format!("FMulReg %{dst}, %{src}"))
1208 }
1209
1210 fn shell_command_f_div_reg(&mut self) -> Result<()> {
1211 let dst = self.stream.read_u8()?;
1212 let src = self.stream.read_u8()?;
1213 self.line(&format!("FDivReg %{dst}, %{src}"))
1214 }
1215
1216 fn shell_command_mul32_reg(&mut self) -> Result<()> {
1217 let dst = self.stream.read_u8()?;
1218 let src = self.stream.read_u8()?;
1219 self.line(&format!("Mul32Reg %{dst}, %{src}"))
1220 }
1221
1222 fn shell_command_i_mul32_reg(&mut self) -> Result<()> {
1223 let dst = self.stream.read_u8()?;
1224 let src = self.stream.read_u8()?;
1225 self.line(&format!("IMul32Reg %{dst}, %{src}"))
1226 }
1227
1228 fn shell_command_div32_reg(&mut self) -> Result<()> {
1229 let dst = self.stream.read_u8()?;
1230 let src = self.stream.read_u8()?;
1231 self.line(&format!("Div32Reg %{dst}, %{src}"))
1232 }
1233
1234 fn shell_command_i_div32_reg(&mut self) -> Result<()> {
1235 let dst = self.stream.read_u8()?;
1236 let src = self.stream.read_u8()?;
1237 self.line(&format!("IDiv32Reg %{dst}, %{src}"))
1238 }
1239
1240 fn shell_command_mod32_reg(&mut self) -> Result<()> {
1241 let dst = self.stream.read_u8()?;
1242 let src = self.stream.read_u8()?;
1243 self.line(&format!("Mod32Reg %{dst}, %{src}"))
1244 }
1245
1246 fn shell_command_i_mod32_reg(&mut self) -> Result<()> {
1247 let dst = self.stream.read_u8()?;
1248 let src = self.stream.read_u8()?;
1249 self.line(&format!("IMod32Reg %{dst}, %{src}"))
1250 }
1251
1252 fn shell_command_cmp_ne_reg(&mut self) -> Result<()> {
1253 let dst = self.stream.read_u8()?;
1254 let src = self.stream.read_u8()?;
1255 self.line(&format!("CmpNeReg %{dst}, %{src}"))
1256 }
1257
1258 fn shell_command_cmp_eq_reg(&mut self) -> Result<()> {
1259 let dst = self.stream.read_u8()?;
1260 let src = self.stream.read_u8()?;
1261 self.line(&format!("CmpEqReg %{dst}, %{src}"))
1262 }
1263
1264 fn shell_command_cmp_lt_reg(&mut self) -> Result<()> {
1265 let dst = self.stream.read_u8()?;
1266 let src = self.stream.read_u8()?;
1267 self.line(&format!("CmpLtReg %{dst}, %{src}"))
1268 }
1269
1270 fn shell_command_cmp_le_reg(&mut self) -> Result<()> {
1271 let dst = self.stream.read_u8()?;
1272 let src = self.stream.read_u8()?;
1273 self.line(&format!("CmpLeReg %{dst}, %{src}"))
1274 }
1275
1276 fn shell_command_cmp_gt_reg(&mut self) -> Result<()> {
1277 let dst = self.stream.read_u8()?;
1278 let src = self.stream.read_u8()?;
1279 self.line(&format!("CmpGtReg %{dst}, %{src}"))
1280 }
1281
1282 fn shell_command_cmp_ge_reg(&mut self) -> Result<()> {
1283 let dst = self.stream.read_u8()?;
1284 let src = self.stream.read_u8()?;
1285 self.line(&format!("CmpGeReg %{dst}, %{src}"))
1286 }
1287
1288 fn shell_command_cmp_c_reg(&mut self) -> Result<()> {
1289 let dst = self.stream.read_u8()?;
1290 let src = self.stream.read_u8()?;
1291 self.line(&format!("CmpCReg %{dst}, %{src}"))
1292 }
1293
1294 fn shell_command_cmp_cz_reg(&mut self) -> Result<()> {
1295 let dst = self.stream.read_u8()?;
1296 let src = self.stream.read_u8()?;
1297 self.line(&format!("CmpCZReg %{dst}, %{src}"))
1298 }
1299
1300 fn shell_command_f_cmp_ne_reg(&mut self) -> Result<()> {
1301 let dst = self.stream.read_u8()?;
1302 let src = self.stream.read_u8()?;
1303 self.line(&format!("FCmpNeReg %{dst}, %{src}"))
1304 }
1305
1306 fn shell_command_f_cmp_eq_reg(&mut self) -> Result<()> {
1307 let dst = self.stream.read_u8()?;
1308 let src = self.stream.read_u8()?;
1309 self.line(&format!("FCmpEqReg %{dst}, %{src}"))
1310 }
1311
1312 fn shell_command_f_cmp_lt_reg(&mut self) -> Result<()> {
1313 let dst = self.stream.read_u8()?;
1314 let src = self.stream.read_u8()?;
1315 self.line(&format!("FCmpLtReg %{dst}, %{src}"))
1316 }
1317
1318 fn shell_command_f_cmp_le_reg(&mut self) -> Result<()> {
1319 let dst = self.stream.read_u8()?;
1320 let src = self.stream.read_u8()?;
1321 self.line(&format!("FCmpLeReg %{dst}, %{src}"))
1322 }
1323
1324 fn shell_command_f_cmp_gt_reg(&mut self) -> Result<()> {
1325 let dst = self.stream.read_u8()?;
1326 let src = self.stream.read_u8()?;
1327 self.line(&format!("FCmpGtReg %{dst}, %{src}"))
1328 }
1329
1330 fn shell_command_f_cmp_ge_reg(&mut self) -> Result<()> {
1331 let dst = self.stream.read_u8()?;
1332 let src = self.stream.read_u8()?;
1333 self.line(&format!("FCmpGeReg %{dst}, %{src}"))
1334 }
1335
1336 fn shell_command_jump_offset32(&mut self) -> Result<()> {
1337 let offset = self.stream.read_i32()? as i64;
1338 let dest = self.addr as i64 + offset + 5;
1339 self.line(&format!("JumpOffset32 {dest:08x}"))
1340 }
1341
1342 fn shell_command_jump_reg(&mut self) -> Result<()> {
1343 let reg = self.stream.read_u8()?;
1344 self.line(&format!("JumpReg %{reg}"))
1345 }
1346
1347 fn shell_command_cn_jump_offset32(&mut self) -> Result<()> {
1348 let reg = self.stream.read_u8()?;
1349 let offset = self.stream.read_i32()? as i64;
1350 let dest = self.addr as i64 + offset + 6;
1351 self.line(&format!("CNJumpOffset32 %{reg}, {dest:08x}"))
1352 }
1353
1354 fn shell_command_c_jump_offset32(&mut self) -> Result<()> {
1355 let reg = self.stream.read_u8()?;
1356 let offset = self.stream.read_i32()? as i64;
1357 let dest = self.addr as i64 + offset + 6;
1358 self.line(&format!("CJumpOffset32 %{reg}, {dest:08x}"))
1359 }
1360
1361 fn shell_command_call_imm32(&mut self) -> Result<()> {
1362 let dst = self.stream.read_u32()?;
1363 if let Some(func) = self.func_map.get(&dst) {
1364 self.line(&format!("CallImm32 \"{}\"", func.name.0))
1365 } else {
1366 self.line(&format!("CallImm32 {dst:08x}"))
1367 }
1368 }
1369
1370 fn shell_command_call_reg(&mut self) -> Result<()> {
1371 let reg = self.stream.read_u8()?;
1372 self.line(&format!("CallReg %{reg}"))
1373 }
1374
1375 fn shell_command_sys_call_imm32(&mut self) -> Result<()> {
1376 let num = self.stream.read_i32()?;
1377 self.line(&format!("SysCallImm32 {num:02x}"))
1378 }
1379
1380 fn shell_command_sys_call_reg(&mut self) -> Result<()> {
1381 let reg = self.stream.read_u8()?;
1382 self.line(&format!("SysCallReg %{reg}"))
1383 }
1384
1385 fn shell_command_return(&mut self) -> Result<()> {
1386 self.line("Shell Return")
1387 }
1388
1389 fn shell_command_push_reg(&mut self) -> Result<()> {
1390 let reg = self.stream.read_u8()?;
1391 self.line(&format!("PushReg %{reg}"))
1392 }
1393
1394 fn shell_command_pop_reg(&mut self) -> Result<()> {
1395 let reg = self.stream.read_u8()?;
1396 self.line(&format!("PopReg %{reg}"))
1397 }
1398
1399 fn shell_command_push_regs(&mut self) -> Result<()> {
1400 let reg_first = self.stream.read_u8()?;
1401 let count = self.stream.read_u8()?;
1402 self.line(&format!("PushRegs %{reg_first}, {count}"))
1403 }
1404
1405 fn shell_command_pop_regs(&mut self) -> Result<()> {
1406 let reg_first = self.stream.read_u8()?;
1407 let count = self.stream.read_u8()?;
1408 self.line(&format!("PopRegs %{reg_first}, {count}"))
1409 }
1410
1411 fn shell_command_memory_hint(&mut self) -> Result<()> {
1412 let hint = self.stream.read_u8()?;
1413 let reg = self.stream.read_u8()?;
1414 self.line(&format!("MemoryHint {hint}, %{reg}"))
1415 }
1416
1417 fn shell_command_float_extension(&mut self) -> Result<()> {
1418 let ext = self.stream.read_u8()?;
1419 let reg1 = self.stream.read_u8()?;
1420 let reg2 = self.stream.read_u8()?;
1421 self.line(&format!("FloatExtension {ext}, %{reg1}, %{reg2}"))
1422 }
1423
1424 fn shell_command_simd64_extension_2op(&mut self) -> Result<()> {
1425 let ext = self.stream.read_u8()?;
1426 let reg1 = self.stream.read_u8()?;
1427 let reg2 = self.stream.read_u8()?;
1428 self.line(&format!("SIMD64Extension2Op {ext}, %{reg1}, %{reg2}"))
1429 }
1430
1431 fn shell_command_simd64_extension_3op(&mut self) -> Result<()> {
1432 let ext = self.stream.read_u8()?;
1433 let reg1 = self.stream.read_u8()?;
1434 let reg2 = self.stream.read_u8()?;
1435 let imm = self.stream.read_u8()?;
1436 self.line(&format!(
1437 "SIMD64Extension3Op {ext}, %{reg1}, %{reg2}, {imm}"
1438 ))
1439 }
1440
1441 fn shell_command_simd128_extension_2op(&mut self) -> Result<()> {
1442 let ext = self.stream.read_u8()?;
1443 let dst = self.stream.read_u8()?;
1444 let src = self.stream.read_u8()?;
1445 self.line(&format!("SIMD128Extension2Op {ext}, %{dst}, %{src}"))
1446 }
1447
1448 fn shell_command_simd128_extension_3op(&mut self) -> Result<()> {
1449 let ext = self.stream.read_u8()?;
1450 let dst = self.stream.read_u8()?;
1451 let src = self.stream.read_u8()?;
1452 let imm = self.stream.read_u8()?;
1453 if ext == 0 {
1454 self.line(&format!(
1455 "SIMD128Extension3Op {ext}, %{dst}, %{src}, %{imm}"
1456 ))
1457 } else {
1458 self.line(&format!("SIMD128Extension3Op {ext}, %{dst}, %{src}, {imm}"))
1459 }
1460 }
1461
1462 fn shell_command_escape(&mut self) -> Result<()> {
1463 self.line("Escape")
1464 }
1465
1466 fn shell_command_no_operation(&mut self) -> Result<()> {
1467 self.line("NoOperation")
1468 }
1469
1470 fn shell_command_system_reserved(&mut self) -> Result<()> {
1471 self.line("SystemReserved")
1472 }
1473}