Skip to content
Snippets Groups Projects
  • Geo Ster's avatar
    a6679fdc
    Refactor and fix IOP interrupts · a6679fdc
    Geo Ster authored
    This commit fixes some issues preventing IOP interrupts from working
    correctly while also seperating them into a seperate class for convenience.
    
    * Previously the pending flag was written to the first bit of cause.IP, which
    while correct was flawed. To understandw why let's look at how interrupts
    get triggered. COP0 has 2 8 bit masks, IP (cause) and Im (status). On both
    of these registers the first 2 bits are ignored because they are used for
    software interrupts which are unsupported on the IOP. However while Im was
    including these unused bits, IP did not thus causing mistaken comparions.
    Below is a diagram that shows the issue. IP was bits 10-15 while Im was bits
    8-15. Comparing diffent ranges like this doesn't work.
    
    Cause: ... 00|111111| ...
    Status: ... |00111111| ...
    
    The fix was to make IP point to 8-15 range and adjust the writing
    mechanism in the INTR::interrupt_pending function.
    
    * In addition the usage of >= instead of == in the timers, caused
    a bug where the timer would continiously send interrupts after reaching
    target which is not the intended behaviour. Fix that as well.
    a6679fdc
    History
    Refactor and fix IOP interrupts
    Geo Ster authored
    This commit fixes some issues preventing IOP interrupts from working
    correctly while also seperating them into a seperate class for convenience.
    
    * Previously the pending flag was written to the first bit of cause.IP, which
    while correct was flawed. To understandw why let's look at how interrupts
    get triggered. COP0 has 2 8 bit masks, IP (cause) and Im (status). On both
    of these registers the first 2 bits are ignored because they are used for
    software interrupts which are unsupported on the IOP. However while Im was
    including these unused bits, IP did not thus causing mistaken comparions.
    Below is a diagram that shows the issue. IP was bits 10-15 while Im was bits
    8-15. Comparing diffent ranges like this doesn't work.
    
    Cause: ... 00|111111| ...
    Status: ... |00111111| ...
    
    The fix was to make IP point to 8-15 range and adjust the writing
    mechanism in the INTR::interrupt_pending function.
    
    * In addition the usage of >= instead of == in the timers, caused
    a bug where the timer would continiously send interrupts after reaching
    target which is not the intended behaviour. Fix that as well.