From 4b4c46d7caf09208edf4d0117f5644a9e88cc23d Mon Sep 17 00:00:00 2001 From: pjht Date: Tue, 19 Mar 2024 09:24:25 -0500 Subject: [PATCH] Initial commit --- Tupfile | 6 ++ Tupfile.imi | 0 include/memory.i | 7 +++ include/string.i | 9 +++ include/syscalls.i | 22 +++++++ memory.68k | 145 +++++++++++++++++++++++++++++++++++++++++++++ string.68k | 71 ++++++++++++++++++++++ syscalls.68k | 70 ++++++++++++++++++++++ 8 files changed, 330 insertions(+) create mode 100644 Tupfile create mode 100644 Tupfile.imi create mode 100644 include/memory.i create mode 100644 include/string.i create mode 100644 include/syscalls.i create mode 100644 memory.68k create mode 100644 string.68k create mode 100644 syscalls.68k diff --git a/Tupfile b/Tupfile new file mode 100644 index 0000000..d8ba533 --- /dev/null +++ b/Tupfile @@ -0,0 +1,6 @@ +.gitignore + +ASFLAGS = -m68010 -spaces -Felf -ldots -align -quiet -x -nowarn=62 + +: foreach *.68k |> vasmm68k_mot $(ASFLAGS) -o %o %f |> %B.o +: *.o |> ar rs %o %f |> libstd.a diff --git a/Tupfile.imi b/Tupfile.imi new file mode 100644 index 0000000..e69de29 diff --git a/include/memory.i b/include/memory.i new file mode 100644 index 0000000..26d1e9a --- /dev/null +++ b/include/memory.i @@ -0,0 +1,7 @@ + ifnd __STD_MEMORY_I +__STD_MEMORY_I equ 1 +; Frees the memory block pointed to by a0 + xref free +; Allocates a memory block of size d0 and returns the address in a0 + xref malloc + endif diff --git a/include/string.i b/include/string.i new file mode 100644 index 0000000..c62d7d6 --- /dev/null +++ b/include/string.i @@ -0,0 +1,9 @@ + ifnd __STD_STRING_I +__STD_STRING_I equ 1 +; Writes the hexdecimal ASCII representation of d0.l to the 11-byte buffer at a0 + xref hex_to_ascii +; Compares the strings in a0 and a1 +; Returns 0 in d0.b if identical +; Returns difference of first mismatching character in d0.b (s1-s2) if different + xref strcmp + endif diff --git a/include/syscalls.i b/include/syscalls.i new file mode 100644 index 0000000..01060cd --- /dev/null +++ b/include/syscalls.i @@ -0,0 +1,22 @@ + ifnd __STD_SYSCALLS_I +__STD_SYSCALLS_I equ 1 +; Exits the process + xref syscall_exit +; Yields to the next process + xref syscall_yield +; Prints the string pointed to by d0 + xref syscall_print +; Prints the string pointed to by d0 followed by a newline + xref syscall_println +; Maps the range of pages starting at address a0 with length d0 to free physical frames +; Permission flags in d1 + xref syscall_vmem_map +; Map a free range of pages with length d0 to free physical frames +; Returns the range start in a0 +; Permission flags in d1 + xref syscall_vmem_map_free +; Maps a free range of virtual pages with length d1 to the range of physical frames starting at d0 +; Returns the range start in a0 +; Permission flags in d2 + xref syscall_vmem_map_free_to + endif diff --git a/memory.68k b/memory.68k new file mode 100644 index 0000000..7b00685 --- /dev/null +++ b/memory.68k @@ -0,0 +1,145 @@ + include include/syscalls.i + section .text,text +; Frees the memory block pointed to by a0 +; free_w_size internal entry expecting size in d0 +; instead of 4 bytes before passed in address + public free +free: + move.l -(a0), d0 ; Read the allocatuon size and get the true hole pointer +free_w_size: + move.l (free_list), a1 ; Get the head of the free list in a0 + cmpa.l #0, a1 ; Check if the free list is empty + bne.b free_list_not_empty ; If not, find the right position and insert the hole + move.l d0, (a0) ; Otherwise, set the free list to be the passed in hole and return + move.l #0, ($4,a0) + move.l a0, (free_list) + rts +free_list_not_empty: + move.l a2, -(a7) ; Preserve a2 (callee saved) + move.l #0, a1 ; a1 is the pointer to the previous hole in the list, starts out NULL + move.l (free_list), a2 ; a2 is the pointer to the current hole in the list +free_find_loop: + cmpa.l #0, a2 ; If we have hit the end of the list, we have found the right position + beq.b free_find_loop_done + cmp.l a0, a2 + bgt.b free_find_loop_done + move.l a2, a1 ; Go to the next item + move.l ($4,a2), a2 + bra.b free_find_loop +free_find_loop_done: +; We have now found where to put the hole, that being between a1 (previous hole), and a2 (current hole) + cmpa.l #0, a1 ; If there is no previous item, we cannot merge + beq.b free_no_prev + move.l (a1), d1 ; If size of prev hole + address of prev hole = address of hole to free, they are consecutive and can be merged + add.l a1, d1 + cmp.l a0, d1 + bne.b free_no_prev_merge + add.l d0, (a1) ; size of prev hole += size of hole to free + move.l a1, a0 ; hole to free = prev hole + move.l #0, a1 ; prev hole = NULL + bra.b free_prev_merge_done +free_no_prev_merge: + move.l a2, ($4,a0) ; If we are not merging, hole to free next = current hole, prev hole next = hole to free + move.l a0, ($4,a1) + bra free_prev_merge_done +free_no_prev: + move.l (free_list), ($4,a0) ; If there is no previous hole, add it to the beginning of the free list + move a0, (free_list) +free_prev_merge_done: + cmpa.l #0, a2 ; If there is no current hole, no merging must be done + beq.b free_curr_merge_done + move.l (a0), d1 ; If size of hole to free + address of hole to free = address of current hole, they are consecutive and can be merged + add.l a0, d1 + cmp.l a2, d1 + bne.b free_curr_merge_done + move.l ($4,a2), d1 ; hole to free next = current hole next + move.l d1, ($4,a0) + move.l (a0), d1 ; hole to free size += current hole size + add.l (a2), d1 + move.l d1, (a0) +free_curr_merge_done: + move.l (a7)+, a2 ; Restore a2 (callee saved) + rts + +; Allocates a memory block of size d0 and returns the address in a0 + public malloc +malloc: + ; Return NULL if d0=0 + cmpi.l #0, d0 + bne .1 + move.l #0, a0 + rts +.1: + ; d0=d0+4 rounded to next multiple of 4 + addi.l #4, d0 + move.l d0, d1 + andi.l #$2, d1 + beq.b .2 + move.l d0, d1 + andi.l #~$2, d1 + addi.l #8, d1 + move.l d1, d0 +.2: + move.l (free_list), a0 +malloc_find_loop: + cmpa.l #0, a0 + beq malloc_found_end + move.l (a0), d1 + cmp.l d0, d1 + blt.b malloc_too_small + beq.b malloc_block_exact_size + sub.l d0, d1 + move.l d1, (a0) + adda.l d1, a0 + move.l d0, (a0)+ + rts +malloc_block_exact_size: + adda.l #4, a0 + rts +malloc_too_small: + move.l ($8,a0), a0 + bra.b malloc_find_loop +malloc_found_end: + move.l d0, -(a7) + move.l d0, d1 + andi.l #$fff, d1 + beq.b .1 + move.l d0, d1 + andi.l #~$fff, d1 + addi.l #$1000, d1 + move.l d1, d0 +.1: + lsr.l #8, d0 + lsr.l #4, d0 + move.l d0, -(a7) + jsr alloc_pages + move.l (a7)+, d0 + lsl.l #8, d0 + lsl.l #4, d0 + move.l d0, d1 + move.l (a7)+, d0 + sub.l d0, d1 + move.l a0, a1 + adda.l d1, a1 + move.l d0, (a1)+ + move.l d1, d0 + move.l a1, -(a7) + bsr.w free_w_size + move.l (a7)+, a0 + rts + +; Allocate a block of memory d0 pages in length and returns the address in a0 + weak alloc_pages +alloc_pages: + move.l d2, -(a7) + move.l #$2, d1 + jsr syscall_vmem_map_free +alloc_pages_done: + move.l (a7)+, d2 + rts + + + + section .bss,bss +free_list: + ds.b 4 diff --git a/string.68k b/string.68k new file mode 100644 index 0000000..da5340e --- /dev/null +++ b/string.68k @@ -0,0 +1,71 @@ + section .text,text + public hex_to_ascii +; Writes the hexdecimal ASCII representation of d0.l to the 11-byte buffer at a0 +hex_to_ascii: + movem.l d2/d3, -(a7) ; Save old values of d2 and d3 (callee preserved) + move.b #'0', (a0)+ + move.b #'x', (a0)+ + move.b #0, d1 + move.w #28, d2 +hex_to_ascii_loop: + cmpi.w #0, d2 + beq.b hex_to_ascii_loop_done + move.l d0, d3 + lsr.l d2, d3 + andi.l #$F, d3 + cmp.l #0, d3 + bne.b .1 + cmp.b #0, d1 + bne.b .1 + subi.w #4, d2 + bra.b hex_to_ascii_loop +.1: + move.b #1, d1 + cmp.b #$A, d3 + blt.b .2 + add.b #('a' - $A), d3 + move.b d3, (a0)+ + bra.b .3 +.2: + add.b #'0', d3 + move.b d3, (a0)+ +.3: + subi.w #4, d2 + bra.b hex_to_ascii_loop +hex_to_ascii_loop_done: + move.l d0, d3 + andi.l #$F, d3 + cmp.b #$A, d3 + blt.b .2 + add.b #('a' - $A), d3 + move.b d3, (a0)+ + bra.b .3 +.2: + add.b #'0', d3 + move.b d3, (a0)+ +.3: + move.b #0, (a0) + movem.l (a7)+, d2/d3 ; Restore d2 and d3 (callee preserved) + rts + +; Compares the strings in a0 and a1 +; Returns 0 in d0.b if identical +; Returns difference of first mismatching character in d0.b (s1-s2) if different + public strcmp +strcmp: +strcmp_loop: + move.b (a0), d0 + cmp.b (a1), d0 + bne.b strcmp_loop_done + cmpi.b #0, (a0) + bne.b .1 + move.b #0, d0 + rts +.1: + adda.l #1, a0 + adda.l #1, a1 + bra.b strcmp_loop +strcmp_loop_done: + move.b (a0), d0 + sub.b (a1), d0 + rts diff --git a/syscalls.68k b/syscalls.68k new file mode 100644 index 0000000..9ebb13d --- /dev/null +++ b/syscalls.68k @@ -0,0 +1,70 @@ + section .text,text + + public syscall_exit +; Exits the process +syscall_exit: + move.l #0, d0 + trap #0 + rts + + public syscall_yield +; Yields to the next process +syscall_yield: + move.l #1, d0 + rts + + public syscall_print +; Prints the string pointed to by d0 +syscall_print: + move.l d0, d1 + move.l #2, d0 + trap #0 + rts + + public syscall_println +; Prints the string pointed to by d0 followed by a newline +syscall_println: + move.l d0, d1 + move.l #3, d0 + trap #0 + rts + + public syscall_vmem_map +; Maps the range of pages starting at address a0 with length d0 to free physical frames +; Permission flags in d1 +syscall_vmem_map: + move.l d2, -(a7) + move.l d1, d2 + move.l d0, d1 + move.l #4, d0 + trap #0 + move.l (a7)+, d2 + rts + + public syscall_vmem_map_free +; Map a free range of pages with length d0 to free physical frames +; Returns the range start in a0 +; Permission flags in d1 +syscall_vmem_map_free: + move.l d2, -(a7) + move.l d1, d2 + move.l d0, d1 + move.l #5, d0 + trap #0 + move.l (a7)+, d2 + rts + + public syscall_vmem_map_free_to +; Maps a free range of virtual pages with length d1 to the range of physical frames starting at d0 +; Returns the range start in a0 +; Permission flags in d2 +syscall_vmem_map_free_to: + move.l d3, -(a7) + move.l d2, d3 + move.l d1, d2 + move.l d0, d1 + move.l #6, d0 + trap #0 + move.l (a7)+, d3 + rts +