Initial commit
This commit is contained in:
630
common.s
Normal file
630
common.s
Normal file
@ -0,0 +1,630 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
# obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
.global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower
|
||||
.global _write_s, _read_file, _write_error, _write_c, _write_i, _print_i
|
||||
.global _memcmp, _memchr, _memmem, _memcpy, _mmap
|
||||
.global _current, _get, _advance, _label_counter
|
||||
.global _divide_by_zero_error, _exit, _strings_index, _string_equal
|
||||
|
||||
.section .rodata
|
||||
|
||||
.equ SYS_READ, 63
|
||||
.equ SYS_WRITE, 64
|
||||
.equ SYS_EXIT, 93
|
||||
.equ SYS_MMAP2, 222
|
||||
.equ STDIN, 0
|
||||
.equ STDOUT, 1
|
||||
.equ STDERR, 2
|
||||
.equ PROT_READ, 0x1
|
||||
.equ PROT_WRITE, 0x2
|
||||
.equ MAP_PRIVATE, 0x02
|
||||
.equ MAP_ANONYMOUS, 0x20
|
||||
|
||||
new_line: .ascii "\n"
|
||||
|
||||
.section .text
|
||||
|
||||
# Write the current token to stderr. Ends the output with a newline.
|
||||
#
|
||||
# a0 - String pointer.
|
||||
# a1 - String length.
|
||||
.type _write_error, @function
|
||||
_write_error:
|
||||
mv t0, a0
|
||||
mv t1, a1
|
||||
|
||||
li a0, STDERR
|
||||
mv a1, t0
|
||||
mv a2, t1
|
||||
li a7, SYS_WRITE
|
||||
ecall
|
||||
|
||||
li a0, STDERR
|
||||
la a1, new_line
|
||||
li a2, 1
|
||||
li a7, SYS_WRITE
|
||||
ecall
|
||||
|
||||
ret
|
||||
|
||||
# a0 - First pointer.
|
||||
# a1 - Second pointer.
|
||||
# a2 - The length to compare.
|
||||
#
|
||||
# Returns 0 in a0 if memory regions are equal.
|
||||
.type _memcmp, @function
|
||||
_memcmp:
|
||||
mv t0, a0
|
||||
li a0, 0
|
||||
|
||||
.Lmemcmp_loop:
|
||||
beqz a2, .Lmemcmp_end
|
||||
|
||||
lbu t1, (t0)
|
||||
lbu t2, (a1)
|
||||
sub a0, t1, t2
|
||||
|
||||
bnez a0, .Lmemcmp_end
|
||||
|
||||
addi t0, t0, 1
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, -1
|
||||
|
||||
j .Lmemcmp_loop
|
||||
|
||||
.Lmemcmp_end:
|
||||
ret
|
||||
|
||||
# Detects if a0 is an uppercase character. Sets a0 to 1 if so, otherwise to 0.
|
||||
.type _is_upper, @function
|
||||
_is_upper:
|
||||
li t0, 'A' - 1
|
||||
sltu t1, t0, a0 # t1 = a0 >= 'A'
|
||||
|
||||
sltiu t2, a0, 'Z' + 1 # t2 = a0 <= 'Z'
|
||||
and a0, t1, t2 # t1 = a0 >= 'A' & a0 <= 'Z'
|
||||
|
||||
ret
|
||||
|
||||
# Detects if a0 is an lowercase character. Sets a0 to 1 if so, otherwise to 0.
|
||||
.type _is_lower, @function
|
||||
_is_lower:
|
||||
li t0, 'a' - 1
|
||||
sltu t2, t0, a0 # t2 = a0 >= 'a'
|
||||
|
||||
sltiu t3, a0, 'z' + 1 # t3 = a0 <= 'z'
|
||||
and a0, t2, t3 # t2 = a0 >= 'a' & a0 <= 'z'
|
||||
|
||||
ret
|
||||
|
||||
# Detects if the passed character is a 7-bit alpha character or an underscore.
|
||||
# The character is passed in a0.
|
||||
# Sets a0 to 1 if the character is an alpha character or underscore, sets it to 0 otherwise.
|
||||
.type _is_alpha, @function
|
||||
_is_alpha:
|
||||
# Prologue.
|
||||
addi sp, sp, -16
|
||||
sw ra, 12(sp)
|
||||
sw s0, 8(sp)
|
||||
addi s0, sp, 16
|
||||
|
||||
sw a0, 4(sp)
|
||||
|
||||
call _is_upper
|
||||
sw a0, 0(sp)
|
||||
|
||||
lw a0, 4(sp)
|
||||
call _is_lower
|
||||
|
||||
lw t0, 4(sp)
|
||||
xori t1, t0, '_'
|
||||
seqz t1, t1
|
||||
|
||||
lw t0, 0(sp)
|
||||
or a0, a0, t0
|
||||
or a0, a0, t1
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 12(sp)
|
||||
lw s0, 8(sp)
|
||||
addi sp, sp, 16
|
||||
ret
|
||||
|
||||
# Detects whether the passed character is a digit
|
||||
# (a value between 0 and 9).
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Exemined value.
|
||||
#
|
||||
# Sets a0 to 1 if it is a digit, to 0 otherwise.
|
||||
.type _is_digit, @function
|
||||
_is_digit:
|
||||
li t0, '0' - 1
|
||||
sltu t1, t0, a0 # t1 = a0 >= '0'
|
||||
|
||||
sltiu t2, a0, '9' + 1 # t2 = a0 <= '9'
|
||||
|
||||
and a0, t1, t2
|
||||
|
||||
ret
|
||||
|
||||
.type _is_alnum, @function
|
||||
_is_alnum:
|
||||
# Prologue.
|
||||
addi sp, sp, -16
|
||||
sw ra, 12(sp)
|
||||
sw s0, 8(sp)
|
||||
addi s0, sp, 16
|
||||
|
||||
sw a0, 4(sp)
|
||||
|
||||
call _is_alpha
|
||||
sw a0, 0(sp)
|
||||
|
||||
lw a0, 4(sp)
|
||||
call _is_digit
|
||||
|
||||
lw a1, 0(sp)
|
||||
or a0, a0, a1
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 12(sp)
|
||||
lw s0, 8(sp)
|
||||
addi sp, sp, 16
|
||||
ret
|
||||
|
||||
# Writes a string to the standard output.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Length of the string.
|
||||
# a1 - String pointer.
|
||||
.type _write_s, @function
|
||||
_write_s:
|
||||
# Prologue.
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw s0, 0(sp)
|
||||
addi s0, sp, 8
|
||||
|
||||
mv a2, a0
|
||||
li a0, STDOUT
|
||||
li a7, SYS_WRITE
|
||||
ecall
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 4(sp)
|
||||
lw s0, 0(sp)
|
||||
addi sp, sp, 8
|
||||
ret
|
||||
|
||||
# Reads standard input into a buffer.
|
||||
# a0 - Buffer pointer.
|
||||
# a1 - Buffer size.
|
||||
#
|
||||
# Sets s1 to the buffer passed in a0.
|
||||
#
|
||||
# Returns the amount of bytes written in a0.
|
||||
.type _read_file, @function
|
||||
_read_file:
|
||||
# Prologue.
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw s0, 0(sp)
|
||||
addi s0, sp, 8
|
||||
|
||||
mv s1, a0
|
||||
|
||||
li a0, STDIN
|
||||
mv a2, a1
|
||||
mv a1, s1
|
||||
li a7, SYS_READ
|
||||
ecall
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 4(sp)
|
||||
lw s0, 0(sp)
|
||||
addi sp, sp, 8
|
||||
ret
|
||||
|
||||
# Terminates the program. a0 contains the return code.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Status code.
|
||||
.type _exit, @function
|
||||
_exit:
|
||||
li a7, SYS_EXIT
|
||||
ecall
|
||||
# ret
|
||||
|
||||
.type _divide_by_zero_error, @function
|
||||
_divide_by_zero_error:
|
||||
addi a7, zero, 172 # getpid
|
||||
ecall
|
||||
|
||||
addi a1, zero, 8 # SIGFPE
|
||||
addi a7, zero, 129 # kill
|
||||
ecall
|
||||
ret
|
||||
|
||||
# Writes a number to a string buffer.
|
||||
#
|
||||
# t0 - Local buffer.
|
||||
# t1 - Constant 10.
|
||||
# t2 - Current character.
|
||||
# t3 - Whether the number is negative.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Whole number.
|
||||
# a1 - Buffer pointer.
|
||||
#
|
||||
# Sets a0 to the length of the written number.
|
||||
.type _print_i, @function
|
||||
_print_i:
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
li t1, 10
|
||||
addi t0, s0, -9
|
||||
|
||||
li t3, 0
|
||||
bgez a0, .Lprint_i_digit10
|
||||
li t3, 1
|
||||
neg a0, a0
|
||||
|
||||
.Lprint_i_digit10:
|
||||
rem t2, a0, t1
|
||||
addi t2, t2, '0'
|
||||
sb t2, 0(t0)
|
||||
div a0, a0, t1
|
||||
addi t0, t0, -1
|
||||
bne zero, a0, .Lprint_i_digit10
|
||||
|
||||
beq zero, t3, .Lprint_i_write_call
|
||||
addi t2, zero, '-'
|
||||
sb t2, 0(t0)
|
||||
addi t0, t0, -1
|
||||
|
||||
.Lprint_i_write_call:
|
||||
mv a0, a1
|
||||
addi a1, t0, 1
|
||||
sub a2, s0, t0
|
||||
addi a2, a2, -9
|
||||
sw a2, 0(sp)
|
||||
|
||||
call _memcpy
|
||||
|
||||
lw a0, 0(sp)
|
||||
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
addi sp, sp, 32
|
||||
ret
|
||||
|
||||
# Writes a number to the standard output.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Whole number.
|
||||
.type _write_i, @function
|
||||
_write_i:
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
addi a1, sp, 0
|
||||
call _print_i
|
||||
|
||||
addi a1, sp, 0
|
||||
call _write_s
|
||||
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
addi sp, sp, 32
|
||||
ret
|
||||
|
||||
# Writes a character from a0 into the standard output.
|
||||
.type _write_c, @function
|
||||
_write_c:
|
||||
# Prologue
|
||||
addi sp, sp, -16
|
||||
sw ra, 12(sp)
|
||||
sw s0, 8(sp)
|
||||
addi s0, sp, 16
|
||||
|
||||
sb a0, 4(sp)
|
||||
li a0, STDOUT
|
||||
addi a1, sp, 4
|
||||
li a2, 1
|
||||
li a7, SYS_WRITE
|
||||
ecall
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 12(sp)
|
||||
lw s0, 8(sp)
|
||||
add sp, sp, 16
|
||||
ret
|
||||
|
||||
# a0 - Pointer to an array to get the first element.
|
||||
#
|
||||
# Dereferences a pointer and returns what is on the address in a0.
|
||||
.type _get, @function
|
||||
_get:
|
||||
lw a0, (a0)
|
||||
ret
|
||||
|
||||
# Searches for the occurences of a character in the given memory block.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Memory block.
|
||||
# a1 - Needle.
|
||||
# a2 - Memory size.
|
||||
#
|
||||
# Sets a0 to the pointer to the found character or to null if the character
|
||||
# doesn't occur in the memory block.
|
||||
.type _memchr, @function
|
||||
_memchr:
|
||||
.Lmemchr_loop:
|
||||
beqz a2, .Lmemchr_nil # Exit if the length is 0.
|
||||
|
||||
lbu t0, (a0) # Load the character from the memory block.
|
||||
beq t0, a1, .Lmemchr_end # Exit if the character was found.
|
||||
|
||||
# Otherwise, continue with the next character.
|
||||
addi a0, a0, 1
|
||||
addi a2, a2, -1
|
||||
|
||||
j .Lmemchr_loop
|
||||
|
||||
.Lmemchr_nil:
|
||||
li a0, 0
|
||||
|
||||
.Lmemchr_end:
|
||||
ret
|
||||
|
||||
# Locates a substring.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Haystack.
|
||||
# a1 - Haystack size.
|
||||
# a2 - Needle.
|
||||
# a3 - Needle size.
|
||||
#
|
||||
# Sets a0 to the pointer to the beginning of the substring in memory or to 0
|
||||
# if the substring doesn't occur in the block.
|
||||
.type _memmem, @function
|
||||
_memmem:
|
||||
# Prologue.
|
||||
addi sp, sp, -24
|
||||
sw ra, 20(sp)
|
||||
sw s0, 16(sp)
|
||||
addi s0, sp, 24
|
||||
|
||||
# Save preserved registers. They are used to keep arguments.
|
||||
sw s1, 12(sp)
|
||||
sw s2, 8(sp)
|
||||
sw s3, 4(sp)
|
||||
sw s4, 0(sp)
|
||||
|
||||
mv s1, a0
|
||||
mv s2, a1
|
||||
mv s3, a2
|
||||
mv s4, a3
|
||||
|
||||
.Lmemmem_loop:
|
||||
blt s2, s3, .Lmemmem_nil # Exit if the needle length is greater than memory.
|
||||
|
||||
mv a0, s1
|
||||
mv a1, s3
|
||||
mv a2, s4
|
||||
call _memcmp
|
||||
|
||||
mv t0, a0 # memcmp result.
|
||||
mv a0, s1 # Memory pointer for the case the substring was found.
|
||||
beqz t0, .Lmemmem_end
|
||||
|
||||
addi s1, s1, 1
|
||||
add s2, s2, -1
|
||||
|
||||
j .Lmemmem_loop
|
||||
|
||||
.Lmemmem_nil:
|
||||
li a0, 0
|
||||
|
||||
.Lmemmem_end:
|
||||
|
||||
# Restore the preserved registers.
|
||||
lw s1, 12(sp)
|
||||
lw s2, 8(sp)
|
||||
lw s3, 4(sp)
|
||||
lw s4, 0(sp)
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 20(sp)
|
||||
lw s0, 16(sp)
|
||||
add sp, sp, 24
|
||||
ret
|
||||
|
||||
# Copies memory.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Destination.
|
||||
# a1 - Source.
|
||||
# a2 - Size.
|
||||
#
|
||||
# Preserves a0.
|
||||
.type _memcpy, @function
|
||||
_memcpy:
|
||||
mv t0, a0
|
||||
|
||||
.Lmemcpy_loop:
|
||||
beqz a2, .Lmemcpy_end
|
||||
|
||||
lbu t1, (a1)
|
||||
sb t1, (a0)
|
||||
|
||||
addi a0, a0, 1
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, -1
|
||||
|
||||
j .Lmemcpy_loop
|
||||
|
||||
.Lmemcpy_end:
|
||||
mv a0, t0
|
||||
ret
|
||||
|
||||
# Searches for a string in a string array.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Number of elements in the string array.
|
||||
# a1 - String array.
|
||||
# a2 - Needle length.
|
||||
# a3 - Needle.
|
||||
#
|
||||
# Sets a0 to the 1-based index of the needle in the haystack or to 0 if the
|
||||
# element could not be found.
|
||||
.type _strings_index, @function
|
||||
_strings_index:
|
||||
# Prologue.
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
sw s1, 20(sp)
|
||||
mv s1, a0
|
||||
sw s2, 16(sp)
|
||||
mv s2, a1
|
||||
sw s3, 12(sp)
|
||||
mv s3, a2
|
||||
sw s4, 8(sp)
|
||||
mv s4, a3
|
||||
sw s5, 4(sp)
|
||||
li s5, 0 # Index counter.
|
||||
|
||||
.Lstrings_index_loop:
|
||||
addi s5, s5, 1
|
||||
beqz s1, .Lstrings_index_missing
|
||||
|
||||
lw a2, (s2) # Read the length of the current element in the haystack.
|
||||
bne a2, s3, .Lstrings_index_next # Lengths don't match, skip the iteration.
|
||||
|
||||
addi a0, s2, 4
|
||||
mv a1, s4
|
||||
call _memcmp
|
||||
|
||||
beqz a0, .Lstrings_index_end
|
||||
|
||||
.Lstrings_index_next:
|
||||
# Advance the pointer, reduce the length.
|
||||
lw a2, (s2)
|
||||
addi s2, s2, 4
|
||||
add s2, s2, a2
|
||||
addi s1, s1, -1
|
||||
j .Lstrings_index_loop
|
||||
|
||||
.Lstrings_index_missing:
|
||||
li s5, 0
|
||||
|
||||
.Lstrings_index_end:
|
||||
mv a0, s5
|
||||
|
||||
lw s1, 20(sp)
|
||||
lw s2, 16(sp)
|
||||
lw s3, 12(sp)
|
||||
lw s4, 8(sp)
|
||||
lw s5, 4(sp)
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
add sp, sp, 32
|
||||
ret
|
||||
|
||||
# Compares two strings for equality.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Length of the first string.
|
||||
# a1 - Pointer to the first string.
|
||||
# a2 - Length of the second string.
|
||||
# a3 - Pointer to the second string.
|
||||
#
|
||||
# Sets a0 to 1 if the string are equal, to 0 if not.
|
||||
.type _string_equal, @function
|
||||
_string_equal:
|
||||
# Prologue.
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
# Compare string lengths.
|
||||
bne a0, a2, .Lstring_equal_not_found
|
||||
|
||||
# If lengths match, compare the content.
|
||||
mv a0, a1
|
||||
mv a1, a3
|
||||
# a2 is already set to the length.
|
||||
call _memcmp
|
||||
|
||||
bnez a0, .Lstring_equal_not_found
|
||||
|
||||
li a0, 1
|
||||
j .Lstring_equal_end
|
||||
|
||||
.Lstring_equal_not_found:
|
||||
mv a0, zero
|
||||
|
||||
.Lstring_equal_end:
|
||||
# Epilogue.
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
addi sp, sp, 32
|
||||
ret
|
||||
|
||||
# Sets a0 to the mapping address.
|
||||
.type _mmap, @function
|
||||
_mmap:
|
||||
li a0, 0 # Address at which to create the mapping.
|
||||
li a1, 4096 # The length of the mapping.
|
||||
li a2, PROT_READ | PROT_WRITE # Protection flags.
|
||||
li a3, MAP_ANONYMOUS | MAP_PRIVATE # The mapping is not backed by a file.
|
||||
li a4, -1 # File descriptor.
|
||||
li a5, 0 # Page offset.
|
||||
li a7, SYS_MMAP2
|
||||
ecall
|
||||
|
||||
ret
|
||||
|
||||
# Sets the a0 to the current position in the source text (s1).
|
||||
.type _current, @function
|
||||
_current:
|
||||
mv a0, s1
|
||||
ret
|
||||
|
||||
# Advances the position of the source text.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - The number of bytes to advance.
|
||||
.type _advance, @function
|
||||
_advance:
|
||||
add s1, s1, a0
|
||||
ret
|
||||
|
||||
# Advances the global label counter by 1 setting a0 to the previous value.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - If it is 0, resets the counter to 1.
|
||||
.type _label_counter, @function
|
||||
_label_counter:
|
||||
bnez a0, .Llabel_counter_advance
|
||||
li s2, 0
|
||||
|
||||
.Llabel_counter_advance:
|
||||
mv a0, s2
|
||||
addi s2, s2, 1
|
||||
|
||||
ret
|
30
kernel.ld
Normal file
30
kernel.ld
Normal file
@ -0,0 +1,30 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
OUTPUT_FORMAT("elf32-littleriscv")
|
||||
ENTRY(boot)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x80200000;
|
||||
|
||||
.text :{
|
||||
KEEP(*(.text.boot));
|
||||
*(.text .text.*);
|
||||
}
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata .rodata.*);
|
||||
}
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data .data.*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
__bss = .;
|
||||
*(.bss .bss.* .sbss .sbss.*);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
. += 128 * 1024; /* 128KB */
|
||||
__stack_top = .;
|
||||
}
|
73
kernel.s
Normal file
73
kernel.s
Normal file
@ -0,0 +1,73 @@
|
||||
.global kernel_main, __bss, __bss_end, __stack_top
|
||||
|
||||
.section .rodata
|
||||
|
||||
hello_world: .asciz "\nHello world!\n"
|
||||
|
||||
.section .text
|
||||
|
||||
bzero:
|
||||
la t0, __bss
|
||||
la t1, __bss_end
|
||||
|
||||
.Lbzero_loop:
|
||||
bgt t0, t1, .Lbzero_end
|
||||
sw zero, (t0)
|
||||
addi t0, t0, 4
|
||||
|
||||
.Lbzero_end:
|
||||
ret
|
||||
|
||||
# Arguments:
|
||||
# a0 - Character.
|
||||
.type putchar, @function
|
||||
putchar:
|
||||
li a1, 0
|
||||
li a2, 0
|
||||
li a3, 0
|
||||
li a4, 0
|
||||
li a5, 0
|
||||
li a6, 0
|
||||
li a7, 1 # sbi_console_putchar.
|
||||
|
||||
ecall
|
||||
ret
|
||||
|
||||
.type kernel_main, @function
|
||||
kernel_main:
|
||||
# Prologue.
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
sw s1, 20(sp)
|
||||
|
||||
la s1, hello_world
|
||||
|
||||
.Lkernel_main_if:
|
||||
lw a0, (s1)
|
||||
beqz a0, .Lkernel_main
|
||||
|
||||
call putchar
|
||||
addi s1, s1, 1
|
||||
|
||||
j .Lkernel_main_if
|
||||
|
||||
.Lkernel_main:
|
||||
j .Lkernel_main
|
||||
|
||||
lw s1, 20(sp)
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
add sp, sp, 32
|
||||
ret
|
||||
|
||||
.section .text.boot
|
||||
boot:
|
||||
la a0, __stack_top
|
||||
mv sp, a0 # Set the stack pointer
|
||||
call bzero
|
||||
j kernel_main
|
16
run.sh
Executable file
16
run.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -xue
|
||||
|
||||
# QEMU file path
|
||||
QEMU=qemu-system-riscv32
|
||||
|
||||
# Path to clang and compiler flags
|
||||
CC=../riscv32-ilp32d--glibc/bin/riscv32-linux-gcc
|
||||
CFLAGS="-O2 -g3 -Wall -march=rv32im -mabi=ilp32 -fno-stack-protector -ffreestanding -nostdlib -static"
|
||||
|
||||
# Build the kernel
|
||||
$CC $CFLAGS -T kernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.s common.s
|
||||
|
||||
# Start QEMU
|
||||
$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf
|
Reference in New Issue
Block a user