Processor

Struct Processor 

Source
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: ArmVersion

ARM emutaled version.

§registers: CoreRegisters

r0-r15 and sys registers.

§execution_priority: i16§local_monitor: LocalMonitor

The 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: u64

Number 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: bool

When 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

Source

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());
Source

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.

Source

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.

Source

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.
Source

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.

Source

pub fn hook_code(&mut self, range: Range<usize>)

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn read_u16_aligned(&mut self, address: u32) -> Result<u16, RunError>

Implements MemA from Arm Architecture Reference Manual, for 16 bit read accesses.

Source

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.

Source

pub fn read_u32_aligned(&mut self, address: u32) -> Result<u32, RunError>

Implements MemA from Arm Architecture Reference Manual, for 32 bit read accesses.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn read_u16_unaligned(&mut self, address: u32) -> Result<u16, RunError>

Implements MemU from Arm Architecture Reference Manual, for 16 bit read accesses.

Source

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.

Source

pub fn read_u32_unaligned(&mut self, address: u32) -> Result<u32, RunError>

Implements MemU from Arm Architecture Reference Manual, for 32 bit read accesses.

Source

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.

Source

pub fn read_u8_iface(&mut self, address: u32) -> Result<u8, RunError>

Reads a byte at address without checking for privileges.

Source

pub fn write_u8_iface( &mut self, address: u32, value: u8, ) -> Result<(), RunError>

Write byte value at address without checking for privileges.

Source

pub fn write_u16le_iface( &mut self, address: u32, value: u16, ) -> Result<(), RunError>

Write halfword value at address without checking for privileges or alignment.

Source

pub fn read_u16le_iface(&mut self, address: u32) -> Result<u16, RunError>

Read halfword at address without checking for privileges or alignment.

Source

pub fn read_u32le_iface(&mut self, address: u32) -> Result<u32, RunError>

Reads 32-bit word at address without checking for privileges or alignment.

Source

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.

Source

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.

Source

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.

Source

pub fn sp(&self) -> u32

Returns current value of the Stack Pointer (r13)

Source

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).

Source

pub fn set_sp(&mut self, value: u32)

Sets value of the Stack Pointer (r13)

§Arguments
  • value - New Stack Pointer value
Source

pub fn lr(&self) -> u32

Returns current value of the Link Register (r14)

Source

pub fn set_lr(&mut self, value: u32)

Sets Link Register (r14) value

§Arguments
  • value - New Link Register value
Source

pub fn pc(&self) -> u32

Returns current value of the Program Counter (r15)

Source

pub fn set_pc(&mut self, value: u32)

Sets Program Counter (r15) value. This is equivalent to modifying CoreRegisters::pc in Self::registers.

Source

pub fn update_peripherals(&mut self)

Call update on memory mapping which requested an update during a previous operation.

Source

pub fn request_interrupt(&mut self, irq: Irq)

Source

pub fn is_privileged(&self) -> bool

Returns true if execution is privileged.

Corresponds to FindPriv() from Arm Architecture Reference Manual.

Source

pub fn alu_write_pc(&mut self, address: u32)

Write value to PC, with interworking for ARM only from ARMv7

Source

pub fn blx_write_pc(&mut self, address: u32)

Write value to PC, with interworking

Source

pub fn load_write_pc(&mut self, address: u32) -> Result<(), RunError>

Corresponds to operation LoadWritePC() described in ARMv7-M Architecture Reference Manual.

Source

pub fn bx_write_pc(&mut self, address: u32) -> Result<(), RunError>

Write value to PC, with interworking

Source

pub fn condition_passed(&self) -> bool

Source

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.

Source

pub fn generate_coprocessor_exception(&mut self)

Raise usage fault exception and sets NOCP fault flag.

Source

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.

Source

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.

Source

pub fn clear_exclusive_local(&mut self)

Clears the local exclusive monitor lock.

Corresponds to ClearExclusiveLocal() in the Arm Architecture Reference Manual.

Trait Implementations§

Source§

impl Emulator for Processor

Source§

fn next_event(&mut self) -> Result<Event, RunError>

Processes execution until next event, and returns that event.
Source§

fn run(&mut self, options: RunOptions) -> Result<Option<Event>, RunError>

Runs the device until a non instruction event occurs of emulation reaches optional gas limit.
Source§

impl Index<RegisterIndex> for Processor

Indexing implemented for easier access to the registers.

Source§

type Output = u32

The returned type after indexing.
Source§

fn index(&self, index: RegisterIndex) -> &Self::Output

Performs the indexing (container[index]) operation. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.