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
impl Clone for IndexedOperand
Source§fn clone(&self) -> IndexedOperand
fn clone(&self) -> IndexedOperand
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more