A Playstation One (PS1) emulator fully written in Jam
0

Configure Feed

Select the types of activity you want to include in your feed.

jamstation / irq.jam
3.8 kB 127 lines
1// SPDX-License-Identifier: MIT 2// Copyright (c) 2026 Raphael Amorim 3 4// Two registers live at 0x1F801070..0x1F801077: 5// 0x00 I_STAT status - set by devices raising IRQs, cleared by 6// writing 0 to the matching bit 7// 0x04 I_MASK mask - when (stat & mask) != 0, COP0 CAUSE bit IP2 8// (= 0x00000400) is asserted, which causes the CPU to 9// take an external interrupt the next time it samples 10// pending IRQs at fetch time. 11// 12// State buffer (two u32 entries): 13// [0] I_STAT 14// [1] I_MASK 15 16const { Vec } = import("std/collections"); 17 18pub const IC_VBLANK: u32 = 0x001; 19pub const IC_GPU: u32 = 0x002; 20pub const IC_CDROM: u32 = 0x004; 21pub const IC_DMA: u32 = 0x008; 22pub const IC_TIMER0: u32 = 0x010; 23pub const IC_TIMER1: u32 = 0x020; 24pub const IC_TIMER2: u32 = 0x040; 25pub const IC_JOY: u32 = 0x080; 26pub const IC_SIO: u32 = 0x100; 27pub const IC_SPU: u32 = 0x200; 28pub const IC_LP_PIO: u32 = 0x400; 29 30const CAUSE_IP2: u32 = 0x00000400; 31const C0_CAUSE: u32 = 13; 32 33pub fn createIrq() Vec(u32) { 34 return Vec(u32).filled(0, 16); 35} 36 37pub fn irqReevaluate(ic: *mut[] u32, cop0: *mut[] u32) { 38 const pending: u32 = ic[0] & ic[1]; 39 var cause: u32 = cop0[C0_CAUSE]; 40 if (pending != 0) { 41 cause = cause | CAUSE_IP2; 42 } else { 43 cause = cause & (~CAUSE_IP2); 44 } 45 cop0[C0_CAUSE] = cause; 46} 47 48pub fn irqRead32(ic: *mut[] u32, off: u32) u32 { 49 match (off) { 50 0x00 { return ic[0]; } 51 0x04 { return ic[1]; } 52 _ { return 0; } 53 } 54} 55 56pub fn irqRead16(ic: *mut[] u32, off: u32) u32 { 57 match (off) { 58 0x00 { return ic[0] & 0xFFFF; } 59 0x02 { return (ic[0] >> 16) & 0xFFFF; } 60 0x04 { return ic[1] & 0xFFFF; } 61 0x06 { return (ic[1] >> 16) & 0xFFFF; } 62 _ { return 0; } 63 } 64} 65 66pub fn irqRead8(ic: *mut[] u32, off: u32) u32 { 67 match (off) { 68 0x00 { return ic[0] & 0xFF; } 69 0x01 { return (ic[0] >> 8) & 0xFF; } 70 0x02 { return (ic[0] >> 16) & 0xFF; } 71 0x03 { return (ic[0] >> 24) & 0xFF; } 72 0x04 { return ic[1] & 0xFF; } 73 0x05 { return (ic[1] >> 8) & 0xFF; } 74 0x06 { return (ic[1] >> 16) & 0xFF; } 75 0x07 { return (ic[1] >> 24) & 0xFF; } 76 _ { return 0; } 77 } 78} 79 80pub fn irqWrite32(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { 81 match (off) { 82 0x00 { ic[0] = ic[0] & val; } 83 0x04 { ic[1] = val; } 84 _ {} 85 } 86 irqReevaluate(ic, cop0); 87} 88 89pub fn irqWrite16(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { 90 const v: u32 = val & 0xFFFF; 91 match (off) { 92 0x00 { ic[0] = ic[0] & (0xFFFF0000 | v); } 93 0x02 { ic[0] = ic[0] & (0x0000FFFF | (v << 16)); } 94 0x04 { ic[1] = (ic[1] & 0xFFFF0000) | v; } 95 0x06 { ic[1] = (ic[1] & 0x0000FFFF) | (v << 16); } 96 _ {} 97 } 98 irqReevaluate(ic, cop0); 99} 100 101pub fn irqWrite8(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { 102 const v: u32 = val & 0xFF; 103 match (off) { 104 0x00 { ic[0] = ic[0] & (0xFFFFFF00 | v); } 105 0x01 { ic[0] = ic[0] & (0xFFFF00FF | (v << 8)); } 106 0x02 { ic[0] = ic[0] & (0xFF00FFFF | (v << 16)); } 107 0x03 { ic[0] = ic[0] & (0x00FFFFFF | (v << 24)); } 108 0x04 { ic[1] = (ic[1] & 0xFFFFFF00) | v; } 109 0x05 { ic[1] = (ic[1] & 0xFFFF00FF) | (v << 8); } 110 0x06 { ic[1] = (ic[1] & 0xFF00FFFF) | (v << 16); } 111 0x07 { ic[1] = (ic[1] & 0x00FFFFFF) | (v << 24); } 112 _ {} 113 } 114 irqReevaluate(ic, cop0); 115} 116 117pub fn irqRaise(ic: *mut[] u32, cop0: *mut[] u32, lines: u32) { 118 ic[0] = ic[0] | lines; 119 var b: u32 = 0; 120 while (b < 11) { 121 if ((lines & (1 << b)) != 0) { 122 ic[2 + b] = ic[2 + b] + 1; 123 } 124 b = b + 1; 125 } 126 irqReevaluate(ic, cop0); 127}