Enum IndexedOperand

Source
pub enum IndexedOperand {
    RegisterDeferred(Register),
    AutoDecrement(Register),
    AutoIncrement(Register),
    AutoIncrementDeferred(Register),
    ByteDisplacement(i8, Register),
    ByteDisplacementDeferred(i8, Register),
    WordDisplacement(i16, Register),
    WordDisplacementDeferred(i16, Register),
    LongwordDisplacement(i32, Register),
    LongwordDisplacementDeferred(i32, Register),
    Absolute(u32),
}
Expand description

§VAX Instruction Indexed Operand

This enum specifies all of the valid VAX instruction operands that can be part of an indexed addressing mode.

Variants§

§

RegisterDeferred(Register)

§Register Deferred Mode

The register deferred addressing mode is used to access the data pointed to by a register. It is identified by byte values 0x60 through 0x6E with the low nibble indicating the register. The behavior of 0x6F (which would use the PC) is unpredictable.

§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for register_deferred in 0x60_u8..=0x6E {
        let reg = Register::from(register_deferred);
        assert_eq!(Operand::Indexed(IndexedOperand::RegisterDeferred(reg), indexed_reg),
            Cursor::new([indexed, register_deferred])
                .read_operand(AccessType::Read, DataType::Byte).unwrap());
    }
}
§

AutoDecrement(Register)

§Autodecrement Mode

The autodecrement addressing mode decreases the value in the specified register by the number of bytes indicated by the VAX data type, and then the register is used as a pointer to memory to access the VAX data type. It is identified by byte values 0x70 through 0x7E with the low nibble indicating which register is used. 0x7F (which would use the PC) is unpredictable.

§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for autodecrement in 0x70_u8..=0x7E {
        let reg = Register::from(autodecrement);
        if indexed_reg != reg {
            assert_eq!(Operand::Indexed(IndexedOperand::AutoDecrement(reg), indexed_reg),
                Cursor::new([indexed, autodecrement])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

AutoIncrement(Register)

§Autoincrement Mode

The autoincrement addressing mode uses the specified register as a pointer to memory to access the VAX data type, and then increases the value in the register to point to the byte after the VAX data type. It is identified by byte values 0x80 through 0x8E with the low nibble indicating which register is used. 0x8F indicates the immediate addressing mode.

§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for autoincrement in 0x80_u8..=0x8E {
        let reg = Register::from(autoincrement);
        if indexed_reg != reg {
            assert_eq!(Operand::Indexed(IndexedOperand::AutoIncrement(reg), indexed_reg),
                Cursor::new([indexed, autoincrement])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

AutoIncrementDeferred(Register)

§Autoincrement Deferred Mode

The autoincrement deferred addressing mode uses the specified register as the 32-bit address of a pointer to memory to access a VAX data type, and then increases the value in the register by 4 to point to the next 32-bit address. It is identified by byte values 0x90 through 0x9E with the low nibble indicating which register is used. 0x8F indicates the absolute addressing mode.

§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for autoincrement_deferred in 0x90_u8..=0x9E {
        let reg = Register::from(autoincrement_deferred);
        if indexed_reg != reg {
            assert_eq!(Operand::Indexed(IndexedOperand::AutoIncrementDeferred(reg),
                indexed_reg), Cursor::new([indexed, autoincrement_deferred])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

ByteDisplacement(i8, Register)

§Byte Displacement Mode

The byte displacement addressing mode is used to access the data pointed to by a register with a signed byte offset. It is identified by byte values 0xA0 through 0xAF with the low nibble indicating the register. It is followed by the (8-bit) byte-sized offset value.

When the register is PC (0xAF), it is called byte relative mode. It uses the value of the PC register after it reads the operand and then adds the signed byte offset. When represented in MACRO32 assembly language, the (PC) is implied.

        MOVL    B^20(R0), R1            ; Byte Displacement Mode
        MOVL    B^-20, R2               ; Byte Relative Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const BYTE_OFFSETS: &[i8] = &[-128, -56, -1, 0, 20, 42, 127];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for byte_displacement in 0xA0_u8..=0xAF {
        let reg = Register::from(byte_displacement);
        for byte_offset in BYTE_OFFSETS.iter() {
            assert_eq!(Operand::Indexed(
                IndexedOperand::ByteDisplacement(*byte_offset, reg), indexed_reg),
                Cursor::new([indexed, byte_displacement, *byte_offset as u8])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

ByteDisplacementDeferred(i8, Register)

§Byte Displacement Deferred Mode

The byte displacement deferred addressing mode is used to access the data pointed to by an address stored in memory pointed to by a register with a signed byte offset. It is identified by byte values 0xB0 through 0xBF with the low nibble indicating the register. It is followed by the (8-bit) byte-sized offset value.

When the register is PC (0xBF), it is called byte relative deferred mode. It uses the value of the PC register after it reads the operand and then adds the signed byte offset to point to the 32-bit pointer which it uses to access the desired memory. When represented in MACRO32 assembly language, the (PC) is implied.

        ; The following instruction takes the pointer in R0 and adds 20 to it.
        ; It then uses the 32-bit address stored at that location to access
        ; the 32-bit value and store it in R1.
        MOVL    @B^20(R0), R1           ; Byte Displacement Deferred Mode
        ; The following instruction takes the PC after it reads the `@B^-20`,
        ; and then subracts 20 from it. It then uses the 32-bit address
        ; stored at that location to access the 32-bit value and store it in
        ; R2.
        MOVL    @B^-20, R2              ; Byte Relative Deferred Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const BYTE_OFFSETS: &[i8] = &[-128, -56, -1, 0, 20, 42, 127];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for byte_displacement_deferred in 0xB0_u8..=0xBF {
        let reg = Register::from(byte_displacement_deferred);
        for byte_offset in BYTE_OFFSETS.iter() {
            assert_eq!(Operand::Indexed(
                IndexedOperand::ByteDisplacementDeferred(*byte_offset, reg), indexed_reg),
                Cursor::new([indexed, byte_displacement_deferred, *byte_offset as u8])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

WordDisplacement(i16, Register)

§Word Displacement Mode

The word displacement addressing mode is used to access the data pointed to by a register with a signed word offset. It is identified by word values 0xC0 through 0xCF with the low nibble indicating the register. It is followed by the (16-bit) word-sized offset value.

When the register is PC (0xCF), it is called word relative mode. It uses the value of the PC register after it reads the operand and then adds the signed word offset. When represented in MACRO32 assembly language, the (PC) is implied.

        MOVL    W^1420(R0), R1          ; Word Displacement Mode
        MOVL    W^-9520, R2             ; Word Relative Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const WORD_OFFSETS: &[i16] = &[-32768, -23456, -9876, -129, 128, 5678, 12345, 32767];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for word_displacement in 0xC0_u8..=0xCF {
        let reg = Register::from(word_displacement);
        for word_offset in WORD_OFFSETS.iter() {
            let word_bytes = word_offset.to_le_bytes();
            assert_eq!(Operand::Indexed(
                IndexedOperand::WordDisplacement(*word_offset, reg), indexed_reg),
                Cursor::new([indexed, word_displacement, word_bytes[0], word_bytes[1]])
                    .read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

WordDisplacementDeferred(i16, Register)

§Word Displacement Deferred Mode

The word displacement deferred addressing mode is used to access the data pointed to by an address stored in memory pointed to by a register with a signed word offset. It is identified by word values 0xD0 through 0xDF with the low nibble indicating the register. It is followed by the (16-bit) word-sized offset value.

When the register is PC (0xDF), it is called word relative deferred mode. It uses the value of the PC register after it reads the operand and then adds the signed word offset to point to the 32-bit pointer which it uses to access the desired memory. When represented in MACRO32 assembly language, the (PC) is implied.

        ; The following instruction takes the pointer in R0 and adds 1420 to
        ; it. It then uses the 32-bit address stored at that location to
        ; access the 32-bit value and store it in R1.
        MOVL    @W^1420(R0), R1         ; Word Displacement Deferred Mode

        ; The following instruction takes the PC after it reads the `@W^-5220`,
        ; and then subracts 5220 from it. It then uses the 32-bit address stored
        ; at that location to access the 32-bit value and store it in R2.
        MOVL    @W^-5220, R2            ; Word Relative Deferred Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const WORD_OFFSETS: &[i16] = &[-32768, -23456, -9876, -129, 128, 5678, 12345, 32767];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for word_displacement_deferred in 0xD0_u8..=0xDF {
        let reg = Register::from(word_displacement_deferred);
        for word_offset in WORD_OFFSETS.iter() {
            let word_bytes = word_offset.to_le_bytes();
            assert_eq!(Operand::Indexed(
                IndexedOperand::WordDisplacementDeferred(*word_offset, reg), indexed_reg),
                Cursor::new([
                    indexed,
                    word_displacement_deferred,
                    word_bytes[0],
                    word_bytes[1],
                ]).read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

LongwordDisplacement(i32, Register)

§Longword Displacement Mode

The longword displacement addressing mode is used to access the data pointed to by a register with a signed longword offset. It is identified by longword values 0xE0 through 0xEF with the low nibble indicating the register. It is followed by the (16-bit) longword-sized offset value.

When the register is PC (0xEF), it is called longword relative mode. It uses the value of the PC register after it reads the operand and then adds the signed longword offset. When represented in MACRO32 assembly language, the (PC) is implied.

        MOVL    L^72140(R0), R1          ; Longword Displacement Mode
        MOVL    L^-89520, R2             ; Longword Relative Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const LONGWORD_OFFSETS: &[i32] = &[-2147483648, -12345678, -32769, 32768, 87654321, 2147483647];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for longword_displacement in 0xE0_u8..=0xEF {
        let reg = Register::from(longword_displacement);
        for longword_offset in LONGWORD_OFFSETS.iter() {
            let longword_bytes = longword_offset.to_le_bytes();
            assert_eq!(Operand::Indexed(
                IndexedOperand::LongwordDisplacement(*longword_offset, reg), indexed_reg),
                Cursor::new([
                    indexed,
                    longword_displacement,
                    longword_bytes[0],
                    longword_bytes[1],
                    longword_bytes[2],
                    longword_bytes[3],
                ]).read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

LongwordDisplacementDeferred(i32, Register)

§Longword Displacement Deferred Mode

The longword displacement deferred addressing mode is used to access the data pointed to by an address stored in memory pointed to by a register with a signed longword offset. It is identified by longword values 0xF0 through 0xFF with the low nibble indicating the register. It is followed by the (32-bit) longword-sized offset value.

When the register is PC (0xFF), it is called longword relative deferred mode. It uses the value of the PC register after it reads the operand and then adds the signed longword offset to point to the 32-bit pointer which it uses to access the desired memory. When represented in MACRO32 assembly language, the (PC) is implied.

        ; The following instruction takes the pointer in R0 and adds 721420 to
        ; it. It then uses the 32-bit address stored at that location to access
        ; the 32-bit value and store it in R1.
        MOVL    @L^721420(R0), R1       ; Longword Displacement Deferred Mode

        ; The following instruction takes the PC after it reads the `@L^-89520`,
        ; and then subracts 89520 from it. It then uses the 32-bit address
        ; stored at that location to access the 32-bit value and store it in R2.
        MOVL    @L^-89520, R2           ; Longword Relative Deferred Mode (uses PC)
§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const LONGWORD_OFFSETS: &[i32] = &[-2147483648, -12345678, -32769, 32768, 87654321, 2147483647];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for longword_displacement_deferred in 0xF0_u8..=0xFF {
        let reg = Register::from(longword_displacement_deferred);
        for longword_offset in LONGWORD_OFFSETS.iter() {
            let longword_bytes = longword_offset.to_le_bytes();
            assert_eq!(Operand::Indexed(
                IndexedOperand::LongwordDisplacementDeferred(*longword_offset, reg), indexed_reg),
                Cursor::new([
                    indexed,
                    longword_displacement_deferred,
                    longword_bytes[0],
                    longword_bytes[1],
                    longword_bytes[2],
                    longword_bytes[3],
                ]).read_operand(AccessType::Read, DataType::Byte).unwrap());
        }
    }
}
§

Absolute(u32)

§Absolute Mode

The absolute adressing mode is used to access memory at a fixed address. It is identified by the byte value 0x9F followed by the 32-bit address to access memory in little-endian order.

§Examples
use vax_disassembler::opcode::{AccessType, DataType};
use vax_disassembler::operand::{IndexedOperand, Operand, ReadOperand, Register};
use std::io::Cursor;

const ADDRESSES: &[u32] = &[0x0, 0x200, 0x80000000, 0x81234567, 0xBFFFFFFF, 0xFFFFFFFF];
for indexed in 0x40_u8..=0x4E {
    let indexed_reg = Register::from(indexed);
    for address in ADDRESSES.iter() {
        let address_bytes = address.to_le_bytes();
        assert_eq!(Operand::Indexed(IndexedOperand::Absolute(*address), indexed_reg),
            Cursor::new([
                indexed,
                0x9F,
                address_bytes[0],
                address_bytes[1],
                address_bytes[2],
                address_bytes[3],
            ]).read_operand(AccessType::Read, DataType::Byte).unwrap());
    }
}

Trait Implementations§

Source§

impl Clone for IndexedOperand

Source§

fn clone(&self) -> IndexedOperand

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for IndexedOperand

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for IndexedOperand

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<IndexedOperand> for Operand

Source§

fn from(operand: IndexedOperand) -> Operand

Converts to this type from the input type.
Source§

impl PartialEq for IndexedOperand

Source§

fn eq(&self, other: &IndexedOperand) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl TryFrom<Operand> for IndexedOperand

Source§

type Error = Error

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

fn try_from(operand: Operand) -> Result<IndexedOperand>

Performs the conversion.
Source§

impl Copy for IndexedOperand

Source§

impl Eq for IndexedOperand

Source§

impl StructuralPartialEq for IndexedOperand

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
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.