use std::cmp;
use std::fmt;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MemoryAddress {
RealSegmentOffset(u16, u16),
LongSegmentOffset(u16, u16),
Unset,
}
impl fmt::Display for MemoryAddress {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
MemoryAddress::RealSegmentOffset(seg, off) => {
write!(f, "{:04X}:{:04X}", seg, off)
}
MemoryAddress::LongSegmentOffset(seg, off) => {
write!(f, "{:08X}:{:08X}", seg, off)
}
_ => unreachable!(),
}
}
}
impl PartialOrd for MemoryAddress {
fn partial_cmp(&self, other: &MemoryAddress) -> Option<cmp::Ordering> {
Some(other.cmp(self))
}
}
impl Ord for MemoryAddress {
fn cmp(&self, other: &MemoryAddress) -> cmp::Ordering {
other.value().cmp(&self.value())
}
}
impl MemoryAddress {
pub fn default_real() -> MemoryAddress {
MemoryAddress::RealSegmentOffset(0, 0)
}
pub fn value(self) -> u32 {
match self {
MemoryAddress::RealSegmentOffset(seg, off) => (u32::from(seg) << 4) + u32::from(off),
MemoryAddress::LongSegmentOffset(seg, off) => (u32::from(seg) << 16) + u32::from(off),
_ => unreachable!(),
}
}
pub fn segment(self) -> u16 {
match self {
MemoryAddress::RealSegmentOffset(seg, _) |
MemoryAddress::LongSegmentOffset(seg, _) => seg,
_ => unreachable!(),
}
}
pub fn offset(self) -> u16 {
match self {
MemoryAddress::RealSegmentOffset(_, off) |
MemoryAddress::LongSegmentOffset(_, off) => off,
_ => unreachable!(),
}
}
pub fn set_offset(&mut self, n: u16) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off = n,
_ => unreachable!(),
}
}
pub fn add_offset(&mut self, n: u16) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off += n,
_ => unreachable!(),
}
}
pub fn inc_u8(&mut self) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off += 1,
_ => unreachable!(),
}
}
pub fn inc_u16(&mut self) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off += 2,
_ => unreachable!(),
}
}
pub fn inc_u32(&mut self) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off += 4,
_ => unreachable!(),
}
}
pub fn inc_n(&mut self, n: u16) {
match *self {
MemoryAddress::RealSegmentOffset(_, ref mut off) |
MemoryAddress::LongSegmentOffset(_, ref mut off) => *off += n,
_ => unreachable!(),
}
}
}