87 lines
3.6 KiB
Plaintext
87 lines
3.6 KiB
Plaintext
|
include cards.i
|
||
|
xref main
|
||
|
section .early.text, text
|
||
|
public _start
|
||
|
; Receives pointer to program headers in a0 and number of program headers in d0
|
||
|
_start:
|
||
|
move.l d0, d2 ; Move the number of program headers to d2
|
||
|
move.l a0, a1 ; Move the program headaer pointer to a1
|
||
|
move.w #$5, d0 ; Get the pointer to the MMU card
|
||
|
jsr (find_first_card - $C00000)
|
||
|
cmpa.l #0, a0 ; Abort if there is no MMU card
|
||
|
beq.w no_mmu
|
||
|
subq.w #$1, d2 ; Adjust the number of program headers for dbra
|
||
|
phead_loop:
|
||
|
move.l (a1), d1 ; If the type of the program header isn't 1 (LOAD), skip the header
|
||
|
cmpi.l #$1, d1
|
||
|
bne.b next_phead
|
||
|
move.b (9,a1), d1 ; If the segment isn't for the high quarter, skip it
|
||
|
cmpi.b #$c0, d1
|
||
|
bgt.b next_phead
|
||
|
move.l (20,a1), d4 ; Put the memory size in d4
|
||
|
move.l d4, d3 ; Copy the size to d3
|
||
|
lsr #8, d3 ; Shift d3 right 12 bits to get the number of full pages the segment takes up
|
||
|
lsr #4, d3
|
||
|
andi.l #$FFF, d4 ; If the segment takes up a partial page, add 1 to the number of required pages in d3
|
||
|
cmp.l #$0, d4
|
||
|
beq.b even_page
|
||
|
addq.l #1, d3
|
||
|
even_page:
|
||
|
subq.b #1, d3 ; Adjust the number of pages to map for dbra
|
||
|
move.l (12,a1), d1 ; Get the starting physical page in d3
|
||
|
move.l (24,a1), d4 ; Get the permission flags in d4
|
||
|
andi.l #$2, d4 ; Isolate the writable flag
|
||
|
or.l d4, d1 ; Copy the writable flag to the page entry
|
||
|
move.l (24,a1), d4 ; Get the permission flags in d4
|
||
|
andi.l #$1, d4 ; Isolate the executable flag
|
||
|
lsl.l #3, d4 ; Copy the executable flag to the page entry
|
||
|
or.l d4, d1
|
||
|
ori.l #$1, d1 ; Set the present flag on the entry
|
||
|
move.l (8,a1), d0 ; Get the starting virtual page number in the quarter in d0
|
||
|
lsr.l #8, d0
|
||
|
lsr.l #4, d0
|
||
|
andi.l #$3ff, d0
|
||
|
lsl #2, d0 ; Get the pointer to the entry for the page in a2
|
||
|
move.l #(kernel_map - $C00000), a2
|
||
|
adda d0, a2
|
||
|
map_loop:
|
||
|
move.l d1, (a2)+ ; Write the entry to the mapping page and advance the entry pointer
|
||
|
addi.l #$1000, d1 ; Advance the entry to the next physical page
|
||
|
dbra d3, map_loop ; Loop back if there are more pages to map
|
||
|
next_phead:
|
||
|
lea ($20,a1), a1 ; Advance a1 to point to the next program header
|
||
|
dbra d2, phead_loop ; If there are more program headers, loop back
|
||
|
io_map:
|
||
|
move.l #15, d0 ; Put the number of IO pages in d0, minus one to adjust for dbra
|
||
|
move.l #(kernel_map - $C00000 + $3f0 * 4), a1 ; Put the poiner to the mapping for virtual page $FF0000 in a1
|
||
|
move.l #$ffff0003, d1 ; Put the initial map entry in d1
|
||
|
io_map_loop:
|
||
|
move.l d1, (a1)+ ; Write the entry to the mapping page and advance the entry pointer
|
||
|
addi.l #$1000, d1 ; Advance the entry to the next physical page
|
||
|
dbra d0, io_map_loop ; Loop back if there are more pages to map
|
||
|
map_done:
|
||
|
move.l #(kernel_map - $C00000), d0 ; Load the pointer to the mapping page into d0
|
||
|
ori.l #$1, d0 ; Set the map page present flag
|
||
|
move.l d0, ($0,a0) ; Write the mapping page to both the lower and upper quarter map registers
|
||
|
move.l d0, ($C,a0)
|
||
|
jmp (higher_bridge - $C00000) ; Jump to the lower-half equivalent of the bridging function
|
||
|
no_mmu:
|
||
|
stop #$2700 ; If there was no MMU card, halt the CPU
|
||
|
|
||
|
section .text,text
|
||
|
higher_bridge:
|
||
|
move.w #1, ($14,a0) ; Enable the MMU
|
||
|
jmp in_higher.l ; Jump to the higher half (THis function has been called with the PC in the
|
||
|
; lower half, so this seemingly no-op jump instruction actually switches to the higher half)
|
||
|
in_higher:
|
||
|
move.w #0, $ff0000 ; Disable the IO space at the top of the lower 16MB of memory
|
||
|
move.l #0, ($0,a0) ; Disable the mapping in the lower quarter
|
||
|
jmp main ; Jump to the kernel's main function
|
||
|
|
||
|
section .bss,bss
|
||
|
public kernel_map
|
||
|
kernel_map:
|
||
|
align 12
|
||
|
ds.b 4096
|
||
|
|