pub struct Processor {
pub version: ArmVersion,
pub registers: CoreRegisters,
pub execution_priority: i16,
pub local_monitor: LocalMonitor,
pub instruction_decoder: Box<dyn InstructionDecode>,
pub cycles: u64,
pub coprocessors: Vec<Option<Rc<RefCell<dyn Coprocessor>>>>,
pub tolerate_pop_stack_unaligned_pc: bool,
/* private fields */
}Expand description
ARM processor state and attached peripherals.
This is the main struct of Armagnac. Once instanciated, memories and peripherals can be mapped in the memory space used by the processor. The processor can then be executed, inspected and eventually modified on the fly.
The following example will execute a tiny assembly program:
let mut proc = Processor::new(Config::v7m());
// Load a tiny assembly program at address 0x1000.
// This creates a RAM memory of 6 bytes.
// mov r0, #5
// mov r1, #2
// sub r2, r0, r1
proc.map(0x1000, &[0x05, 0x20, 0x02, 0x21, 0x42, 0x1a]);
proc.set_pc(0x1000);
// Run and limit execution to 3 instructions
proc.run(RunOptions::new().gas(3)).unwrap();
assert_eq!(proc.registers.r2, 3);By default Processor uses BasicInstructionDecoder for decoding instructions. When running long emulations, you may want to use a more performant decoder, at the cost of a longer initialization time:
use armagnac::core::{Processor, Config, ArmVersion};
use armagnac::decoder::{Lut16AndGrouped32InstructionDecoder};
let mut proc = Processor::new(Config::v7m());
proc.instruction_decoder = Box::new(Lut16AndGrouped32InstructionDecoder::new(ArmVersion::V7M));You can also write your own decoder by implementing the InstructionDecode trait. For example, when emulating a small function for fuzzing, you may only keep the instructions used in the assembly of that particular method to make the instruction decoding faster.
Fields§
§version: ArmVersionARM emutaled version.
registers: CoreRegistersr0-r15 and sys registers.
execution_priority: i16§local_monitor: LocalMonitorThe local monitor tags a memory address for exclusive accesses.
instruction_decoder: Box<dyn InstructionDecode>Parses word or double-word values to decode them as executable ARM instructions. Since this is a performance critical task of the emulator, different implementation with different optimisation strategies, which may depend on the context, may be selected.
cycles: u64Number of elapsed CPU clock cycles. Although all instructions will take one clock cycle in Armagnac, this value can be different from the number of executed instruction in the case WFE (Wait For Event) or WFI (Wait For Interrupt) instructions are used.
coprocessors: Vec<Option<Rc<RefCell<dyn Coprocessor>>>>Coprocessors. If Arm profile does not support coprocessors, this vector remains empty.
tolerate_pop_stack_unaligned_pc: boolWhen poping PC from the stack (during exception return for instance), PC should be aligned,
otherwise execution is unpredictable according to the ARM specification. However, some
implementation may still set LSB to 1 for Thumb mode, and this can work on some hardware.
So to allow emulation in that case, tolerate_pop_stack_unaligned_pc can be set to true.
If false (the default) an error will be reported by the emulation if PC is unaligned.
Implementations§
Source§impl Processor
impl Processor
Sourcepub fn new(config: Config) -> Self
pub fn new(config: Config) -> Self
Creates a new Arm processor.
A Config is passed for initialization.
If the Arm architecture version is not defined in the configuration, this method panics.
let processor = Processor::new(Config::v7m());Sourcepub fn map(
&mut self,
address: u32,
data: &[u8],
) -> Result<Rc<RefCell<RamMemory>>, MapConflict>
pub fn map( &mut self, address: u32, data: &[u8], ) -> Result<Rc<RefCell<RamMemory>>, MapConflict>
Maps and returns a RAM memory with data as initial value. The size of the created memory
is the size of data.
Sourcepub fn map_iface(
&mut self,
address: u32,
iface: Rc<RefCell<dyn MemoryInterface>>,
) -> Result<(), MapConflict>
pub fn map_iface( &mut self, address: u32, iface: Rc<RefCell<dyn MemoryInterface>>, ) -> Result<(), MapConflict>
Maps an interface to the memory space. Returns an error if the new interface size overflows the address space, or if the new interface memory region intersects with an already mapped memory region.
Sourcepub fn map_ram(
&mut self,
address: u32,
size: u32,
) -> Result<Rc<RefCell<RamMemory>>, MapConflict>
pub fn map_ram( &mut self, address: u32, size: u32, ) -> Result<Rc<RefCell<RamMemory>>, MapConflict>
Creates a new RAM memory and map it in the address space.
RAM is initialized at 0.
§Arguments
address- RAM memory start address.size- RAM memory size.
Sourcepub fn set_coprocessor(
&mut self,
index: usize,
coprocessor: Rc<RefCell<dyn Coprocessor>>,
)
pub fn set_coprocessor( &mut self, index: usize, coprocessor: Rc<RefCell<dyn Coprocessor>>, )
Defines the implementation of one of the 16 possible coprocessors.
Panics if index is out of range or Arm version does not support coprocessors.
pub fn hook_code(&mut self, range: Range<usize>)
Sourcepub fn read_u8_with_priv(
&mut self,
address: u32,
privileged: bool,
) -> Result<u8, RunError>
pub fn read_u8_with_priv( &mut self, address: u32, privileged: bool, ) -> Result<u8, RunError>
Implements MemA_with_priv and MemU_with_priv from Arm Architecture Reference Manual,
for 8 bit read accesses.
Sourcepub fn write_u8_with_priv(
&mut self,
address: u32,
value: u8,
privileged: bool,
) -> Result<(), RunError>
pub fn write_u8_with_priv( &mut self, address: u32, value: u8, privileged: bool, ) -> Result<(), RunError>
Implements MemA_with_priv and MemU_with_priv from Arm Architecture Reference Manual,
for 8 bit write accesses.
Sourcepub fn read_u16_aligned_with_priv(
&mut self,
address: u32,
privileged: bool,
) -> Result<u16, RunError>
pub fn read_u16_aligned_with_priv( &mut self, address: u32, privileged: bool, ) -> Result<u16, RunError>
Implements MemA_with_priv from Arm Architecture Reference Manual, for 16 bit read
accesses.
Sourcepub fn write_u16_aligned_with_priv(
&mut self,
address: u32,
value: u16,
privileged: bool,
) -> Result<(), RunError>
pub fn write_u16_aligned_with_priv( &mut self, address: u32, value: u16, privileged: bool, ) -> Result<(), RunError>
Implements MemA_with_priv from Arm Architecture Reference Manual, for 16 bit write
accesses.
Sourcepub fn read_u32_aligned_with_priv(
&mut self,
address: u32,
privileged: bool,
) -> Result<u32, RunError>
pub fn read_u32_aligned_with_priv( &mut self, address: u32, privileged: bool, ) -> Result<u32, RunError>
Implements MemA_with_priv from Arm Architecture Reference Manual, for 32 bit read
accesses.
Sourcepub fn write_u32_aligned_with_priv(
&mut self,
address: u32,
value: u32,
privileged: bool,
) -> Result<(), RunError>
pub fn write_u32_aligned_with_priv( &mut self, address: u32, value: u32, privileged: bool, ) -> Result<(), RunError>
Implements MemA_with_priv from Arm Architecture Reference Manual, for 32 bit write
accesses.
Sourcepub fn read_u8(&mut self, address: u32) -> Result<u8, RunError>
pub fn read_u8(&mut self, address: u32) -> Result<u8, RunError>
Implements MemA and MemU from Arm Architecture Reference Manual, for 8 bit read
accesses.
Sourcepub fn write_u8(&mut self, address: u32, value: u8) -> Result<(), RunError>
pub fn write_u8(&mut self, address: u32, value: u8) -> Result<(), RunError>
Implements MemA and MemU from Arm Architecture Reference Manual, for 8 bit write
accesses.
Sourcepub fn read_u16_aligned(&mut self, address: u32) -> Result<u16, RunError>
pub fn read_u16_aligned(&mut self, address: u32) -> Result<u16, RunError>
Implements MemA from Arm Architecture Reference Manual, for 16 bit read accesses.
Sourcepub fn write_u16_aligned(
&mut self,
address: u32,
value: u16,
) -> Result<(), RunError>
pub fn write_u16_aligned( &mut self, address: u32, value: u16, ) -> Result<(), RunError>
Implements MemA from Arm Architecture Reference Manual, for 8 bit write accesses.
Sourcepub fn read_u32_aligned(&mut self, address: u32) -> Result<u32, RunError>
pub fn read_u32_aligned(&mut self, address: u32) -> Result<u32, RunError>
Implements MemA from Arm Architecture Reference Manual, for 32 bit read accesses.
Sourcepub fn write_u32_aligned(
&mut self,
address: u32,
value: u32,
) -> Result<(), RunError>
pub fn write_u32_aligned( &mut self, address: u32, value: u32, ) -> Result<(), RunError>
Implements MemA from Arm Architecture Reference Manual, for 32 bit write accesses.
Sourcepub fn read_u16_unaligned_with_priv(
&mut self,
address: u32,
privileged: bool,
) -> Result<u16, RunError>
pub fn read_u16_unaligned_with_priv( &mut self, address: u32, privileged: bool, ) -> Result<u16, RunError>
Implements MemU_with_priv from Arm Architecture Reference Manual, for 16 bit read
accesses.
Sourcepub fn write_u16_unaligned_with_priv(
&mut self,
address: u32,
value: u16,
privileged: bool,
) -> Result<(), RunError>
pub fn write_u16_unaligned_with_priv( &mut self, address: u32, value: u16, privileged: bool, ) -> Result<(), RunError>
Implements MemU_with_priv from Arm Architecture Reference Manual, for 16 bit write
accesses.
Sourcepub fn read_u32_unaligned_with_priv(
&mut self,
address: u32,
privileged: bool,
) -> Result<u32, RunError>
pub fn read_u32_unaligned_with_priv( &mut self, address: u32, privileged: bool, ) -> Result<u32, RunError>
Implements MemU_with_priv from Arm Architecture Reference Manual, for 32 bit read
accesses.
Sourcepub fn write_u32_unaligned_with_priv(
&mut self,
address: u32,
value: u32,
privileged: bool,
) -> Result<(), RunError>
pub fn write_u32_unaligned_with_priv( &mut self, address: u32, value: u32, privileged: bool, ) -> Result<(), RunError>
Implements MemU_with_priv from Arm Architecture Reference Manual, for 32 bit write
accesses.
Sourcepub fn read_u16_unaligned(&mut self, address: u32) -> Result<u16, RunError>
pub fn read_u16_unaligned(&mut self, address: u32) -> Result<u16, RunError>
Implements MemU from Arm Architecture Reference Manual, for 16 bit read accesses.
Sourcepub fn write_u16_unaligned(
&mut self,
address: u32,
value: u16,
) -> Result<(), RunError>
pub fn write_u16_unaligned( &mut self, address: u32, value: u16, ) -> Result<(), RunError>
Implements MemU from Arm Architecture Reference Manual, for 16 bit write accesses.
Sourcepub fn read_u32_unaligned(&mut self, address: u32) -> Result<u32, RunError>
pub fn read_u32_unaligned(&mut self, address: u32) -> Result<u32, RunError>
Implements MemU from Arm Architecture Reference Manual, for 32 bit read accesses.
Sourcepub fn write_u32_unaligned(
&mut self,
address: u32,
value: u32,
) -> Result<(), RunError>
pub fn write_u32_unaligned( &mut self, address: u32, value: u32, ) -> Result<(), RunError>
Implements MemU from Arm Architecture Reference Manual, for 32 bit write accesses.
Sourcepub fn read_u8_iface(&mut self, address: u32) -> Result<u8, RunError>
pub fn read_u8_iface(&mut self, address: u32) -> Result<u8, RunError>
Reads a byte at address without checking for privileges.
Sourcepub fn write_u8_iface(
&mut self,
address: u32,
value: u8,
) -> Result<(), RunError>
pub fn write_u8_iface( &mut self, address: u32, value: u8, ) -> Result<(), RunError>
Write byte value at address without checking for privileges.
Sourcepub fn write_u16le_iface(
&mut self,
address: u32,
value: u16,
) -> Result<(), RunError>
pub fn write_u16le_iface( &mut self, address: u32, value: u16, ) -> Result<(), RunError>
Write halfword value at address without checking for privileges or alignment.
Sourcepub fn read_u16le_iface(&mut self, address: u32) -> Result<u16, RunError>
pub fn read_u16le_iface(&mut self, address: u32) -> Result<u16, RunError>
Read halfword at address without checking for privileges or alignment.
Sourcepub fn read_u32le_iface(&mut self, address: u32) -> Result<u32, RunError>
pub fn read_u32le_iface(&mut self, address: u32) -> Result<u32, RunError>
Reads 32-bit word at address without checking for privileges or alignment.
Sourcepub fn write_u32le_iface(
&mut self,
address: u32,
value: u32,
) -> Result<(), RunError>
pub fn write_u32le_iface( &mut self, address: u32, value: u32, ) -> Result<(), RunError>
Writes 32-bit word at address without checking for privileges or alignment.
Sourcepub fn read_bytes_iface(
&mut self,
address: u32,
size: u32,
) -> Result<Vec<u8>, RunError>
pub fn read_bytes_iface( &mut self, address: u32, size: u32, ) -> Result<Vec<u8>, RunError>
Reads size successive bytes starting at address, without checking for privileges or
alignment.
Panics if address overflows. This may change in the future.
Sourcepub fn write_bytes_iface(
&mut self,
address: u32,
data: &[u8],
) -> Result<(), RunError>
pub fn write_bytes_iface( &mut self, address: u32, data: &[u8], ) -> Result<(), RunError>
Writes bytes starting at address, without checking for privileges or alignment.
Panics if address overflows. This may change in the future.
Sourcepub fn set(&mut self, index: RegisterIndex, value: u32)
pub fn set(&mut self, index: RegisterIndex, value: u32)
Sets the value of a register.
This is a shorcut to self.registers.set(r, value).
Sourcepub fn set_pc(&mut self, value: u32)
pub fn set_pc(&mut self, value: u32)
Sets Program Counter (r15) value. This is equivalent to modifying CoreRegisters::pc in Self::registers.
Sourcepub fn update_peripherals(&mut self)
pub fn update_peripherals(&mut self)
Call update on memory mapping which requested an update during a previous operation.
pub fn request_interrupt(&mut self, irq: Irq)
Sourcepub fn is_privileged(&self) -> bool
pub fn is_privileged(&self) -> bool
Returns true if execution is privileged.
Corresponds to FindPriv() from Arm Architecture Reference Manual.
Sourcepub fn alu_write_pc(&mut self, address: u32)
pub fn alu_write_pc(&mut self, address: u32)
Write value to PC, with interworking for ARM only from ARMv7
Sourcepub fn blx_write_pc(&mut self, address: u32)
pub fn blx_write_pc(&mut self, address: u32)
Write value to PC, with interworking
Sourcepub fn load_write_pc(&mut self, address: u32) -> Result<(), RunError>
pub fn load_write_pc(&mut self, address: u32) -> Result<(), RunError>
Corresponds to operation LoadWritePC() described in ARMv7-M Architecture Reference Manual.
Sourcepub fn bx_write_pc(&mut self, address: u32) -> Result<(), RunError>
pub fn bx_write_pc(&mut self, address: u32) -> Result<(), RunError>
Write value to PC, with interworking
pub fn condition_passed(&self) -> bool
Sourcepub fn coproc_accepted(
&mut self,
cp: u8,
ins: u32,
) -> Option<Rc<RefCell<dyn Coprocessor>>>
pub fn coproc_accepted( &mut self, cp: u8, ins: u32, ) -> Option<Rc<RefCell<dyn Coprocessor>>>
Calls for Coprocessor::accepted of a selected coprocessor, for a given instruction.
If coprocessor does not accept instruction, or if coprocessor is not defined, None is returned.
If coprocessor is defined and accepts the instruction, it is returned.
This corresponds to Coproc_Accepted() ins Arm Architecture Reference Manual.
Sourcepub fn generate_coprocessor_exception(&mut self)
pub fn generate_coprocessor_exception(&mut self)
Raise usage fault exception and sets NOCP fault flag.
Sourcepub fn set_exclusive_monitors(&mut self, address: u32, size: u32)
pub fn set_exclusive_monitors(&mut self, address: u32, size: u32)
Tags a memory address for exclusive access. size can be in [1, 4].
Corresponds to SetExclusiveMonitors() in Arm Architecture Reference Manual.
Sourcepub fn exclusive_monitors_pass(
&mut self,
address: u32,
size: u32,
) -> Result<bool, RunError>
pub fn exclusive_monitors_pass( &mut self, address: u32, size: u32, ) -> Result<bool, RunError>
If the local exclusive monitor has locked a given address, clear the lock and return true.
Corresponds to ExclusiveMonitorsPass() in the Arm Architecture Reference Manual.
Sourcepub fn clear_exclusive_local(&mut self)
pub fn clear_exclusive_local(&mut self)
Clears the local exclusive monitor lock.
Corresponds to ClearExclusiveLocal() in the Arm Architecture Reference Manual.