forked from Zeal8bit/Zeal-8-bit-OS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mmu_h.asm
172 lines (148 loc) · 5.68 KB
/
mmu_h.asm
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
; SPDX-FileCopyrightText: 2023 Zeal 8-bit Computer <[email protected]>
;
; SPDX-License-Identifier: Apache-2.0
INCLUDE "kern_mmu_h.asm"
INCLUDE "romdisk_info_h.asm"
INCLUDE "osconfig.asm"
IFNDEF MMU_H
DEFINE MMU_H
; Size of the RAM in bytes
DEFC MMU_RAM_SIZE = 512 * 1024
; RAM physical address
DEFC MMU_RAM_PHYS_ADDR = 0x80000 ; 512KB
; Index of the first RAM page
DEFC MMU_RAM_PHYS_START_IDX = MMU_RAM_PHYS_ADDR / KERN_MMU_VIRT_PAGES_SIZE
; Number of 16KB pages for the RAM: 512KB/16KB
DEFC MMU_RAM_PHYS_PAGES = MMU_RAM_SIZE / KERN_MMU_VIRT_PAGES_SIZE
; RAM page index of kernel RAM
DEFC MMU_KERNEL_RAM_PAGE_INDEX = (CONFIG_KERNEL_RAM_PHYS_ADDRESS >> 14) - MMU_RAM_PHYS_START_IDX
; MMU pages configuration I/O address
DEFC MMU_PAGE_0 = 0xF0
DEFC MMU_PAGE_1 = 0xF1
DEFC MMU_PAGE_2 = 0xF2
DEFC MMU_PAGE_3 = 0xF3
; Routines implemented in `mmu.asm` source file
EXTERN mmu_init_ram_code
EXTERN mmu_alloc_page
EXTERN mmu_free_page
EXTERN mmu_mark_page_allocated
EXTERN mmu_bitmap
; Macro used to map a physical address to a virtual page. Both must be defined at compile time.
MACRO MMU_MAP_PHYS_ADDR page, address
ASSERT(address < 0x400000) ; Max 4MB of physical memory
ld a, address >> 14 ; Virtual address are 16 - 2 = 14 bits wide
out (page), a
ENDM
MACRO MMU_SET_PAGE_NUMBER page
ASSERT(page >= MMU_PAGE_0 && page <= MMU_PAGE_3)
out (page), a
ENDM
; Get the MMU configuration for a page declared at compile time.
MACRO MMU_GET_PAGE_NUMBER page
ASSERT(page >= MMU_PAGE_0 && page <= MMU_PAGE_3)
ld a, page << 6 & 0xff
in a, (page)
ENDM
; Get the MMU configuration for a page declared at runtime, in A
; Page must be between 0 and 3.
MACRO MMU_GET_PAGE_NUMBER_A _
rrca
rrca ; Put 0-3 in top bits
in a, (MMU_PAGE_0) ; when reading, only 0xF_ matters
ENDM
; Macro used to map the kernel RAM into the specified virtual page
MACRO MMU_MAP_KERNEL_RAM page
ASSERT(page >= MMU_PAGE_0 && page <= MMU_PAGE_3)
; For some reasons, z88dk doesn't allow us to call another macro is a macro...
; Copy the content of MMU_MAP_PHYS_ADDR here. When it will be supported,
; the following should be used:
; MMU_MAP_PHYS_ADDR(page, CONFIG_KERNEL_RAM_PHYS_ADDRESS)
ld a, CONFIG_KERNEL_RAM_PHYS_ADDRESS >> 14
out (page), a
ENDM
MACRO MMU_ALLOC_PAGE _
call mmu_alloc_page
ENDM
; Free a previously allocated page
; Must not alter HL, DE
MACRO MMU_FREE_PAGE page
ld a, page
call mmu_free_page
ENDM
IF CONFIG_KERNEL_TARGET_HAS_MMU
MACRO MMU_INIT _
; Map Kernel RAM now and initialize the allocation bitmap
; z88dk doesn't support using a macro in a macro, when it will be supported,
; Replace the following with: MMU_MAP_KERNEL_RAM(MMU_PAGE_3)
ld a, CONFIG_KERNEL_RAM_PHYS_ADDRESS >> 14
out (MMU_PAGE_3), a
; Clear the allocated bitmap
ld hl, 0xFFFF
; At the moment, we know we have only 4 bytes, no need to make a loop
ASSERT(MMU_RAM_PHYS_PAGES == 32)
ld (mmu_bitmap), hl
ld (mmu_bitmap + 2), hl
; In theory, the stack is not ready, let's take some advance and set it
; in order ot be able to call a function
ld sp, CONFIG_KERNEL_STACK_ADDR
call mmu_init_ram_code
; Mark kernel RAM page as allocated (page number in A, subtract RAM start index)
ld a, MMU_KERNEL_RAM_PAGE_INDEX
call mmu_mark_page_allocated
; Check if the kernel is running in RAM, if that's the case, mark the page it is
; running in as allocated
xor a ; 2 top bits to 0
in a, (MMU_PAGE_0) ; Kernel is running from page 0
sub MMU_RAM_PHYS_START_IDX
; Kernel is in RAM if there is no carry
call nc, mmu_mark_page_allocated
; TODO: If support for RAMDISK is added, loaded by a bootloader, mark its pages as allocated
ENDM
ELSE ; !CONFIG_KERNEL_TARGET_HAS_MMU
; In case the kernel is in no-MMU mode, define a macro to initialize the memory (map some RAM)
MACRO MMU_INIT _
; Set RAM page 0, 1, 2 to virtual pages 1, 2, 3 respectively
ld a, MMU_RAM_PHYS_START_IDX
out (MMU_PAGE_1), a
inc a
out (MMU_PAGE_2), a
inc a
out (MMU_PAGE_3), a
ENDM
ENDIF ; CONFIG_KERNEL_TARGET_HAS_MMU
; Macro to map the physical address pointed by HBC to the page pointed by A.
; If the physical address is not a multiple of the page size, it shall be
; rounded down.
; Parameters:
; HBC - 24-bit physical address to map
; A - Page index to map it to. Considered valid.
; Returns*:
; A - ERR_SUCCESS on success, error code else.
; Alters:
; A
; *Not really a return as the macro shall not use ret instruction, but more like values to modify
MACRO MMU_MAP_PHYS_HBC_TO_PAGE_A _
LOCAL endmacro
push bc
; A points to the page index, convert this to an I/O address before storing it inside C
add MMU_PAGE_0
ld c, a
; Check that the address is within 4MB as Zeal 8-bit computer only supports up to 4MB of memory.
ld a, h
and 0xc0
ld a, ERR_INVALID_PHYS_ADDRESS
jp nz, endmacro
; Else, we have to shift right the address 14 times and keep the result in A
ld a, h
rlc b
rla
rlc b
rla
; Perform the MMU configuration now that A is correct
out (c), a
; Success, return 0
xor a
endmacro:
pop bc
ENDM
ENDIF ; MMU_H