Class: PSX::COP0
- Inherits:
-
Object
- Object
- PSX::COP0
- Defined in:
- lib/psx/cop0.rb
Overview
Coprocessor 0 - System Control Handles exceptions, interrupts, and memory management
Constant Summary collapse
- BPC =
Register indices
3- BDA =
Breakpoint on execute
5- JUMPDEST =
Breakpoint on data access
6- DCIC =
Jump destination (for branch delay debugging)
7- BADVADDR =
Breakpoint control
8- BDAM =
Bad virtual address
9- BPCM =
Data access breakpoint mask
11- SR =
Execute breakpoint mask
12- CAUSE =
Status register
13- EPC =
Exception cause
14- PRID =
Exception program counter
15- SR_IEC =
Status register bits
0x01- SR_KUC =
Interrupt Enable Current
0x02- SR_IEP =
Kernel/User Mode Current (0=kernel)
0x04- SR_KUP =
Interrupt Enable Previous
0x08- SR_IEO =
Kernel/User Mode Previous
0x10- SR_KUO =
Interrupt Enable Old
0x20- SR_IM =
Kernel/User Mode Old
0xFF00- SR_ISC =
Interrupt Mask (bits 8-15)
0x1_0000- SR_SWC =
Isolate Cache
0x2_0000- SR_PZ =
Swap Caches
0x4_0000- SR_CM =
Parity Zero
0x8_0000- SR_PE =
Cache Miss
0x10_0000- SR_TS =
Parity Error
0x20_0000- SR_BEV =
TLB Shutdown
0x40_0000- SR_RE =
Boot Exception Vectors
0x200_0000- SR_CU0 =
Reverse Endianness
0x1000_0000- SR_CU1 =
COP0 Enable
0x2000_0000- SR_CU2 =
COP1 Enable (no FPU on PSX, but enable bit exists)
0x4000_0000- SR_CU3 =
COP2 (GTE) Enable
0x8000_0000- EXC_INT =
Exception codes (for CAUSE register bits 2-6)
0x00- EXC_MOD =
Interrupt
0x01- EXC_TLBL =
TLB modification
0x02- EXC_TLBS =
TLB load
0x03- EXC_ADEL =
TLB store
0x04- EXC_ADES =
Address error (load/fetch)
0x05- EXC_IBE =
Address error (store)
0x06- EXC_DBE =
Bus error (instruction fetch)
0x07- EXC_SYS =
Bus error (data load/store)
0x08- EXC_BP =
Syscall
0x09- EXC_RI =
Breakpoint
0x0A- EXC_CPU =
Reserved instruction
0x0B- EXC_OV =
Coprocessor unusable
0x0C- IRQ_SOFTWARE0 =
Interrupt bits in CAUSE (bits 8-15, matches SR mask)
0x0100- IRQ_SOFTWARE1 =
0x0200- IRQ_HARDWARE =
External hardware interrupt (active when I_STAT & I_MASK != 0)
0x0400
Instance Attribute Summary collapse
-
#regs ⇒ Object
readonly
Returns the value of attribute regs.
Instance Method Summary collapse
- #bev? ⇒ Boolean
- #cache_isolated? ⇒ Boolean
- #cause ⇒ Object
-
#enter_exception(code, pc, in_delay_slot: false, bad_addr: nil, coprocessor: nil) ⇒ Object
Enter exception handler.
- #epc ⇒ Object
-
#initialize ⇒ COP0
constructor
A new instance of COP0.
- #interrupt_pending? ⇒ Boolean
- #interrupts_enabled? ⇒ Boolean
- #read(reg) ⇒ Object
-
#return_from_exception ⇒ Object
Return from exception (RFE instruction).
- #set_hardware_irq(active) ⇒ Object
- #sr ⇒ Object
- #sr=(value) ⇒ Object
- #write(reg, value) ⇒ Object
Constructor Details
Instance Attribute Details
#regs ⇒ Object (readonly)
Returns the value of attribute regs.
61 62 63 |
# File 'lib/psx/cop0.rb', line 61 def regs @regs end |
Instance Method Details
#bev? ⇒ Boolean
107 108 109 |
# File 'lib/psx/cop0.rb', line 107 def bev? (@regs[SR] & SR_BEV) != 0 end |
#cache_isolated? ⇒ Boolean
103 104 105 |
# File 'lib/psx/cop0.rb', line 103 def cache_isolated? (@regs[SR] & SR_ISC) != 0 end |
#cause ⇒ Object
95 96 97 |
# File 'lib/psx/cop0.rb', line 95 def cause @regs[CAUSE] end |
#enter_exception(code, pc, in_delay_slot: false, bad_addr: nil, coprocessor: nil) ⇒ Object
Enter exception handler. Returns the exception vector address. ‘coprocessor` is the COP number (0-3) reported in CAUSE.CE for Coprocessor-Unusable exceptions.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/psx/cop0.rb', line 135 def enter_exception(code, pc, in_delay_slot: false, bad_addr: nil, coprocessor: nil) @regs[EPC] = in_delay_slot ? pc - 4 : pc @regs[BADVADDR] = bad_addr if bad_addr # CAUSE: preserve interrupt-pending bits, set ExcCode, BD, and CE. ce = coprocessor ? ((coprocessor & 0x3) << 28) : 0 @regs[CAUSE] = (@regs[CAUSE] & 0x0000_FF00) | (code << 2) | ce | (in_delay_slot ? 0x8000_0000 : 0) # Shift IE/KU stack: current -> previous -> old. mode = @regs[SR] & 0x3F @regs[SR] = (@regs[SR] & ~0x3F) | ((mode << 2) & 0x3F) bev? ? 0xBFC0_0180 : 0x8000_0080 end |
#epc ⇒ Object
99 100 101 |
# File 'lib/psx/cop0.rb', line 99 def epc @regs[EPC] end |
#interrupt_pending? ⇒ Boolean
115 116 117 118 119 120 121 122 |
# File 'lib/psx/cop0.rb', line 115 def interrupt_pending? # Check if any unmasked interrupt is pending return false unless interrupts_enabled? mask = (@regs[SR] >> 8) & 0xFF pending = (@regs[CAUSE] >> 8) & 0xFF (mask & pending) != 0 end |
#interrupts_enabled? ⇒ Boolean
111 112 113 |
# File 'lib/psx/cop0.rb', line 111 def interrupts_enabled? (@regs[SR] & SR_IEC) != 0 end |
#read(reg) ⇒ Object
68 69 70 |
# File 'lib/psx/cop0.rb', line 68 def read(reg) @regs[reg] end |
#return_from_exception ⇒ Object
Return from exception (RFE instruction)
154 155 156 157 158 159 |
# File 'lib/psx/cop0.rb', line 154 def return_from_exception # Shift interrupt enable/kernel mode bits back # Old -> Previous -> Current mode = @regs[SR] & 0x3F @regs[SR] = (@regs[SR] & ~0x0F) | ((mode >> 2) & 0x0F) end |
#set_hardware_irq(active) ⇒ Object
124 125 126 127 128 129 130 |
# File 'lib/psx/cop0.rb', line 124 def set_hardware_irq(active) if active @regs[CAUSE] |= IRQ_HARDWARE else @regs[CAUSE] &= ~IRQ_HARDWARE end end |
#sr ⇒ Object
87 88 89 |
# File 'lib/psx/cop0.rb', line 87 def sr @regs[SR] end |
#sr=(value) ⇒ Object
91 92 93 |
# File 'lib/psx/cop0.rb', line 91 def sr=(value) write(SR, value) end |
#write(reg, value) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/psx/cop0.rb', line 72 def write(reg, value) case reg when SR # Most bits are writable @regs[SR] = value & 0xF4C7_9C3F when CAUSE # Only software interrupt bits (8-9) are writable @regs[CAUSE] = (value & 0x0300) | (@regs[CAUSE] & ~0x0300) when PRID # Read-only else @regs[reg] = value end end |