mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-21 19:30:52 +00:00
Implemented RLD and RRD instructions for Z80
This commit is contained in:
parent
f3d1fd0ae2
commit
5ec2fe4157
@ -94,6 +94,7 @@ impl Z80 {
|
||||
|
||||
pub fn decode_next(&mut self) -> Result<(), Error> {
|
||||
self.decoder.decode_at(&mut self.port, self.current_clock, self.state.pc)?;
|
||||
self.increment_refresh(self.decoder.end.saturating_sub(self.decoder.start) as u8);
|
||||
self.state.pc = self.decoder.end;
|
||||
Ok(())
|
||||
}
|
||||
@ -249,9 +250,9 @@ impl Z80 {
|
||||
Instruction::EXsp(regpair) => {
|
||||
let reg_value = self.get_register_pair_value(regpair);
|
||||
let sp = self.get_register_pair_value(RegisterPair::SP);
|
||||
let sp_value = self.port.read_leu16(self.current_clock, sp as Address)?;
|
||||
let sp_value = self.read_port_u16(sp)?;
|
||||
self.set_register_pair_value(regpair, sp_value);
|
||||
self.port.write_leu16(self.current_clock, sp as Address, reg_value)?;
|
||||
self.write_port_u16(sp, reg_value)?;
|
||||
},
|
||||
Instruction::HALT => {
|
||||
self.state.status = Status::Halted;
|
||||
@ -307,7 +308,6 @@ impl Z80 {
|
||||
},
|
||||
Instruction::JPIndirect(regpair) => {
|
||||
let value = self.get_register_pair_value(regpair);
|
||||
//let addr = self.port.read_leu16(value as Address)?;
|
||||
self.state.pc = value;
|
||||
},
|
||||
Instruction::JPcc(cond, addr) => {
|
||||
@ -334,14 +334,19 @@ impl Z80 {
|
||||
};
|
||||
|
||||
match dir {
|
||||
Direction::FromAcc => { *addr = self.state.reg[Register::A as usize]; },
|
||||
Direction::ToAcc => { self.state.reg[Register::A as usize] = *addr; },
|
||||
Direction::FromAcc => {
|
||||
*addr = self.state.reg[Register::A as usize];
|
||||
},
|
||||
Direction::ToAcc => {
|
||||
self.state.reg[Register::A as usize] = *addr;
|
||||
let value = self.state.reg[Register::A as usize];
|
||||
self.set_numeric_flags(value as u16, Size::Byte);
|
||||
self.set_flag(Flags::Parity, self.state.iff2);
|
||||
self.set_flag(Flags::AddSubtract, false);
|
||||
self.set_flag(Flags::HalfCarry, false);
|
||||
},
|
||||
}
|
||||
let value = self.state.reg[Register::A as usize];
|
||||
self.set_numeric_flags(value as u16, Size::Byte);
|
||||
self.set_flag(Flags::Parity, self.state.iff2);
|
||||
self.set_flag(Flags::AddSubtract, false);
|
||||
self.set_flag(Flags::HalfCarry, false);
|
||||
|
||||
}
|
||||
Instruction::LDD | Instruction::LDDR | Instruction::LDI | Instruction::LDIR => {
|
||||
let diff = if self.decoder.instruction == Instruction::LDI || self.decoder.instruction == Instruction::LDIR {
|
||||
@ -468,8 +473,22 @@ impl Z80 {
|
||||
self.set_flag(Flags::Carry, out_bit);
|
||||
self.set_register_value(Register::A, result);
|
||||
},
|
||||
//Instruction::RLD => {
|
||||
//},
|
||||
Instruction::RLD => {
|
||||
let a = self.get_register_value(Register::A);
|
||||
let mem = self.get_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL))? as u8;
|
||||
|
||||
let lower_a = a & 0x0F;
|
||||
let a = (a & 0xF0) | (mem >> 4);
|
||||
let mem = (mem << 4) | lower_a;
|
||||
|
||||
self.set_register_value(Register::A, a);
|
||||
self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), mem as u16)?;
|
||||
|
||||
self.set_numeric_flags(a as u16, Size::Byte);
|
||||
self.set_parity_flags(a);
|
||||
self.set_flag(Flags::HalfCarry, false);
|
||||
self.set_flag(Flags::AddSubtract, false);
|
||||
},
|
||||
Instruction::RR(target, opt_copy) => {
|
||||
let value = self.get_target_value(target)?;
|
||||
let (result, out_bit) = self.rotate_right(value, RotateType::Bit9);
|
||||
@ -504,8 +523,22 @@ impl Z80 {
|
||||
self.set_flag(Flags::Carry, out_bit);
|
||||
self.set_register_value(Register::A, result);
|
||||
},
|
||||
//Instruction::RRD => {
|
||||
//},
|
||||
Instruction::RRD => {
|
||||
let a = self.get_register_value(Register::A);
|
||||
let mem = self.get_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL))? as u8;
|
||||
|
||||
let lower_mem = mem & 0x0F;
|
||||
let mem = (a << 4) | (mem >> 4);
|
||||
let a = (a & 0xF0) | lower_mem;
|
||||
|
||||
self.set_register_value(Register::A, a);
|
||||
self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), mem as u16)?;
|
||||
|
||||
self.set_numeric_flags(a as u16, Size::Byte);
|
||||
self.set_parity_flags(a);
|
||||
self.set_flag(Flags::HalfCarry, false);
|
||||
self.set_flag(Flags::AddSubtract, false);
|
||||
},
|
||||
Instruction::RST(addr) => {
|
||||
self.push_word(self.decoder.end)?;
|
||||
self.state.pc = addr as u16;
|
||||
@ -652,17 +685,17 @@ impl Z80 {
|
||||
|
||||
fn push_word(&mut self, value: u16) -> Result<(), Error> {
|
||||
self.state.sp = self.state.sp.wrapping_sub(1);
|
||||
self.port.write_u8(self.current_clock, self.state.sp as Address, (value >> 8) as u8)?;
|
||||
self.write_port_u8(self.state.sp, (value >> 8) as u8)?;
|
||||
self.state.sp = self.state.sp.wrapping_sub(1);
|
||||
self.port.write_u8(self.current_clock, self.state.sp as Address, (value & 0x00FF) as u8)?;
|
||||
self.write_port_u8(self.state.sp, (value & 0x00FF) as u8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pop_word(&mut self) -> Result<u16, Error> {
|
||||
let mut value;
|
||||
value = self.port.read_u8(self.current_clock, self.state.sp as Address)? as u16;
|
||||
value = self.read_port_u8(self.state.sp)? as u16;
|
||||
self.state.sp = self.state.sp.wrapping_add(1);
|
||||
value |= (self.port.read_u8(self.current_clock, self.state.sp as Address)? as u16) << 8;
|
||||
value |= (self.read_port_u8(self.state.sp)? as u16) << 8;
|
||||
self.state.sp = self.state.sp.wrapping_add(1);
|
||||
Ok(value)
|
||||
}
|
||||
@ -674,21 +707,21 @@ impl Z80 {
|
||||
LoadTarget::DirectRegWord(regpair) => self.get_register_pair_value(regpair),
|
||||
LoadTarget::IndirectRegByte(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.read_u8(self.current_clock, addr as Address)? as u16
|
||||
self.read_port_u8(addr)? as u16
|
||||
},
|
||||
LoadTarget::IndirectOffsetByte(index_reg, offset) => {
|
||||
let addr = self.get_index_register_value(index_reg);
|
||||
self.port.read_u8(self.current_clock, ((addr as i16).wrapping_add(offset as i16)) as Address)? as u16
|
||||
self.read_port_u8((addr as i16).wrapping_add(offset as i16) as u16)? as u16
|
||||
},
|
||||
LoadTarget::IndirectRegWord(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.read_leu16(self.current_clock, addr as Address)?
|
||||
self.read_port_u16(addr)?
|
||||
},
|
||||
LoadTarget::IndirectByte(addr) => {
|
||||
self.port.read_u8(self.current_clock, addr as Address)? as u16
|
||||
self.read_port_u8(addr)? as u16
|
||||
},
|
||||
LoadTarget::IndirectWord(addr) => {
|
||||
self.port.read_leu16(self.current_clock, addr as Address)?
|
||||
self.read_port_u16(addr)?
|
||||
},
|
||||
LoadTarget::ImmediateByte(data) => data as u16,
|
||||
LoadTarget::ImmediateWord(data) => data,
|
||||
@ -704,21 +737,21 @@ impl Z80 {
|
||||
LoadTarget::DirectRegWord(regpair) => self.set_register_pair_value(regpair, value),
|
||||
LoadTarget::IndirectRegByte(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.write_u8(self.current_clock, addr as Address, value as u8)?;
|
||||
self.write_port_u8(addr, value as u8)?;
|
||||
},
|
||||
LoadTarget::IndirectOffsetByte(index_reg, offset) => {
|
||||
let addr = self.get_index_register_value(index_reg);
|
||||
self.port.write_u8(self.current_clock, ((addr as i16).wrapping_add(offset as i16)) as Address, value as u8)?;
|
||||
self.write_port_u8((addr as i16).wrapping_add(offset as i16) as u16, value as u8)?;
|
||||
},
|
||||
LoadTarget::IndirectRegWord(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.write_leu16(self.current_clock, addr as Address, value)?;
|
||||
self.write_port_u16(addr, value)?;
|
||||
},
|
||||
LoadTarget::IndirectByte(addr) => {
|
||||
self.port.write_u8(self.current_clock, addr as Address, value as u8)?;
|
||||
self.write_port_u8(addr, value as u8)?;
|
||||
},
|
||||
LoadTarget::IndirectWord(addr) => {
|
||||
self.port.write_leu16(self.current_clock, addr as Address, value)?;
|
||||
self.write_port_u16(addr, value)?;
|
||||
},
|
||||
_ => panic!("Unsupported LoadTarget for set: {:?}", target),
|
||||
}
|
||||
@ -731,11 +764,11 @@ impl Z80 {
|
||||
Target::DirectRegHalf(reg) => Ok(self.get_index_register_half_value(reg)),
|
||||
Target::IndirectReg(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
Ok(self.port.read_u8(self.current_clock, addr as Address)?)
|
||||
Ok(self.read_port_u8(addr)?)
|
||||
},
|
||||
Target::IndirectOffset(reg, offset) => {
|
||||
let addr = self.get_index_register_value(reg).wrapping_add_signed(offset as i16);
|
||||
Ok(self.port.read_u8(self.current_clock, addr as Address)?)
|
||||
Ok(self.read_port_u8(addr)?)
|
||||
},
|
||||
Target::Immediate(data) => Ok(data),
|
||||
}
|
||||
@ -747,17 +780,41 @@ impl Z80 {
|
||||
Target::DirectRegHalf(reg) => self.set_index_register_half_value(reg, value),
|
||||
Target::IndirectReg(regpair) => {
|
||||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.write_u8(self.current_clock, addr as Address, value)?;
|
||||
self.write_port_u8(addr, value)?;
|
||||
},
|
||||
Target::IndirectOffset(reg, offset) => {
|
||||
let addr = self.get_index_register_value(reg).wrapping_add_signed(offset as i16);
|
||||
self.port.write_u8(self.current_clock, addr as Address, value)?;
|
||||
self.write_port_u8(addr, value)?;
|
||||
},
|
||||
_ => panic!("Unsupported LoadTarget for set"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn increment_refresh(&mut self, count: u8) {
|
||||
self.state.r = (self.state.r & 0x80) | ((self.state.r + count) & 0x7F);
|
||||
}
|
||||
|
||||
fn read_port_u8(&mut self, addr: u16) -> Result<u8, Error> {
|
||||
self.increment_refresh(1);
|
||||
self.port.read_u8(self.current_clock, addr as Address)
|
||||
}
|
||||
|
||||
fn write_port_u8(&mut self, addr: u16, value: u8) -> Result<(), Error> {
|
||||
self.increment_refresh(1);
|
||||
self.port.write_u8(self.current_clock, addr as Address, value)
|
||||
}
|
||||
|
||||
fn read_port_u16(&mut self, addr: u16) -> Result<u16, Error> {
|
||||
self.increment_refresh(2);
|
||||
self.port.read_leu16(self.current_clock, addr as Address)
|
||||
}
|
||||
|
||||
fn write_port_u16(&mut self, addr: u16, value: u16) -> Result<(), Error> {
|
||||
self.increment_refresh(2);
|
||||
self.port.write_leu16(self.current_clock, addr as Address, value)
|
||||
}
|
||||
|
||||
fn get_ioport_value(&mut self, upper: u8, lower: u8) -> Result<u8, Error> {
|
||||
let addr = ((upper as Address) << 8) | (lower as Address);
|
||||
if let Some(io) = self.ioport.as_mut() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
Last run on 2023-05-13 at commit e61e0cfe8f79c42b3ec232ddb3c97e63dbb40864
|
||||
Last run on 2023-05-13 at commit f3d1fd0ae2410a164c92150cc3caa0f525cbb4b7
|
||||
|
||||
00.json completed, all passed!
|
||||
01.json completed, all passed!
|
||||
@ -524,7 +524,7 @@ ed 43.json completed, all passed!
|
||||
ed 44.json completed, all passed!
|
||||
ed 45.json completed, all passed!
|
||||
ed 46.json completed, all passed!
|
||||
ed 47.json completed: 34 passed, 966 FAILED
|
||||
ed 47.json completed, all passed!
|
||||
ed 48.json completed, all passed!
|
||||
ed 49.json completed, all passed!
|
||||
ed 4a.json completed, all passed!
|
||||
@ -532,7 +532,7 @@ ed 4b.json completed, all passed!
|
||||
ed 4c.json completed, all passed!
|
||||
ed 4d.json completed, all passed!
|
||||
ed 4e.json completed, all passed!
|
||||
ed 4f.json completed: 36 passed, 964 FAILED
|
||||
ed 4f.json completed, all passed!
|
||||
ed 50.json completed, all passed!
|
||||
ed 51.json completed, all passed!
|
||||
ed 52.json completed, all passed!
|
||||
@ -548,21 +548,21 @@ ed 5b.json completed, all passed!
|
||||
ed 5c.json completed, all passed!
|
||||
ed 5d.json completed, all passed!
|
||||
ed 5e.json completed, all passed!
|
||||
ed 5f.json completed: 0 passed, 1000 FAILED
|
||||
ed 5f.json completed, all passed!
|
||||
ed 60.json completed, all passed!
|
||||
ed 61.json completed, all passed!
|
||||
ed 62.json completed, all passed!
|
||||
ed 64.json completed, all passed!
|
||||
ed 65.json completed, all passed!
|
||||
ed 66.json completed, all passed!
|
||||
ed 67.json completed: 0 passed, 1000 FAILED
|
||||
ed 67.json completed, all passed!
|
||||
ed 68.json completed, all passed!
|
||||
ed 69.json completed, all passed!
|
||||
ed 6a.json completed, all passed!
|
||||
ed 6c.json completed, all passed!
|
||||
ed 6d.json completed, all passed!
|
||||
ed 6e.json completed, all passed!
|
||||
ed 6f.json completed: 0 passed, 1000 FAILED
|
||||
ed 6f.json completed, all passed!
|
||||
ed 72.json completed, all passed!
|
||||
ed 73.json completed, all passed!
|
||||
ed 74.json completed, all passed!
|
||||
@ -643,5 +643,5 @@ fd f9.json completed, all passed!
|
||||
fe.json completed, all passed!
|
||||
ff.json completed, all passed!
|
||||
|
||||
passed: 624068, failed: 17932, total 97%
|
||||
passed: 628998, failed: 13002, total 98%
|
||||
completed in 0m 31s
|
||||
|
Loading…
Reference in New Issue
Block a user