-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathirq.lisp
65 lines (59 loc) · 2.19 KB
/
irq.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(defpackage #:psx-irq
(:nicknames #:irq)
(:use :cl)
(:export #:irq #:make-irq #:raise-interrupt #:read-irq #:write-irq
#:irq-exception-callback #:has-pending-irq))
(in-package :psx-irq)
(declaim (optimize (speed 3) (safety 1)))
(defstruct irq
"Simple structure to hold the irq registers and perform bookkeeping on them."
(status 0 :type (unsigned-byte 16))
(mask 0 :type (unsigned-byte 16))
(exception-callback
(lambda () 0) :type (function () (unsigned-byte 32))))
(declaim (ftype (function (irq keyword)
(unsigned-byte 16))
raise-interrupt))
(defun raise-interrupt (irq interrupt)
"Takes an interrupt source and performs the bookkeeping required to
potentially raise an interrupt."
(let ((interrupt-index
(case interrupt
(:vblank #x0)
(:cdrom #x2)
(:timer0 #x4)
(:timer1 #x5)
(:timer2 #x6)
(:joypad #x7)
(otherwise (error "Unrecognized interrupt: ~A~%" interrupt)))))
(setf (irq-status irq)
(logior (irq-status irq) (ash 1 interrupt-index)))
interrupt-index))
(declaim (ftype (function (irq)
boolean)
has-pending-irq)
(inline has-pending-irq))
(defun has-pending-irq (irq)
(if (zerop (logand (irq-status irq) (irq-mask irq)))
nil
t))
(declaim (ftype (function (irq (unsigned-byte 8))
(unsigned-byte 16))
read-irq))
(defun read-irq (irq offset)
"Takes an offset and returns the appropriate slot of irq."
(case offset
(0 (irq-status irq))
(4 (irq-mask irq))
(otherwise (error "Invalid irq offset #x~1,'0x~%" offset))))
(declaim (ftype (function (irq (unsigned-byte 8) (unsigned-byte 32))
(unsigned-byte 16))
write-irq))
(defun write-irq (irq offset value)
"Takes an offset and word and sets the value at the requested offset,
performing required masking on irq-status."
(case offset
(0 (setf (irq-status irq)
(logand (irq-status irq) value #xFFFF)))
(4 (setf (irq-mask irq) (logand value #xFFFF)))
(otherwise (error "Invalid irq offset #x~1,'0x~%" offset))))