iced_x86/formatter/
fmt_utils_all.rs

1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4use crate::{Code, CodeSize, Instruction, Register};
5
6#[must_use]
7pub(super) const fn is_rep_repe_repne_instruction(code: Code) -> bool {
8	matches!(
9		code,
10		Code::Insb_m8_DX
11			| Code::Insw_m16_DX
12			| Code::Insd_m32_DX
13			| Code::Outsb_DX_m8
14			| Code::Outsw_DX_m16
15			| Code::Outsd_DX_m32
16			| Code::Movsb_m8_m8
17			| Code::Movsw_m16_m16
18			| Code::Movsd_m32_m32
19			| Code::Movsq_m64_m64
20			| Code::Cmpsb_m8_m8
21			| Code::Cmpsw_m16_m16
22			| Code::Cmpsd_m32_m32
23			| Code::Cmpsq_m64_m64
24			| Code::Stosb_m8_AL
25			| Code::Stosw_m16_AX
26			| Code::Stosd_m32_EAX
27			| Code::Stosq_m64_RAX
28			| Code::Lodsb_AL_m8
29			| Code::Lodsw_AX_m16
30			| Code::Lodsd_EAX_m32
31			| Code::Lodsq_RAX_m64
32			| Code::Scasb_AL_m8
33			| Code::Scasw_AX_m16
34			| Code::Scasd_EAX_m32
35			| Code::Scasq_RAX_m64
36			| Code::Montmul_16
37			| Code::Montmul_32
38			| Code::Montmul_64
39			| Code::Xsha1_16
40			| Code::Xsha1_32
41			| Code::Xsha1_64
42			| Code::Xsha256_16
43			| Code::Xsha256_32
44			| Code::Xsha256_64
45			| Code::Xstore_16
46			| Code::Xstore_32
47			| Code::Xstore_64
48			| Code::Xcryptecb_16
49			| Code::Xcryptecb_32
50			| Code::Xcryptecb_64
51			| Code::Xcryptcbc_16
52			| Code::Xcryptcbc_32
53			| Code::Xcryptcbc_64
54			| Code::Xcryptctr_16
55			| Code::Xcryptctr_32
56			| Code::Xcryptctr_64
57			| Code::Xcryptcfb_16
58			| Code::Xcryptcfb_32
59			| Code::Xcryptcfb_64
60			| Code::Xcryptofb_16
61			| Code::Xcryptofb_32
62			| Code::Xcryptofb_64
63			| Code::Ccs_hash_16
64			| Code::Ccs_hash_32
65			| Code::Ccs_hash_64
66			| Code::Ccs_encrypt_16
67			| Code::Ccs_encrypt_32
68			| Code::Ccs_encrypt_64
69			| Code::Via_undoc_F30FA6F0_16
70			| Code::Via_undoc_F30FA6F0_32
71			| Code::Via_undoc_F30FA6F0_64
72			| Code::Via_undoc_F30FA6F8_16
73			| Code::Via_undoc_F30FA6F8_32
74			| Code::Via_undoc_F30FA6F8_64
75			| Code::Xsha512_16
76			| Code::Xsha512_32
77			| Code::Xsha512_64
78			| Code::Xstore_alt_16
79			| Code::Xstore_alt_32
80			| Code::Xstore_alt_64
81			| Code::Xsha512_alt_16
82			| Code::Xsha512_alt_32
83			| Code::Xsha512_alt_64
84	)
85}
86
87#[must_use]
88pub(super) const fn show_rep_or_repe_prefix_bool(code: Code, show_useless_prefixes: bool) -> bool {
89	if show_useless_prefixes || is_rep_repe_repne_instruction(code) {
90		true
91	} else {
92		// We allow 'rep ret' too since some old code use it to work around an old AMD bug
93		match code {
94			Code::Retnw | Code::Retnd | Code::Retnq => true,
95			_ => show_useless_prefixes,
96		}
97	}
98}
99
100#[must_use]
101pub(super) const fn show_repne_prefix_bool(code: Code, show_useless_prefixes: bool) -> bool {
102	// If it's a 'rep/repne' instruction, always show the prefix
103	if show_useless_prefixes || is_rep_repe_repne_instruction(code) {
104		true
105	} else {
106		show_useless_prefixes
107	}
108}
109
110#[must_use]
111pub(super) fn is_code64(code_size: CodeSize) -> bool {
112	code_size == CodeSize::Code64 || code_size == CodeSize::Unknown
113}
114
115#[must_use]
116pub(super) fn get_default_segment_register(instruction: &Instruction) -> Register {
117	let base_reg = instruction.memory_base();
118	if base_reg == Register::BP || base_reg == Register::EBP || base_reg == Register::ESP || base_reg == Register::RBP || base_reg == Register::RSP {
119		Register::SS
120	} else {
121		Register::DS
122	}
123}
124
125#[must_use]
126pub(super) fn show_segment_prefix_bool(mut default_seg_reg: Register, instruction: &Instruction, show_useless_prefixes: bool) -> bool {
127	if instruction.code().ignores_segment() {
128		return show_useless_prefixes;
129	}
130	let prefix_seg = instruction.segment_prefix();
131	debug_assert_ne!(prefix_seg, Register::None);
132	if is_code64(instruction.code_size()) {
133		// ES,CS,SS,DS are ignored
134		if prefix_seg == Register::FS || prefix_seg == Register::GS {
135			true
136		} else {
137			show_useless_prefixes
138		}
139	} else {
140		if default_seg_reg == Register::None {
141			default_seg_reg = get_default_segment_register(instruction);
142		}
143		if prefix_seg != default_seg_reg {
144			true
145		} else {
146			show_useless_prefixes
147		}
148	}
149}
150
151#[must_use]
152pub(super) const fn is_repe_or_repne_instruction(code: Code) -> bool {
153	matches!(
154		code,
155		Code::Cmpsb_m8_m8
156			| Code::Cmpsw_m16_m16
157			| Code::Cmpsd_m32_m32
158			| Code::Cmpsq_m64_m64
159			| Code::Scasb_AL_m8
160			| Code::Scasw_AX_m16
161			| Code::Scasd_EAX_m32
162			| Code::Scasq_RAX_m64
163	)
164}
165
166#[must_use]
167#[inline]
168pub(super) const fn is_notrack_prefix_branch(code: Code) -> bool {
169	const _: () = assert!(Code::Jmp_rm16 as u32 + 1 == Code::Jmp_rm32 as u32);
170	const _: () = assert!(Code::Jmp_rm16 as u32 + 2 == Code::Jmp_rm64 as u32);
171	const _: () = assert!(Code::Call_rm16 as u32 + 1 == Code::Call_rm32 as u32);
172	const _: () = assert!(Code::Call_rm16 as u32 + 2 == Code::Call_rm64 as u32);
173	(code as u32).wrapping_sub(Code::Jmp_rm16 as u32) <= 2 || (code as u32).wrapping_sub(Code::Call_rm16 as u32) <= 2
174}