/*
Copyright (C) 2018-2019 de4dot@gmail.com

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

use crate::enum_utils::{
	to_cc_a, to_cc_ae, to_cc_b, to_cc_be, to_cc_e, to_cc_g, to_cc_ge, to_cc_l, to_cc_le, to_cc_ne, to_cc_np, to_cc_p, to_memory_size_options,
	to_register,
};
use crate::instruction::Instruction;
use crate::utils::to_value_error;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;

// GENERATOR-BEGIN: FormatterSyntax
// ⚠️This was generated by GENERATOR!🦹‍♂️
/// Formatter syntax (GNU Assembler, Intel XED, masm, nasm)
#[allow(dead_code)]
pub(crate) enum FormatterSyntax {
	/// GNU Assembler (AT&T)
	Gas = 0,
	/// Intel XED
	Intel = 1,
	/// masm
	Masm = 2,
	/// nasm
	Nasm = 3,
}
// GENERATOR-END: FormatterSyntax

/// x86 formatter that supports GNU Assembler, Intel XED, masm and nasm syntax
///
/// Args:
///     `syntax` (:class:`FormatterSyntax`): Formatter syntax
///
/// Examples:
///
/// .. testcode::
///
///     from iced_x86 import *
///
///     data = b"\x62\xF2\x4F\xDD\x72\x50\x01"
///     decoder = Decoder(64, data)
///     instr = decoder.decode()
///
///     formatter = Formatter(FormatterSyntax.MASM)
///     formatter.uppercase_mnemonics = True
///     disasm = formatter.format(instr)
///     assert disasm == "VCVTNE2PS2BF16 zmm2{k5}{z},zmm6,dword bcst [rax+4]"
#[pyclass(module = "_iced_x86_py")]
#[text_signature = "(syntax, /)"]
pub(crate) struct Formatter {
	fmt_output: String,
	formatter: Box<dyn iced_x86::Formatter>,
}

unsafe impl Send for Formatter {}

#[pymethods]
impl Formatter {
	#[new]
	fn new(syntax: u32) -> PyResult<Self> {
		let formatter: Box<dyn iced_x86::Formatter> = if syntax == FormatterSyntax::Gas as u32 {
			Box::new(iced_x86::GasFormatter::new())
		} else if syntax == FormatterSyntax::Intel as u32 {
			Box::new(iced_x86::IntelFormatter::new())
		} else if syntax == FormatterSyntax::Masm as u32 {
			Box::new(iced_x86::MasmFormatter::new())
		} else if syntax == FormatterSyntax::Nasm as u32 {
			Box::new(iced_x86::NasmFormatter::new())
		} else {
			return Err(PyValueError::new_err("Invalid formatter syntax"));
		};

		Ok(Formatter { fmt_output: String::new(), formatter })
	}

	/// Formats the whole instruction: prefixes, mnemonic, operands
	///
	/// Args:
	///     `instruction` (Instruction): Instruction to format
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, instruction, /)"]
	fn format(&mut self, instruction: &Instruction) -> &str {
		self.fmt_output.clear();
		self.formatter.format(&instruction.instr, &mut self.fmt_output);
		&self.fmt_output
	}

	/// Formats the mnemonic and any prefixes
	///
	/// Args:
	///     `instruction` (Instruction): Instruction to format
	///     `options` (:class:`FormatMnemonicOptions`): (default = :class:`FormatMnemonicOptions.NONE`) Options
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, instruction, options, /)"]
	#[args(options = 0)]
	fn format_mnemonic(&mut self, instruction: &Instruction, options: u32) -> &str {
		// #[args] line assumption
		const_assert_eq!(0, iced_x86::FormatMnemonicOptions::NONE);

		self.fmt_output.clear();
		self.formatter.format_mnemonic_options(&instruction.instr, &mut self.fmt_output, options);
		&self.fmt_output
	}

	/// Gets the number of operands that will be formatted. A formatter can add and remove operands
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///
	/// Returns:
	///     int: Operand count
	#[text_signature = "($self, instruction, /)"]
	fn operand_count(&mut self, instruction: &Instruction) -> u32 {
		self.formatter.operand_count(&instruction.instr)
	}

	/// Returns the operand access but only if it's an operand added by the formatter.
	///
	/// If it's an operand that is part of :class:`Instruction`, you should call eg. :class:`InstructionInfoFactory.info`.
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///     `operand` (int): Operand number, 0-based. This is a formatter operand and isn't necessarily the same as an instruction operand. See :class:`Formatter.operand_count`
	///
	/// Returns:
	///     :class:`OpAccess`, None: Operand access or ``None``
	///
	/// Raises:
	///     ValueError: If `operand` is invalid
	#[text_signature = "($self, instruction, operand, /)"]
	fn op_access(&mut self, instruction: &Instruction, operand: u32) -> PyResult<Option<u32>> {
		match self.formatter.op_access(&instruction.instr, operand) {
			Ok(res) => Ok(res.map(|v| v as u32)),
			Err(_) => Err(PyValueError::new_err("Invalid operand")),
		}
	}

	/// Converts a formatter operand index to an instruction operand index.
	///
	/// Returns ``None`` if it's an operand added by the formatter
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///     `operand` (int): Operand number, 0-based. This is a formatter operand and isn't necessarily the same as an instruction operand. See :class:`Formatter.operand_count`
	///
	/// Returns:
	///     int, None: Instruction operand or ``None`` if it's an operand added by the formatter
	///
	/// Raises:
	///     ValueError: If `operand` is invalid
	#[text_signature = "($self, instruction, operand, /)"]
	fn get_instruction_operand(&mut self, instruction: &Instruction, operand: u32) -> PyResult<Option<u32>> {
		self.formatter.get_instruction_operand(&instruction.instr, operand).map_err(to_value_error)
	}

	/// Converts an instruction operand index to a formatter operand index.
	///
	/// Returns ``None`` if the instruction operand isn't used by the formatter
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///     `instruction_operand` (int): Instruction operand
	///
	/// Returns:
	///     int, None: Instruction operand or ``None`` if the instruction operand isn't used by the formatter
	///
	/// Raises:
	///     ValueError: If `instruction_operand` is invalid
	#[text_signature = "($self, instruction, instruction_operand, /)"]
	fn get_formatter_operand(&mut self, instruction: &Instruction, instruction_operand: u32) -> PyResult<Option<u32>> {
		self.formatter.get_formatter_operand(&instruction.instr, instruction_operand).map_err(to_value_error)
	}

	/// Formats an operand.
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///     `operand` (int): Operand number, 0-based. This is a formatter operand and isn't necessarily the same as an instruction operand. See :class:`Formatter.operand_count`
	///
	/// Returns:
	///     str: The formatted string
	///
	/// Raises:
	///     ValueError: If `operand` is invalid
	#[text_signature = "($self, instruction, operand, /)"]
	fn format_operand(&mut self, instruction: &Instruction, operand: u32) -> PyResult<&str> {
		self.fmt_output.clear();
		self.formatter.format_operand(&instruction.instr, &mut self.fmt_output, operand).map_err(to_value_error)?;
		Ok(&self.fmt_output)
	}

	/// Formats an operand separator
	///
	/// Args:
	///     `instruction` (Instruction): Instruction
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, instruction, /)"]
	fn format_operand_separator(&mut self, instruction: &Instruction) -> &str {
		self.fmt_output.clear();
		self.formatter.format_operand_separator(&instruction.instr, &mut self.fmt_output);
		&self.fmt_output
	}

	/// Formats all operands
	///
	/// Args:
	///     `instruction` (Instruction): Instruction to format
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, instruction, /)"]
	fn format_all_operands(&mut self, instruction: &Instruction) -> &str {
		self.fmt_output.clear();
		self.formatter.format_all_operands(&instruction.instr, &mut self.fmt_output);
		&self.fmt_output
	}

	/// Formats a register
	///
	/// Args:
	///     `register` (:class:`Register`): Register
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, register, /)"]
	fn format_register(&mut self, register: u32) -> PyResult<&str> {
		Ok(self.formatter.format_register(to_register(register)?))
	}

	/// Formats a ``i8``
	///
	/// Args:
	///     `value` (int): (``i8``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_i8(&mut self, value: i8) -> &str {
		self.formatter.format_i8(value)
	}

	/// Formats a ``i16``
	///
	/// Args:
	///     `value` (int): (``i16``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_i16(&mut self, value: i16) -> &str {
		self.formatter.format_i16(value)
	}

	/// Formats a ``i32``
	///
	/// Args:
	///     `value` (int): (``i32``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_i32(&mut self, value: i32) -> &str {
		self.formatter.format_i32(value)
	}

	/// Formats a ``i64``
	///
	/// Args:
	///     `value` (int): (``i64``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_i64(&mut self, value: i64) -> &str {
		self.formatter.format_i64(value)
	}

	/// Formats a ``u8``
	///
	/// Args:
	///     `value` (int): (``u8``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_u8(&mut self, value: u8) -> &str {
		self.formatter.format_u8(value)
	}

	/// Formats a ``u16``
	///
	/// Args:
	///     `value` (int): (``u16``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_u16(&mut self, value: u16) -> &str {
		self.formatter.format_u16(value)
	}

	/// Formats a ``u32``
	///
	/// Args:
	///     `value` (int): (``u32``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_u32(&mut self, value: u32) -> &str {
		self.formatter.format_u32(value)
	}

	/// Formats a ``u64``
	///
	/// Args:
	///     `value` (int): (``u64``) Value
	///
	/// Returns:
	///     str: The formatted string
	#[text_signature = "($self, value, /)"]
	fn format_u64(&mut self, value: u64) -> &str {
		self.formatter.format_u64(value)
	}

	/// bool: Prefixes are upper cased
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``REP stosd``
	/// ✔️          ``False``   ``rep stosd``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_prefixes(&self) -> bool {
		self.formatter.options().uppercase_prefixes()
	}

	#[setter]
	fn set_uppercase_prefixes(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_prefixes(new_value);
	}

	/// bool: Mnemonics are upper cased
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``MOV rcx,rax``
	/// ✔️          ``False``   ``mov rcx,rax``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_mnemonics(&self) -> bool {
		self.formatter.options().uppercase_mnemonics()
	}

	#[setter]
	fn set_uppercase_mnemonics(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_mnemonics(new_value);
	}

	/// bool: Registers are upper cased
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov RCX,[RAX+RDX*8]``
	/// ✔️          ``False``   ``mov rcx,[rax+rdx*8]``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_registers(&self) -> bool {
		self.formatter.options().uppercase_registers()
	}

	#[setter]
	fn set_uppercase_registers(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_registers(new_value);
	}

	/// bool: Keywords are upper cased (eg. ``BYTE PTR``, ``SHORT``)
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov BYTE PTR [rcx],12h``
	/// ✔️          ``False``   ``mov byte ptr [rcx],12h``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_keywords(&self) -> bool {
		self.formatter.options().uppercase_keywords()
	}

	#[setter]
	fn set_uppercase_keywords(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_keywords(new_value);
	}

	/// bool: Upper case decorators, eg. ``{z}``, ``{sae}``, ``{rd-sae}`` (but not op mask registers: ``{k1}``)
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``vunpcklps xmm2{k5}{Z},xmm6,dword bcst [rax+4]``
	/// ✔️          ``False``   ``vunpcklps xmm2{k5}{z},xmm6,dword bcst [rax+4]``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_decorators(&self) -> bool {
		self.formatter.options().uppercase_decorators()
	}

	#[setter]
	fn set_uppercase_decorators(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_decorators(new_value);
	}

	/// bool: Everything is upper cased, except numbers and their prefixes/suffixes
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``MOV EAX,GS:[RCX*4+0ffh]``
	/// ✔️          ``False``   ``mov eax,gs:[rcx*4+0ffh]``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_all(&self) -> bool {
		self.formatter.options().uppercase_all()
	}

	#[setter]
	fn set_uppercase_all(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_all(new_value);
	}

	/// int: (``u32``) Character index (0-based) where the first operand is formatted. Can be set to 0 to format it immediately after the mnemonic.
	/// At least one space or tab is always added between the mnemonic and the first operand.
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``0``      ``mov•rcx,rbp``
	/// \           ``8``      ``mov•••••rcx,rbp``
	/// =========== ========== ================================================
	#[getter]
	fn first_operand_char_index(&self) -> u32 {
		self.formatter.options().first_operand_char_index()
	}

	#[setter]
	fn set_first_operand_char_index(&mut self, new_value: u32) {
		self.formatter.options_mut().set_first_operand_char_index(new_value);
	}

	/// int: (``u32``) Size of a tab character or 0 to use spaces
	///
	/// Default: ``0``
	#[getter]
	fn tab_size(&self) -> u32 {
		self.formatter.options().tab_size()
	}

	#[setter]
	fn set_tab_size(&mut self, new_value: u32) {
		self.formatter.options_mut().set_tab_size(new_value);
	}

	/// bool: Add a space after the operand separator
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov rax, rcx``
	/// ✔️          ``False``   ``mov rax,rcx``
	/// =========== ========== ================================================
	#[getter]
	fn space_after_operand_separator(&self) -> bool {
		self.formatter.options().space_after_operand_separator()
	}

	#[setter]
	fn set_space_after_operand_separator(&mut self, new_value: bool) {
		self.formatter.options_mut().set_space_after_operand_separator(new_value);
	}

	/// bool: Add a space between the memory expression and the brackets
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[ rcx+rdx ]``
	/// ✔️          ``False``   ``mov eax,[rcx+rdx]``
	/// =========== ========== ================================================
	#[getter]
	fn space_after_memory_bracket(&self) -> bool {
		self.formatter.options().space_after_memory_bracket()
	}

	#[setter]
	fn set_space_after_memory_bracket(&mut self, new_value: bool) {
		self.formatter.options_mut().set_space_after_memory_bracket(new_value);
	}

	/// bool: Add spaces between memory operand ``+`` and ``-`` operators
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[rcx + rdx*8 - 80h]``
	/// ✔️          ``False``   ``mov eax,[rcx+rdx*8-80h]``
	/// =========== ========== ================================================
	#[getter]
	fn space_between_memory_add_operators(&self) -> bool {
		self.formatter.options().space_between_memory_add_operators()
	}

	#[setter]
	fn set_space_between_memory_add_operators(&mut self, new_value: bool) {
		self.formatter.options_mut().set_space_between_memory_add_operators(new_value);
	}

	/// bool: Add spaces between memory operand ``*`` operator
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[rcx+rdx * 8-80h]``
	/// ✔️          ``False``   ``mov eax,[rcx+rdx*8-80h]``
	/// =========== ========== ================================================
	#[getter]
	fn space_between_memory_mul_operators(&self) -> bool {
		self.formatter.options().space_between_memory_mul_operators()
	}

	#[setter]
	fn set_space_between_memory_mul_operators(&mut self, new_value: bool) {
		self.formatter.options_mut().set_space_between_memory_mul_operators(new_value);
	}

	/// bool: Show memory operand scale value before the index register
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[8*rdx]``
	/// ✔️          ``False``   ``mov eax,[rdx*8]``
	/// =========== ========== ================================================
	#[getter]
	fn scale_before_index(&self) -> bool {
		self.formatter.options().scale_before_index()
	}

	#[setter]
	fn set_scale_before_index(&mut self, new_value: bool) {
		self.formatter.options_mut().set_scale_before_index(new_value);
	}

	/// bool: Always show the scale value even if it's ``*1``
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[rbx+rcx*1]``
	/// ✔️          ``False``   ``mov eax,[rbx+rcx]``
	/// =========== ========== ================================================
	#[getter]
	fn always_show_scale(&self) -> bool {
		self.formatter.options().always_show_scale()
	}

	#[setter]
	fn set_always_show_scale(&mut self, new_value: bool) {
		self.formatter.options_mut().set_always_show_scale(new_value);
	}

	/// bool: Always show the effective segment register.
	///
	/// If the option is ``False``, only show the segment register if there's a segment override prefix.
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,ds:[ecx]``
	/// ✔️          ``False``   ``mov eax,[ecx]``
	/// =========== ========== ================================================
	#[getter]
	fn always_show_segment_register(&self) -> bool {
		self.formatter.options().always_show_segment_register()
	}

	#[setter]
	fn set_always_show_segment_register(&mut self, new_value: bool) {
		self.formatter.options_mut().set_always_show_segment_register(new_value);
	}

	/// bool: Show zero displacements
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[rcx*2+0]``
	/// ✔️          ``False``   ``mov eax,[rcx*2]``
	/// =========== ========== ================================================
	#[getter]
	fn show_zero_displacements(&self) -> bool {
		self.formatter.options().show_zero_displacements()
	}

	#[setter]
	fn set_show_zero_displacements(&mut self, new_value: bool) {
		self.formatter.options_mut().set_show_zero_displacements(new_value);
	}

	/// str: Hex number prefix or an empty string, eg. ``"0x"``
	///
	/// Default: ``""`` (masm/nasm/intel), ``"0x"`` (gas)
	#[getter]
	fn hex_prefix(&self) -> &str {
		self.formatter.options().hex_prefix()
	}

	#[setter]
	fn set_hex_prefix(&mut self, new_value: String) {
		self.formatter.options_mut().set_hex_prefix_string(new_value);
	}

	/// str: Hex number suffix or an empty string, eg. ``"h"``
	///
	/// Default: ``"h"`` (masm/nasm/intel), ``""`` (gas)
	#[getter]
	fn hex_suffix(&self) -> &str {
		self.formatter.options().hex_suffix()
	}

	#[setter]
	fn set_hex_suffix(&mut self, new_value: String) {
		self.formatter.options_mut().set_hex_suffix_string(new_value);
	}

	/// int: (``u8``) Size of a digit group, see also :class:`Formatter.digit_separator`
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``0``      ``0x12345678``
	/// ✔️          ``4``      ``0x1234_5678``
	/// =========== ========== ================================================
	#[getter]
	fn hex_digit_group_size(&self) -> u32 {
		self.formatter.options().hex_digit_group_size()
	}

	#[setter]
	fn set_hex_digit_group_size(&mut self, new_value: u32) {
		self.formatter.options_mut().set_hex_digit_group_size(new_value);
	}

	/// str: Decimal number prefix or an empty string
	///
	/// Default: ``""``
	#[getter]
	fn decimal_prefix(&self) -> &str {
		self.formatter.options().decimal_prefix()
	}

	#[setter]
	fn set_decimal_prefix(&mut self, new_value: String) {
		self.formatter.options_mut().set_decimal_prefix_string(new_value);
	}

	/// str: Decimal number suffix or an empty string
	///
	/// Default: ``""``
	#[getter]
	fn decimal_suffix(&self) -> &str {
		self.formatter.options().decimal_suffix()
	}

	#[setter]
	fn set_decimal_suffix(&mut self, new_value: String) {
		self.formatter.options_mut().set_decimal_suffix_string(new_value);
	}

	/// int: (``u8``) Size of a digit group, see also :class:`Formatter.digit_separator`
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``0``      ``12345678``
	/// ✔️          ``3``      ``12_345_678``
	/// =========== ========== ================================================
	#[getter]
	fn decimal_digit_group_size(&self) -> u32 {
		self.formatter.options().decimal_digit_group_size()
	}

	#[setter]
	fn set_decimal_digit_group_size(&mut self, new_value: u32) {
		self.formatter.options_mut().set_decimal_digit_group_size(new_value);
	}

	/// str: Octal number prefix or an empty string
	///
	/// Default: ``""`` (masm/nasm/intel), ``"0"`` (gas)
	#[getter]
	fn octal_prefix(&self) -> &str {
		self.formatter.options().octal_prefix()
	}

	#[setter]
	fn set_octal_prefix(&mut self, new_value: String) {
		self.formatter.options_mut().set_octal_prefix_string(new_value);
	}

	/// str: Octal number suffix or an empty string
	///
	/// Default: ``"o"`` (masm/nasm/intel), ``""`` (gas)
	#[getter]
	fn octal_suffix(&self) -> &str {
		self.formatter.options().octal_suffix()
	}

	#[setter]
	fn set_octal_suffix(&mut self, new_value: String) {
		self.formatter.options_mut().set_octal_suffix_string(new_value);
	}

	/// int: (``u8``) Size of a digit group, see also :class:`Formatter.digit_separator`
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``0``      ``12345670``
	/// ✔️          ``4``      ``1234_5670``
	/// =========== ========== ================================================
	#[getter]
	fn octal_digit_group_size(&self) -> u32 {
		self.formatter.options().octal_digit_group_size()
	}

	#[setter]
	fn set_octal_digit_group_size(&mut self, new_value: u32) {
		self.formatter.options_mut().set_octal_digit_group_size(new_value);
	}

	/// str: Binary number prefix or an empty string
	///
	/// Default: ``""`` (masm/nasm/intel), ``"0b"`` (gas)
	#[getter]
	fn binary_prefix(&self) -> &str {
		self.formatter.options().binary_prefix()
	}

	#[setter]
	fn set_binary_prefix(&mut self, new_value: String) {
		self.formatter.options_mut().set_binary_prefix_string(new_value);
	}

	/// str: Binary number suffix or an empty string
	///
	/// Default: ``"b"`` (masm/nasm/intel), ``""`` (gas)
	#[getter]
	fn binary_suffix(&self) -> &str {
		self.formatter.options().binary_suffix()
	}

	#[setter]
	fn set_binary_suffix(&mut self, new_value: String) {
		self.formatter.options_mut().set_binary_suffix_string(new_value);
	}

	/// int: (``u8``) Size of a digit group, see also :class:`Formatter.digit_separator`
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``0``      ``11010111``
	/// ✔️          ``4``      ``1101_0111``
	/// =========== ========== ================================================
	#[getter]
	fn binary_digit_group_size(&self) -> u32 {
		self.formatter.options().binary_digit_group_size()
	}

	#[setter]
	fn set_binary_digit_group_size(&mut self, new_value: u32) {
		self.formatter.options_mut().set_binary_digit_group_size(new_value);
	}

	/// str: Digit separator or an empty string. See also eg. :class:`Formatter.hex_digit_group_size`
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``""``     ``0x12345678``
	/// \           ``"_"``    ``0x1234_5678``
	/// =========== ========== ================================================
	#[getter]
	fn digit_separator(&self) -> &str {
		self.formatter.options().digit_separator()
	}

	#[setter]
	fn set_digit_separator(&mut self, new_value: String) {
		self.formatter.options_mut().set_digit_separator_string(new_value);
	}

	/// bool: Add leading zeroes to hexadecimal/octal/binary numbers.
	///
	/// This option has no effect on branch targets and displacements, use :class:`Formatter.branch_leading_zeroes`
	/// and :class:`Formatter.displacement_leading_zeroes`.
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``0x0000000A``/``0000000Ah``
	/// ✔️          ``False``   ``0xA``/``0Ah``
	/// =========== ========== ================================================
	#[getter]
	fn leading_zeroes(&self) -> bool {
		self.formatter.options().leading_zeroes()
	}

	#[setter]
	fn set_leading_zeroes(&mut self, new_value: bool) {
		self.formatter.options_mut().set_leading_zeroes(new_value);
	}

	/// bool: Use upper case hex digits
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``0xFF``
	/// \           ``False``   ``0xff``
	/// =========== ========== ================================================
	#[getter]
	fn uppercase_hex(&self) -> bool {
		self.formatter.options().uppercase_hex()
	}

	#[setter]
	fn set_uppercase_hex(&mut self, new_value: bool) {
		self.formatter.options_mut().set_uppercase_hex(new_value);
	}

	/// bool: Small hex numbers (-9 .. 9) are shown in decimal
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``9``
	/// \           ``False``   ``0x9``
	/// =========== ========== ================================================
	#[getter]
	fn small_hex_numbers_in_decimal(&self) -> bool {
		self.formatter.options().small_hex_numbers_in_decimal()
	}

	#[setter]
	fn set_small_hex_numbers_in_decimal(&mut self, new_value: bool) {
		self.formatter.options_mut().set_small_hex_numbers_in_decimal(new_value);
	}

	/// bool: Add a leading zero to hex numbers if there's no prefix and the number starts with hex digits ``A-F``
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``0FFh``
	/// \           ``False``   ``FFh``
	/// =========== ========== ================================================
	#[getter]
	fn add_leading_zero_to_hex_numbers(&self) -> bool {
		self.formatter.options().add_leading_zero_to_hex_numbers()
	}

	#[setter]
	fn set_add_leading_zero_to_hex_numbers(&mut self, new_value: bool) {
		self.formatter.options_mut().set_add_leading_zero_to_hex_numbers(new_value);
	}

	/// int: Number base (``2``, ``8``, ``10``, ``16``)
	///
	/// Raises:
	///     ValueError: If it's an invalid number base
	///
	/// Default: ``16``
	#[getter]
	fn number_base(&self) -> u32 {
		match self.formatter.options().number_base() {
			iced_x86::NumberBase::Binary => 2,
			iced_x86::NumberBase::Octal => 8,
			iced_x86::NumberBase::Decimal => 10,
			iced_x86::NumberBase::Hexadecimal => 16,
		}
	}

	#[setter]
	fn set_number_base(&mut self, new_value: u32) -> PyResult<()> {
		let base = match new_value {
			2 => iced_x86::NumberBase::Binary,
			8 => iced_x86::NumberBase::Octal,
			10 => iced_x86::NumberBase::Decimal,
			16 => iced_x86::NumberBase::Hexadecimal,
			_ => return Err(PyValueError::new_err("Invalid number base")),
		};
		self.formatter.options_mut().set_number_base(base);
		Ok(())
	}

	/// bool: Add leading zeroes to branch offsets. Used by ``CALL NEAR``, ``CALL FAR``, ``JMP NEAR``, ``JMP FAR``, ``Jcc``, ``LOOP``, ``LOOPcc``, ``XBEGIN``
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``je 00000123h``
	/// \           ``False``   ``je 123h``
	/// =========== ========== ================================================
	#[getter]
	fn branch_leading_zeroes(&self) -> bool {
		self.formatter.options().branch_leading_zeroes()
	}

	#[setter]
	fn set_branch_leading_zeroes(&mut self, new_value: bool) {
		self.formatter.options_mut().set_branch_leading_zeroes(new_value);
	}

	/// bool: Show immediate operands as signed numbers
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,-1``
	/// ✔️          ``False``   ``mov eax,FFFFFFFF``
	/// =========== ========== ================================================
	#[getter]
	fn signed_immediate_operands(&self) -> bool {
		self.formatter.options().signed_immediate_operands()
	}

	#[setter]
	fn set_signed_immediate_operands(&mut self, new_value: bool) {
		self.formatter.options_mut().set_signed_immediate_operands(new_value);
	}

	/// bool: Displacements are signed numbers
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``mov al,[eax-2000h]``
	/// \           ``False``   ``mov al,[eax+0FFFFE000h]``
	/// =========== ========== ================================================
	#[getter]
	fn signed_memory_displacements(&self) -> bool {
		self.formatter.options().signed_memory_displacements()
	}

	#[setter]
	fn set_signed_memory_displacements(&mut self, new_value: bool) {
		self.formatter.options_mut().set_signed_memory_displacements(new_value);
	}

	/// bool: Add leading zeroes to displacements
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov al,[eax+00000012h]``
	/// ✔️          ``False``   ``mov al,[eax+12h]``
	/// =========== ========== ================================================
	#[getter]
	fn displacement_leading_zeroes(&self) -> bool {
		self.formatter.options().displacement_leading_zeroes()
	}

	#[setter]
	fn set_displacement_leading_zeroes(&mut self, new_value: bool) {
		self.formatter.options_mut().set_displacement_leading_zeroes(new_value);
	}

	/// :class:`MemorySizeOptions`: Options that control if the memory size (eg. ``DWORD PTR``) is shown or not.
	///
	/// This is ignored by the gas (AT&T) formatter.
	///
	/// Default: :class:`MemorySizeOptions.DEFAULT`
	#[getter]
	fn memory_size_options(&self) -> u32 {
		self.formatter.options().memory_size_options() as u32
	}

	#[setter]
	fn set_memory_size_options(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_memory_size_options(to_memory_size_options(new_value)?);
		Ok(())
	}

	/// bool: Show ``RIP+displ`` or the virtual address
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[rip+12345678h]``
	/// ✔️          ``False``   ``mov eax,[1029384756AFBECDh]``
	/// =========== ========== ================================================
	#[getter]
	fn rip_relative_addresses(&self) -> bool {
		self.formatter.options().rip_relative_addresses()
	}

	#[setter]
	fn set_rip_relative_addresses(&mut self, new_value: bool) {
		self.formatter.options_mut().set_rip_relative_addresses(new_value);
	}

	/// bool: Show ``NEAR``, ``SHORT``, etc if it's a branch instruction
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``je short 1234h``
	/// \           ``False``   ``je 1234h``
	/// =========== ========== ================================================
	#[getter]
	fn show_branch_size(&self) -> bool {
		self.formatter.options().show_branch_size()
	}

	#[setter]
	fn set_show_branch_size(&mut self, new_value: bool) {
		self.formatter.options_mut().set_show_branch_size(new_value);
	}

	/// bool: Use pseudo instructions
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``vcmpnltsd xmm2,xmm6,xmm3``
	/// \           ``False``   ``vcmpsd xmm2,xmm6,xmm3,5``
	/// =========== ========== ================================================
	#[getter]
	fn use_pseudo_ops(&self) -> bool {
		self.formatter.options().use_pseudo_ops()
	}

	#[setter]
	fn set_use_pseudo_ops(&mut self, new_value: bool) {
		self.formatter.options_mut().set_use_pseudo_ops(new_value);
	}

	/// bool: Show the original value after the symbol name
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,[myfield (12345678)]``
	/// ✔️          ``False``   ``mov eax,[myfield]``
	/// =========== ========== ================================================
	#[getter]
	fn show_symbol_address(&self) -> bool {
		self.formatter.options().show_symbol_address()
	}

	#[setter]
	fn set_show_symbol_address(&mut self, new_value: bool) {
		self.formatter.options_mut().set_show_symbol_address(new_value);
	}

	/// bool: (gas only): If ``True``, the formatter doesn't add ``%`` to registers
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``mov eax,ecx``
	/// ✔️          ``False``   ``mov %eax,%ecx``
	/// =========== ========== ================================================
	#[getter]
	fn gas_naked_registers(&self) -> bool {
		self.formatter.options().gas_naked_registers()
	}

	#[setter]
	fn set_gas_naked_registers(&mut self, new_value: bool) {
		self.formatter.options_mut().set_gas_naked_registers(new_value);
	}

	/// bool: (gas only): Shows the mnemonic size suffix even when not needed
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``movl %eax,%ecx``
	/// ✔️          ``False``   ``mov %eax,%ecx``
	/// =========== ========== ================================================
	#[getter]
	fn gas_show_mnemonic_size_suffix(&self) -> bool {
		self.formatter.options().gas_show_mnemonic_size_suffix()
	}

	#[setter]
	fn set_gas_show_mnemonic_size_suffix(&mut self, new_value: bool) {
		self.formatter.options_mut().set_gas_show_mnemonic_size_suffix(new_value);
	}

	/// bool: (gas only): Add a space after the comma if it's a memory operand
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``(%eax, %ecx, 2)``
	/// ✔️          ``False``   ``(%eax,%ecx,2)``
	/// =========== ========== ================================================
	#[getter]
	fn gas_space_after_memory_operand_comma(&self) -> bool {
		self.formatter.options().gas_space_after_memory_operand_comma()
	}

	#[setter]
	fn set_gas_space_after_memory_operand_comma(&mut self, new_value: bool) {
		self.formatter.options_mut().set_gas_space_after_memory_operand_comma(new_value);
	}

	/// bool: (masm only): Add a ``DS`` segment override even if it's not present. Used if it's 16/32-bit code and mem op is a displ
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``mov eax,ds:[12345678]``
	/// \           ``False``   ``mov eax,[12345678]``
	/// =========== ========== ================================================
	#[getter]
	fn masm_add_ds_prefix32(&self) -> bool {
		self.formatter.options().masm_add_ds_prefix32()
	}

	#[setter]
	fn set_masm_add_ds_prefix32(&mut self, new_value: bool) {
		self.formatter.options_mut().set_masm_add_ds_prefix32(new_value);
	}

	/// bool: (masm only): Show symbols in brackets
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``[ecx+symbol]`` / ``[symbol]``
	/// \           ``False``   ``symbol[ecx]`` / ``symbol``
	/// =========== ========== ================================================
	#[getter]
	fn masm_symbol_displ_in_brackets(&self) -> bool {
		self.formatter.options().masm_symbol_displ_in_brackets()
	}

	#[setter]
	fn set_masm_symbol_displ_in_brackets(&mut self, new_value: bool) {
		self.formatter.options_mut().set_masm_symbol_displ_in_brackets(new_value);
	}

	/// bool: (masm only): Show displacements in brackets
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// ✔️          ``True``   ``[ecx+1234h]``
	/// \           ``False``   ``1234h[ecx]``
	/// =========== ========== ================================================
	#[getter]
	fn masm_displ_in_brackets(&self) -> bool {
		self.formatter.options().masm_displ_in_brackets()
	}

	#[setter]
	fn set_masm_displ_in_brackets(&mut self, new_value: bool) {
		self.formatter.options_mut().set_masm_displ_in_brackets(new_value);
	}

	/// bool: (nasm only): Shows ``BYTE``, ``WORD``, ``DWORD`` or ``QWORD`` if it's a sign extended immediate operand value
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``or rcx,byte -1``
	/// ✔️          ``False``   ``or rcx,-1``
	/// =========== ========== ================================================
	#[getter]
	fn nasm_show_sign_extended_immediate_size(&self) -> bool {
		self.formatter.options().nasm_show_sign_extended_immediate_size()
	}

	#[setter]
	fn set_nasm_show_sign_extended_immediate_size(&mut self, new_value: bool) {
		self.formatter.options_mut().set_nasm_show_sign_extended_immediate_size(new_value);
	}

	/// bool: Use ``st(0)`` instead of ``st`` if ``st`` can be used. Ignored by the nasm formatter.
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``fadd st(0),st(3)``
	/// ✔️          ``False``   ``fadd st,st(3)``
	/// =========== ========== ================================================
	#[getter]
	fn prefer_st0(&self) -> bool {
		self.formatter.options().prefer_st0()
	}

	#[setter]
	fn set_prefer_st0(&mut self, new_value: bool) {
		self.formatter.options_mut().set_prefer_st0(new_value);
	}

	/// bool: Show useless prefixes. If it has useless prefixes, it could be data and not code.
	///
	/// =========== ========== ================================================
	/// Default     Value      Example
	/// =========== ========== ================================================
	/// \           ``True``   ``es rep add eax,ecx``
	/// ✔️          ``False``   ``add eax,ecx``
	/// =========== ========== ================================================
	#[getter]
	fn show_useless_prefixes(&self) -> bool {
		self.formatter.options().show_useless_prefixes()
	}

	#[setter]
	fn set_show_useless_prefixes(&mut self, new_value: bool) {
		self.formatter.options_mut().set_show_useless_prefixes(new_value)
	}

	/// :class:`CC_b`: Mnemonic condition code selector (eg. ``JB`` / ``JC`` / ``JNAE``)
	///
	/// Default: ``JB``, ``CMOVB``, ``SETB``
	#[getter]
	fn cc_b(&self) -> u32 {
		self.formatter.options().cc_b() as u32
	}

	#[setter]
	fn set_cc_b(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_b(to_cc_b(new_value)?);
		Ok(())
	}

	/// :class:`CC_ae`: Mnemonic condition code selector (eg. ``JAE`` / ``JNB`` / ``JNC``)
	///
	/// Default: ``JAE``, ``CMOVAE``, ``SETAE``
	#[getter]
	fn cc_ae(&self) -> u32 {
		self.formatter.options().cc_ae() as u32
	}

	#[setter]
	fn set_cc_ae(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_ae(to_cc_ae(new_value)?);
		Ok(())
	}

	/// :class:`CC_e`: Mnemonic condition code selector (eg. ``JE`` / ``JZ``)
	///
	/// Default: ``JE``, ``CMOVE``, ``SETE``, ``LOOPE``, ``REPE``
	#[getter]
	fn cc_e(&self) -> u32 {
		self.formatter.options().cc_e() as u32
	}

	#[setter]
	fn set_cc_e(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_e(to_cc_e(new_value)?);
		Ok(())
	}

	/// :class:`CC_ne`: Mnemonic condition code selector (eg. ``JNE`` / ``JNZ``)
	///
	/// Default: ``JNE``, ``CMOVNE``, ``SETNE``, ``LOOPNE``, ``REPNE``
	#[getter]
	fn cc_ne(&self) -> u32 {
		self.formatter.options().cc_ne() as u32
	}

	#[setter]
	fn set_cc_ne(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_ne(to_cc_ne(new_value)?);
		Ok(())
	}

	/// :class:`CC_be`: Mnemonic condition code selector (eg. ``JBE`` / ``JNA``)
	///
	/// Default: ``JBE``, ``CMOVBE``, ``SETBE``
	#[getter]
	fn cc_be(&self) -> u32 {
		self.formatter.options().cc_be() as u32
	}

	#[setter]
	fn set_cc_be(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_be(to_cc_be(new_value)?);
		Ok(())
	}

	/// :class:`CC_a`: Mnemonic condition code selector (eg. ``JA`` / ``JNBE``)
	///
	/// Default: ``JA``, ``CMOVA``, ``SETA``
	#[getter]
	fn cc_a(&self) -> u32 {
		self.formatter.options().cc_a() as u32
	}

	#[setter]
	fn set_cc_a(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_a(to_cc_a(new_value)?);
		Ok(())
	}

	/// :class:`CC_p`: Mnemonic condition code selector (eg. ``JP`` / ``JPE``)
	///
	/// Default: ``JP``, ``CMOVP``, ``SETP``
	#[getter]
	fn cc_p(&self) -> u32 {
		self.formatter.options().cc_p() as u32
	}

	#[setter]
	fn set_cc_p(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_p(to_cc_p(new_value)?);
		Ok(())
	}

	/// :class:`CC_np`: Mnemonic condition code selector (eg. ``JNP`` / ``JPO``)
	///
	/// Default: ``JNP``, ``CMOVNP``, ``SETNP``
	#[getter]
	fn cc_np(&self) -> u32 {
		self.formatter.options().cc_np() as u32
	}

	#[setter]
	fn set_cc_np(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_np(to_cc_np(new_value)?);
		Ok(())
	}

	/// :class:`CC_l`: Mnemonic condition code selector (eg. ``JL`` / ``JNGE``)
	///
	/// Default: ``JL``, ``CMOVL``, ``SETL``
	#[getter]
	fn cc_l(&self) -> u32 {
		self.formatter.options().cc_l() as u32
	}

	#[setter]
	fn set_cc_l(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_l(to_cc_l(new_value)?);
		Ok(())
	}

	/// :class:`CC_ge`: Mnemonic condition code selector (eg. ``JGE`` / ``JNL``)
	///
	/// Default: ``JGE``, ``CMOVGE``, ``SETGE``
	#[getter]
	fn cc_ge(&self) -> u32 {
		self.formatter.options().cc_ge() as u32
	}

	#[setter]
	fn set_cc_ge(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_ge(to_cc_ge(new_value)?);
		Ok(())
	}

	/// :class:`CC_le`: Mnemonic condition code selector (eg. ``JLE`` / ``JNG``)
	///
	/// Default: ``JLE``, ``CMOVLE``, ``SETLE``
	#[getter]
	fn cc_le(&self) -> u32 {
		self.formatter.options().cc_le() as u32
	}

	#[setter]
	fn set_cc_le(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_le(to_cc_le(new_value)?);
		Ok(())
	}

	/// :class:`CC_g`: Mnemonic condition code selector (eg. ``JG`` / ``JNLE``)
	///
	/// Default: ``JG``, ``CMOVG``, ``SETG``
	#[getter]
	fn cc_g(&self) -> u32 {
		self.formatter.options().cc_g() as u32
	}

	#[setter]
	fn set_cc_g(&mut self, new_value: u32) -> PyResult<()> {
		self.formatter.options_mut().set_cc_g(to_cc_g(new_value)?);
		Ok(())
	}
}
