pub trait Cpu:
Clone
+ Default
+ PartialEq
+ Eq {
Show 49 methods
// Required methods
fn reset(&mut self);
fn get_pc(&self) -> u16;
fn set_pc(&mut self, pc: u16);
fn get_sp(&self) -> u16;
fn set_sp(&mut self, sp: u16);
fn get_acc(&self) -> u8;
fn set_acc(&mut self, val: u8);
fn get_flags(&self) -> CpuFlags;
fn set_flags(&mut self, flags: CpuFlags);
fn inc_r(&mut self);
fn add_r(&mut self, delta: i32);
fn get_r(&self) -> u8;
fn set_r(&mut self, r: u8);
fn get_i(&self) -> u8;
fn set_i(&mut self, i: u8);
fn get_ir(&self) -> u16;
fn get_iffs(&self) -> (bool, bool);
fn set_iffs(&mut self, iff1: bool, iff2: bool);
fn halt(&mut self);
fn is_halt(&self) -> bool;
fn get_im(&self) -> InterruptMode;
fn set_im(&mut self, im: InterruptMode);
fn ex_af_af(&mut self);
fn exx(&mut self);
fn get_reg(&self, reg: Reg8, prefix: Option<Prefix>) -> u8;
fn set_reg(&mut self, dst: Reg8, prefix: Option<Prefix>, val: u8);
fn get_reg2(&self, src: StkReg16) -> (u8, u8);
fn get_alt_reg2(&self, src: StkReg16) -> (u8, u8);
fn get_reg16(&self, src: StkReg16) -> u16;
fn get_alt_reg16(&self, src: StkReg16) -> u16;
fn set_reg2(&mut self, src: StkReg16, hi: u8, lo: u8);
fn set_reg16(&mut self, src: StkReg16, val: u16);
fn get_index2(&self, prefix: Prefix) -> (u8, u8);
fn get_index16(&self, prefix: Prefix) -> u16;
fn set_index2(&mut self, prefix: Prefix, hi: u8, lo: u8);
fn set_index16(&mut self, prefix: Prefix, val: u16);
fn is_irq_allowed(&self) -> bool;
fn is_nmi_allowed(&self) -> bool;
fn restore_iff1(&mut self);
fn disable_interrupts(&mut self);
fn enable_interrupts(&mut self);
fn is_after_ei(&self) -> bool;
fn is_after_prefix(&self) -> bool;
fn get_prefix(&self) -> Option<Prefix>;
fn irq<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
) -> Option<Result<M::WrIoBreak, M::RetiBreak>>
where M: Memory<Timestamp = T::Timestamp> + Io<Timestamp = T::Timestamp>,
T: Clock,
F: FnOnce(CpuDebug);
fn nmi<M, T>(&mut self, control: &mut M, tsc: &mut T) -> bool
where M: Memory<Timestamp = T::Timestamp> + Io<Timestamp = T::Timestamp>,
T: Clock;
fn execute_instruction<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
code: u8,
) -> Result<M::WrIoBreak, M::RetiBreak>
where M: Memory<Timestamp = T::Timestamp> + Io<Timestamp = T::Timestamp>,
T: Clock,
F: FnOnce(CpuDebug);
fn execute_next<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
) -> Result<M::WrIoBreak, M::RetiBreak>
where M: Memory<Timestamp = T::Timestamp> + Io<Timestamp = T::Timestamp>,
T: Clock,
F: FnOnce(CpuDebug);
fn execute_with_limit<M, T>(
&mut self,
control: &mut M,
tsc: &mut T,
limit: T::Limit,
) -> Result<M::WrIoBreak, M::RetiBreak>
where M: Memory<Timestamp = T::Timestamp> + Io<Timestamp = T::Timestamp>,
T: Clock;
}
Expand description
The Cpu trait provides means to execute and debug machine code or change the state of self
at User’s will.
Required Methods§
Sourcefn add_r(&mut self, delta: i32)
fn add_r(&mut self, delta: i32)
Adds the arbitrary value to the memory refresh counter. This can be used to emulate the Cpu in the HALT state without executing the busy loop.
Sourcefn halt(&mut self)
fn halt(&mut self)
Forces Cpu to enter the HALT state. This doesn’t involve Clock and happens instantly.
This also can be done by executing HALT
instruction with Cpu::execute_instruction.
Sourcefn get_im(&self) -> InterruptMode
fn get_im(&self) -> InterruptMode
Returns the current interrupt mode.
Sourcefn set_im(&mut self, im: InterruptMode)
fn set_im(&mut self, im: InterruptMode)
Sets the interrupt mode.
Sourcefn exx(&mut self)
fn exx(&mut self)
Swaps the BC
, DE
and HL
registers with their alternative counterparts BC'
, DE'
and HL'
.
Sourcefn get_reg(&self, reg: Reg8, prefix: Option<Prefix>) -> u8
fn get_reg(&self, reg: Reg8, prefix: Option<Prefix>) -> u8
Returns the content of the selected 8-bit register.
The reg
argument specifies the register. If the prefix
argument is
one of Prefix::Xdd or Prefix::Yfd and the reg
is Reg8::H or Reg8::L
the content of the IXh
, IXl
or IYh
, IYl
will be returned instead.
Sourcefn set_reg(&mut self, dst: Reg8, prefix: Option<Prefix>, val: u8)
fn set_reg(&mut self, dst: Reg8, prefix: Option<Prefix>, val: u8)
Sets the content of the selected 8-bit register.
The reg
argument specifies the register. If the prefix
argument is
one of Prefix::Xdd or Prefix::Yfd and the reg
is Reg8::H or Reg8::L
the content of the IXh
, IXl
or IYh
, IYl
will be set instead.
Sourcefn get_reg2(&self, src: StkReg16) -> (u8, u8)
fn get_reg2(&self, src: StkReg16) -> (u8, u8)
Returns the content of the selected pair of registers as a tuple of 8-bit unsigned integers.
E.g. for StkReg16::BC the content of (B, C)
will be returned.
Sourcefn get_alt_reg2(&self, src: StkReg16) -> (u8, u8)
fn get_alt_reg2(&self, src: StkReg16) -> (u8, u8)
Returns the content of the selected pair of alternative registers as a tuple of 8-bit unsigned integers.
E.g. for StkReg16::AF the content of (A', F')
will be returned.
Sourcefn get_reg16(&self, src: StkReg16) -> u16
fn get_reg16(&self, src: StkReg16) -> u16
Returns the content of the selected pair of registers as an unsigned 16-bit integer.
Sourcefn get_alt_reg16(&self, src: StkReg16) -> u16
fn get_alt_reg16(&self, src: StkReg16) -> u16
Returns the content of the selected pair of alternative registers as an unsigned 16-bit integer.
Sourcefn set_reg2(&mut self, src: StkReg16, hi: u8, lo: u8)
fn set_reg2(&mut self, src: StkReg16, hi: u8, lo: u8)
Sets the content of the selected pair of registers.
E.g. for StkReg16::BC register B
will be set to hi
and C
to lo
.
Sourcefn set_reg16(&mut self, src: StkReg16, val: u16)
fn set_reg16(&mut self, src: StkReg16, val: u16)
Sets the content of the selected pair of registers as an unsigned 16-bit integer.
Sourcefn get_index2(&self, prefix: Prefix) -> (u8, u8)
fn get_index2(&self, prefix: Prefix) -> (u8, u8)
Returns the content of one of the index registers as a tuple of 8-bit unsigned integers.
Depending on prefix
this will be:
- Prefix::Xdd -
(IXh, IXl)
- Prefix::Yfd -
(IYh, IYl)
Sourcefn get_index16(&self, prefix: Prefix) -> u16
fn get_index16(&self, prefix: Prefix) -> u16
Returns the content of one of the index registers as a 16-bit unsigned integer.
Depending on prefix
this will be:
- Prefix::Xdd -
IX
- Prefix::Yfd -
IY
Sourcefn set_index2(&mut self, prefix: Prefix, hi: u8, lo: u8)
fn set_index2(&mut self, prefix: Prefix, hi: u8, lo: u8)
Sets the content of one of the index registers.
Depending on prefix
this will be:
- Prefix::Xdd -
IXh=hi, IXl=lo
- Prefix::Yfd -
IYh=hi, IYl=lo
Sourcefn set_index16(&mut self, prefix: Prefix, val: u16)
fn set_index16(&mut self, prefix: Prefix, val: u16)
Sets the content of one of the index registers as a 16-bit unsigned integer.
Depending on prefix
this will be:
- Prefix::Xdd -
IX
- Prefix::Yfd -
IY
Sourcefn is_irq_allowed(&self) -> bool
fn is_irq_allowed(&self) -> bool
Returns true if the Cpu will accept the interrupt request before executing the next opcode.
Sourcefn is_nmi_allowed(&self) -> bool
fn is_nmi_allowed(&self) -> bool
Returns true if the Cpu will accept the non-maskable interrupt before executing the next opcode.
Sourcefn restore_iff1(&mut self)
fn restore_iff1(&mut self)
Restores the content of the interrupt flip-flop 1
from the content of the interrupt flip-flop 2
.
This is what RETN
instruction usually does.
Sourcefn disable_interrupts(&mut self)
fn disable_interrupts(&mut self)
Disables the maskable interrupts by resetting both interrupt flip-flops
to Off.
This is what DI
instruction usually does.
Sourcefn enable_interrupts(&mut self)
fn enable_interrupts(&mut self)
Enabes the maskable interrupts by setting both interrupt flip-flops
to On.
Prevents the interrupts to be allowed before the next command.
This is what EI
instruction usually does.
Sourcefn is_after_ei(&self) -> bool
fn is_after_ei(&self) -> bool
Returns true
if the last command executed was EI
.
Sourcefn is_after_prefix(&self) -> bool
fn is_after_prefix(&self) -> bool
Returns true
if the last command executed was a 0xDD
or a 0xFD
prefix.
See Cpu::execute_instruction for more information.
Sourcefn get_prefix(&self) -> Option<Prefix>
fn get_prefix(&self) -> Option<Prefix>
Returns the prefix value after executing the last command.
See Cpu::execute_instruction for more information.
Sourcefn irq<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
) -> Option<Result<M::WrIoBreak, M::RetiBreak>>
fn irq<M, T, F>( &mut self, control: &mut M, tsc: &mut T, debug: Option<F>, ) -> Option<Result<M::WrIoBreak, M::RetiBreak>>
Requests a maskable interrupt.
This is the alternative method to invoke the maskable interrupt. Usually while instructions are being executed the Cpu checks via Io::is_irq method if the interrrupt from any device is being requested.
Returns None
if the interrupt could not be accepted at this time. In this instance the method performs
no operation.
Returns Some(Ok(()))
if an interrupt was accepted and no break was requested by the executed instruction.
In this instance at least one instruction will be executed. Depending on the interrupt mode this would be:
- InterruptMode::Mode0 an instruction provided via Io::irq_data.
- InterruptMode::Mode1 a
RST 38h
instruction. - InterruptMode::Mode2 a hypothetical
PUSH pc + JP <vector address>
instruction. A debugger will see theJP
command in this instance.
The Clock is advanced by the IRQ:6
cycle + optional wait states + cycles specific to the executed
instruction (minus the M1:4
cycle).
Some(Err(BreakCause))
indicates that an instruction requested a break. Currently this may be possible
in the interrupt mode 0 when the HALT
, OUT
or RETI
instruction was executed and the Io::write_io
or Io::reti requested to break the execution.
See Cpu::execute_instruction for the debug
argument description.
§Note
If the interrupt is being accepted this method resets the HALT
state before everything else.
Sourcefn nmi<M, T>(&mut self, control: &mut M, tsc: &mut T) -> bool
fn nmi<M, T>(&mut self, control: &mut M, tsc: &mut T) -> bool
Attempts to trigger a non-maskable interrupt.
Returns false
if the interrupt could not be accepted at this time. The non-maskable interrupt
is not being accepted in some situations, e.g. right after executing the EI
instruction or after
one of the 0xDD
and 0xFD
opcode prefixes. In this instance the method performs no operation.
Returns true
on success. In this instance no instruction will be executed but the program counter
will be set to 0x0066
and the previous program counter will be pushed on the machine stack.
The interrupt flip-flop 1
is being set to false
, while preserving the value of iff 2
and the
Clock advances according to the Z80 NMI cycles: M1:4 + IR:1 + SP-1:3 + SP-2:3
.
§Note
If the interrupt is being accepted this method resets the HALT
state before everything else.
Sourcefn execute_instruction<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
code: u8,
) -> Result<M::WrIoBreak, M::RetiBreak>
fn execute_instruction<M, T, F>( &mut self, control: &mut M, tsc: &mut T, debug: Option<F>, code: u8, ) -> Result<M::WrIoBreak, M::RetiBreak>
Executes a single instruction given as code
. If the instruction is a first byte of the multi-byte
instruction the rest of the instruction body will be fetched via calls to Memory::read_opcode.
The return value Err(BreakCause)
indicates that an instruction requested a break.
Currently this may be possible when the HALT
instruction was executed or when the OUT
family
instruction was executed and the Io::write_io requested a break or the RETI
instruction was
executed and the Io::reti requested a break. See also BreakCause.
If debug
argument is Some(F)
, a closure F
may be called with CpuDebug argument during the
instruction execution. It won’t be called if code
is one of the 0xDD
or 0xFD
prefixes.
There is no limit of how many of these prefixes can be present before an actual instruction, so the execution is finished each time one of them is being encountered to prevent the overfeeding the Clock with a huge amount of T-states and to allow for the better synchronization with the emulated side effects. The user can check with Cpu::is_after_prefix method if this is the case after calling one of the execution methods.
§Note
This method resets the HALT
state and after EI
state before the instruction is being executed.
Sourcefn execute_next<M, T, F>(
&mut self,
control: &mut M,
tsc: &mut T,
debug: Option<F>,
) -> Result<M::WrIoBreak, M::RetiBreak>
fn execute_next<M, T, F>( &mut self, control: &mut M, tsc: &mut T, debug: Option<F>, ) -> Result<M::WrIoBreak, M::RetiBreak>
Executes the next instruction present in the Memory at the program counter fetched via Memory::read_opcode.
If interrupts are allowed, before fetching the instruction, checks if the interrupt request is present via Io::is_irq and enters the interrupted state, instead of fetching and executing the next instruction.
If the Cpu is in the HALT
state, increases the memory refresh register and advances the Clock only.
If debug
closure is given, it will not be called in this instance.
See Cpu::execute_instruction and Cpu::irq for the returned value and debug
argument descriptions.
Sourcefn execute_with_limit<M, T>(
&mut self,
control: &mut M,
tsc: &mut T,
limit: T::Limit,
) -> Result<M::WrIoBreak, M::RetiBreak>
fn execute_with_limit<M, T>( &mut self, control: &mut M, tsc: &mut T, limit: T::Limit, ) -> Result<M::WrIoBreak, M::RetiBreak>
Executes instructions until Clock reaches the given limit
or when other conditions are met.
Returns Ok(())
only when limit
has been reached and the last executed instruction didn’t request a break.
Returns Err(BreakCause)
when:
- The
HALT
instruction was encountered. This also implies that the Cpu has entered theHALT
state. - An instruction requested a break via Io::write_io or Io::reti.
See also BreakCause.
When interrupts are enabled, before fetching each next instruction, this method checks if the interrupt has been requested via Io::is_irq and executes the interrupt routine without breaking the execution.
When called while the Cpu was already in the HALT
state, increases the memory refresh register and
advances the Clock until the limit
has been reached. If interrupts were enabled and an interrupt
was requested via Io::is_irq, the HALT
state is being reset and the regular execution of commands
will be resumed.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.