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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
|| -*- gas -*-
|| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|| _ __ ___ ___ _ __ ___ ___ _ __ _ _ |||||||||||||||||||||||||||
|| | '_ ` _ \ / _ \ '_ ` _ \ / _ \| '__| | | | \\\\\\\\\\\\\\\\\\\\\\\\\\\
|| | | | | | | __/ | | | | | (_) | | | |_| | |||||||||||||||||||||||||||
|| |_| |_| |_|\___|_| |_| |_|\___/|_| \__, | ///////////////////////////
|| of the virtual type |___/ |||||||||||||||||||||||||||
|| =============================================JJJJJJJJJJJJJJJJJJJJJJJJJJJ
|| Take a virtual address in d1 and dereference it. Returns the
|| host address in a0. Destroys a0, d0.
deref: | 76 cycles + 18 cycles for bsr
| 20 bytes to inline, saves 34 cycles per call
move.w d1,d0
andi.w #0x3FFF,d0
movea.w d0,a0
move.w d1,d0
andi.w #0xC000,d0 | Can cut this out by pre-masking the table.
rol.w #4,d0
adda.l deref_table(pc,d0.w),a0 | TODO gas doesn't like this
rts
.even
.bss
deref_table:
mem_page_0: .long 0 | bank 0 / 0x0000
mem_page_1: .long 0 | bank 1 / 0x4000
mem_page_2: .long 0 | bank 2 / 0x8000
mem_page_3: .long 0 | bank 3 / 0xc000
.xdef mem_page_0
.xdef mem_page_1
.xdef mem_page_2
.xdef mem_page_3
mem_page_loc_0: .byte 0
mem_page_loc_1: .byte 0
mem_page_loc_2: .byte 0
mem_page_loc_3: .byte 0
.xdef mem_page_loc_0
.xdef mem_page_loc_1
.xdef mem_page_loc_2
.xdef mem_page_loc_3
pages: .long 0
.xdef pages
.text
|| Take a physical address in a0 and turn it into a virtual
|| address in d0
|| Destroys d0, a1
| XXX AFAICS, a1 is currently a scratch address register, so you can load deref_table in it, and then save some space:
| But you may wish to use it for other purposes in the future, so you needn't integrate that immediately.
|| Guessing this is 300 cycles.
underef:
move.l d2,-(a7)
lea deref_table(pc),a1
move.l a0,d0
clr.w d2
sub.l (a1)+,d0
bmi.s underef_not0
cmpi.l #0x4000,d0
bmi.s underef_thatsit
underef_not0:
move.l a0,d0
move.w #0x4000,d2
sub.l (a1)+,d0
bmi.s underef_not1
cmpi.l #0x4000,d0
bmi.s underef_thatsit
underef_not1:
move.l a0,d0
move.w #0x8000,d2
sub.l (a1)+,d0
bmi.s underef_not2
cmpi.l #0x4000,d0
bmi.s underef_thatsit
underef_not2:
move.w #0xc000,d2
suba.l (a1)+,a0
|| if that fails too, well shit man!
moveq #0,d0
underef_thatsit:
add.w d2,d0
move.l (a7)+,d2
rts
|