#[cfg(test)]
#[path = "./flag_test.rs"]
mod flag_test;
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Flags {
pub carry: bool,
reserved1: bool,
pub parity: bool,
reserved3: bool,
pub adjust: bool,
reserved5: bool,
pub zero: bool,
pub sign: bool,
pub trap: bool,
pub interrupt: bool,
pub direction: bool,
pub overflow: bool,
iopl12: bool,
iopl13: bool,
nested_task: bool,
reserved15: bool,
}
pub const FLAG_CF: u16 = 0x0000_0001;
pub const FLAG_PF: u16 = 0x0000_0004;
pub const FLAG_AF: u16 = 0x0000_0010;
pub const FLAG_ZF: u16 = 0x0000_0040;
pub const FLAG_SF: u16 = 0x0000_0080;
pub const FLAG_TF: u16 = 0x0000_0100;
pub const FLAG_IF: u16 = 0x0000_0200;
pub const FLAG_DF: u16 = 0x0000_0400;
pub const FLAG_OF: u16 = 0x0000_0800;
static PARITY_LOOKUP: [u16; 256] = [
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF
];
impl Flags {
pub fn new() -> Self {
Flags {
carry: false,
reserved1: false,
parity: false,
reserved3: false,
adjust: false,
reserved5: false,
zero: false,
sign: false,
trap: false,
interrupt: false,
direction: false,
overflow: false,
iopl12: false,
iopl13: false,
nested_task: false,
reserved15: false,
}
}
pub fn new_from_u16(val: u16) -> Flags {
let mut f = Flags::new();
f.set_u16(val);
f
}
pub fn set_szp(&mut self, b: bool) {
self.sign = b;
self.zero = b;
self.parity = b;
}
pub fn set_sign_u8(&mut self, v: usize) {
self.sign = v & 0x80 != 0;
}
pub fn set_sign_u16(&mut self, v: usize) {
self.sign = v & 0x8000 != 0;
}
pub fn set_sign_u32(&mut self, v: usize) {
self.sign = v & 0x8000_0000 != 0;
}
pub fn set_parity(&mut self, v: usize) {
self.parity = PARITY_LOOKUP[v & 0xFF] != 0
}
pub fn set_zero_u8(&mut self, v: usize) {
self.zero = v.trailing_zeros() >= 8;
}
pub fn set_zero_u16(&mut self, v: usize) {
self.zero = v.trailing_zeros() >= 16;
}
pub fn set_zero_u32(&mut self, v: usize) {
self.zero = v.trailing_zeros() >= 32;
}
pub fn set_adjust(&mut self, res: usize, v1: usize, v2: usize) {
self.adjust = (res ^ (v1 ^ v2)) & 0x10 != 0;
}
pub fn set_overflow_add_u8(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (res ^ v1) & (res ^ v2) & 0x80 != 0;
}
pub fn set_overflow_add_u16(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (res ^ v1) & (res ^ v2) & 0x8000 != 0;
}
pub fn set_overflow_add_u32(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (res ^ v1) & (res ^ v2) & 0x8000_0000 != 0;
}
pub fn set_overflow_sub_u8(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (v2 ^ v1) & (v2 ^ res) & 0x80 != 0;
}
pub fn set_overflow_sub_u16(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (v2 ^ v1) & (v2 ^ res) & 0x8000 != 0;
}
pub fn set_overflow_sub_u32(&mut self, res: usize, v1: usize, v2: usize) {
self.overflow = (v2 ^ v1) & (v2 ^ res) & 0x8000_0000 != 0;
}
pub fn set_carry_u8(&mut self, res: usize) {
self.carry = res & 0x100 != 0;
}
pub fn set_carry_u16(&mut self, res: usize) {
self.carry = res & 0x1_0000 != 0;
}
pub fn set_carry_u32(&mut self, res: usize) {
self.carry = res & 0x1_0000_0000 != 0;
}
pub fn set_u16(&mut self, val: u16) {
self.carry = val & 0x1 != 0;
self.parity = val & 0x4 != 0;
self.adjust = val & 0x10 != 0;
self.zero = val & 0x40 != 0;
self.sign = val & 0x80 != 0;
self.trap = val & 0x100 != 0;
self.direction = val & 0x400 != 0;
self.overflow = val & 0x800 != 0;
}
pub fn carry_val(&self) -> usize {
if self.carry {
1
} else {
0
}
}
pub fn carry_numeric(&self) -> String {
format!("{}", if self.carry {
1
} else {
0
})
}
pub fn zero_numeric(&self) -> String {
format!("{}", if self.zero {
1
} else {
0
})
}
pub fn sign_numeric(&self) -> String {
format!("{}", if self.sign { 1 } else { 0 })
}
pub fn overflow_numeric(&self) -> String {
format!("{}", if self.overflow {
1
} else {
0
})
}
pub fn adjust_numeric(&self) -> String {
format!("{}", if self.adjust {
1
} else {
0
})
}
pub fn parity_numeric(&self) -> String {
format!("{}", if self.parity {
1
} else {
0
})
}
pub fn direction_numeric(&self) -> String {
format!("{}", if self.direction {
1
} else {
0
})
}
pub fn interrupt_numeric(&self) -> String {
format!("{}", if self.interrupt {
1
} else {
0
})
}
pub fn u16(&self) -> u16 {
let mut val = 0 as u16;
if self.carry {
val |= 1;
}
if self.reserved1 {
val |= 1 << 1;
}
if self.parity {
val |= 1 << 2;
}
if self.adjust {
val |= 1 << 4;
}
if self.zero {
val |= 1 << 6;
}
if self.sign {
val |= 1 << 7;
}
if self.trap {
val |= 1 << 8;
}
if self.interrupt {
val |= 1 << 9;
}
if self.direction {
val |= 1 << 10;
}
if self.overflow {
val |= 1 << 11;
}
if self.iopl12 {
val |= 1 << 12;
}
if self.iopl13 {
val |= 1 << 13;
}
if self.nested_task {
val |= 1 << 14;
}
val
}
}