From: rs <> Date: Sat, 4 Oct 2025 06:19:51 +0000 (-0500) Subject: Add multi-file assembly project X-Git-Url: https://git.the-white-hart.net/?a=commitdiff_plain;h=d44729f22302b25f94ecc8705b70de663ea27804;p=vhdl Add multi-file assembly project --- diff --git a/projects/cpu_0/asm/build.sh b/projects/cpu_0/asm/build.sh new file mode 100755 index 0000000..88dacf9 --- /dev/null +++ b/projects/cpu_0/asm/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -ev + +# runtime.asm must come first to place the ISR entry at address zero +./as.py -o writer.bin -m writer.map runtime.asm vga_console.asm host.asm ps2_keyboard.asm uart_console.asm timers.asm entry.asm diff --git a/projects/cpu_0/asm/entry.asm b/projects/cpu_0/asm/entry.asm new file mode 100644 index 0000000..73ce9b1 --- /dev/null +++ b/projects/cpu_0/asm/entry.asm @@ -0,0 +1,20 @@ +start: + ( Send greetz to the l33tz ) + #32 greetz_uart call uart_puts + #32 greetz_vga call vga_console_puts + + #8 0xa5i8 call host_seg_upper_set + #8 0xc3i8 call host_seg_lower_set + #8 0x02i8 call host_seg_dp_set + +halt: + #8 0xc0i8 #32 host_swled !8 drop +_halt: + jmp _halt + + +greetz_uart: + "Hellorld," 0x20i8 "through" 0x20i8 "the" 0x20i8 "UART!" 0x0ai8 0x0di8 0x00i8 + +greetz_vga: + "Hellorld," 0x20i8 "through" 0x20i8 "VGA!" 0x0ai8 0x0di8 0x00i8 diff --git a/projects/cpu_0/asm/host.asm b/projects/cpu_0/asm/host.asm new file mode 100644 index 0000000..ec340ad --- /dev/null +++ b/projects/cpu_0/asm/host.asm @@ -0,0 +1,105 @@ +( Initialize host controller with reasonable defaults ) +( -- ) +host_reset: + ( Clear LEDs ) + #8 0x00i8 #32 host_swled !8 drop + #8 0xffi8 #32 host_sseg0 !8 drop + #8 0xffi8 #32 host_sseg1 !8 drop + #8 0xffi8 #32 host_sseg2 !8 drop + #8 0xffi8 #32 host_sseg3 !8 drop + ; + + +( Host flag interrupt ) +( -- ) +host_int: + ( Just acknowledge the interrupt and move on ) + #32 host_flags @8 + #32 host_flags !8 drop + ; + + +( Print a byte to the seven-segment display upper byte ) +( b -- ) +host_seg_upper_set: + dup #8 0x0fi8 & ( Extract lower nibble ) + #32 host_seg_lut + @8 ( Look up segment value ) + #32 host_sseg2 @8 ( Read existing value ) + #8 0x80i8 & | ( Mask out only the decimal point and combine ) + #32 host_sseg2 !8 drop ( Write back to segment register ) + + lsr lsr lsr lsr ( Extract upper nibble ) + #32 host_seg_lut + @8 ( Look up segment value ) + #32 host_sseg3 @8 ( Read existing value ) + #8 0x80i8 & | ( Mask out only decimal point and combine ) + #32 host_sseg3 !8 drop ( Write back to segment register ) + + ; + + +( Print a byte to the seven-segment display lower byte ) +( b -- ) +host_seg_lower_set: + dup #8 0x0fi8 & ( Extract lower nibble ) + #32 host_seg_lut + @8 ( Look up segment value ) + #32 host_sseg0 @8 ( Read existing value ) + #8 0x80i8 & | ( Mask out only the decimal point and combine ) + #32 host_sseg0 !8 drop ( Write back to segment register ) + + lsr lsr lsr lsr ( Extract upper nibble ) + #32 host_seg_lut + @8 ( Look up segment value ) + #32 host_sseg1 @8 ( Read existing value ) + #8 0x80i8 & | ( Mask out only decimal point and combine ) + #32 host_sseg1 !8 drop ( Write back to segment register ) + + ; + + +( Clear the seven-segment display upper byte ) +( -- ) +seg_upper_clr: + #32 host_sseg2 @8 #8 0x7fi8 | ( Read original value and clear all segments except point ) + #32 host_sseg2 !8 drop ( Write back into segment register ) + #32 host_sseg3 @8 #8 0x7fi8 | ( Read original value and clear all segments except point ) + #32 host_sseg3 !8 drop ( Write back into segment register ) + ; + + +( Clear the seven-segment display lower byte ) +( -- ) +seg_upper_clr: + #32 host_sseg0 @8 #8 0x7fi8 | ( Read original value and clear all segments except point ) + #32 host_sseg0 !8 drop ( Write back into segment register ) + #32 host_sseg1 @8 #8 0x7fi8 | ( Read original value and clear all segments except point ) + #32 host_sseg1 !8 drop ( Write back into segment register ) + ; + + +( Turn on a decimal point on the seven-segment display ) +( n -- ) +host_seg_dp_set: + dup #8 0x03i8 - jn _host_seg_dp_set_x + #32 host_sseg0 + + dup @8 #8 0x7fi8 & + swap !8 +_host_seg_dp_set_x: + drop ; + + +( Turn off a decimal point on the seven-segment display ) +( n -- ) +host_seg_dp_clr: + dup #8 0x03i8 - jn _host_seg_dp_clr_x + #32 host_sseg0 + + dup @8 #8 0x80i8 | + swap !8 +_host_seg_dp_clr_x: + drop ; + + +( Look up table for seven-segment values for hex characters ) +host_seg_lut: + 0x40i8 0x79i8 0x24i8 0x30i8 + 0x19i8 0x12i8 0x02i8 0x78i8 + 0x00i8 0x10i8 0x08i8 0x03i8 + 0x46i8 0x21i8 0x06i8 0x0ei8 diff --git a/projects/cpu_0/asm/ps2_keyboard.asm b/projects/cpu_0/asm/ps2_keyboard.asm new file mode 100644 index 0000000..3510b0f --- /dev/null +++ b/projects/cpu_0/asm/ps2_keyboard.asm @@ -0,0 +1,13 @@ +( Reset the PS2 controller with reasonable defaults ) +( -- ) +ps2_reset: + ( Enable PS2 block and Rx interrupt ) + #8 0x41i8 #32 ps2_ctrl !8 drop + #8 0x01i8 #32 ps2_imask !8 drop + ; + + +( PS2 interface interrupt ) +( -- ) +ps2_int: + ; diff --git a/projects/cpu_0/asm/runtime.asm b/projects/cpu_0/asm/runtime.asm new file mode 100644 index 0000000..1798a0c --- /dev/null +++ b/projects/cpu_0/asm/runtime.asm @@ -0,0 +1,189 @@ +( ---------------------------------------------------------------------------- ) +( Global address definitions ) + + +( VGA region bases ) +vga_scr=0x02000000 +vga_tile=0x02004000 +vga_pal=0x02006000 + +( host registers ) +host_ctrl=0x02008000 +host_flags=0x02008001 +host_mbox=0x02008002 +host_swled=0x02008003 +host_sseg0=0x02008004 +host_sseg1=0x02008005 +host_sseg2=0x02008006 +host_sseg3=0x02008007 + +( ps2 registers ) +ps2_ctrl=0x02008008 +ps2_imask=0x02008009 +ps2_iflag=0x0200800a +ps2_error=0x0200800b +ps2_data=0x0200800c + +( rs232 registers ) +uart_ctrl=0x02008010 +uart_baudl=0x02008011 +uart_baudh=0x02008012 +uart_imask=0x02008013 +uart_iflag=0x02008014 +uart_data=0x02008015 + +( timer registers ) +timer0_ctrl=0x02008018 +timer0_count_l=0x02008019 +timer0_count_m=0x0200801a +timer0_count_h=0x0200801b +timer1_ctrl=0x0200801c +timer1_count_l=0x0200801d +timer1_count_m=0x0200801e +timer1_count_h=0x0200801f + + +( ---------------------------------------------------------------------------- ) +( Interrupt service routines ) + + +( ISR common entry point ) +( ivec -- ) +isr: + dup #8 5i8 - jn isr_unknown + dup + dup + #32 isr_jumptable + @32 >r ; + + align +isr_jumptable: + isr_reset + isr_host + isr_ps2 + isr_uart + isr_timer0 + isr_timer1 + + +( Reset ) +( -- ) +isr_reset: + ( Perform device-specific reset/init ) + call vga_reset + call host_reset + call ps2_reset + call uart_reset + call timer_reset + + ( enable interrupts and start ) + ien jmp start + + +( Host controller flags ) +( -- ) +isr_host: + call host_int + ien ; + + +( PS2 host interface ) +( -- ) +isr_ps2: + call ps2_int + ien ; + + +( RS232 UART ) +( -- ) +isr_uart: + call uart_int + ien ; + + +( Timer 0 ) +( -- ) +isr_timer0: + call timer0_int + ien ; + + +( Timer 1 ) +( -- ) +isr_timer1: + call timer1_int + ien ; + + +( Unknown source ) +( ivec -- ) +isr_unknown: + #32 host_swled !8 drop idis +_isr_unknown_halt: + jmp _isr_unknown_halt + + +( ---------------------------------------------------------------------------- ) +( Utility subroutines ) + + +( Copy block of bytes, allowing for overlap ) +( dest src count -- ) +mem_move: + >r swap + >r dup r> swap + >r dup r> swap + - ( dest-src ) + dup jz _mem_move_none + jp _mem_move_back + + ( Copy the block front-to-back ) +_mem_move_front_loop: + r@ jz _mem_move_done + >r dup @8 r@ !8 drop + #8 1i8 + r> #8 1i8 + + #8 1i8 r> - >r + jmp _mem_move_front_loop + +_mem_move_back: + ( Copy the block back-to-front ) + r@ swap >r + + r> r@ + +_mem_move_back_loop: + r@ jz _mem_move_done + #8 1i8 swap - + >r #8 1i8 swap - + dup @8 r@ !8 drop r> + #8 1i8 r> - >r + jmp _mem_move_back_loop + +_mem_move_none: + drop +_mem_move_done: + r> drop drop drop ; + + +( Fill a block of memory with an 8-bit value ) +( dest value count -- ) +mem_set_8: + >r +_mem_set_8_loop: + r@ jz _mem_set_8_done + >r dup r> swap !8 + >r #8 1i8 + r> + #8 1i8 r> - >r + jmp _mem_set_8_loop +_mem_set_8_done: + r> drop drop drop ; + + +( Fill a block of memory with a 16-bit value, little-endian ) +( dest value count -- ) +mem_set_16: + >r +_mem_set_16_loop: + r@ jz _mem_set_16_done + >r dup r@ swap !8 drop + #8 1i8 + dup r@ lsr lsr lsr lsr lsr lsr lsr lsr swap !8 drop + #8 1i8 + r> + #8 1i8 r> - >r + jmp _mem_set_16_loop +_mem_set_16_done: + r> drop drop drop ; diff --git a/projects/cpu_0/asm/timers.asm b/projects/cpu_0/asm/timers.asm new file mode 100644 index 0000000..5557878 --- /dev/null +++ b/projects/cpu_0/asm/timers.asm @@ -0,0 +1,21 @@ +( Reset the timer blocks with reasonable defaults ) +( -- ) +timer_reset: + ( Enable timer 0 with 1s period, auto-restart ) + ( #8 0x02i8 #32 timer0_count_h !8 drop ) + ( #8 0xfai8 #32 timer0_count_m !8 drop ) + ( #8 0xf0i8 #32 timer0_count_l !8 drop ) + ( #8 0x0fi8 #32 timer0_ctrl !8 drop ) + ; + + +( Timer 0 interrupt ) +( -- ) +timer0_int: + ; + + +( Timer 1 interrupt ) +( -- ) +timer1_int: + ; diff --git a/projects/cpu_0/asm/uart_console.asm b/projects/cpu_0/asm/uart_console.asm new file mode 100644 index 0000000..f0895ea --- /dev/null +++ b/projects/cpu_0/asm/uart_console.asm @@ -0,0 +1,51 @@ +( Reset the UART with reasonable defaults ) +( -- ) +uart_reset: + ( 9600 baud, enable Tx/Rx ) + #8 0x01i8 #32 uart_baudh !8 drop + #8 0x46i8 #32 uart_baudl !8 drop + ( #8 0x01i8 #32 uart_imask !8 drop ) + #8 0x13i8 #32 uart_ctrl !8 drop + ; + + +( UART interrupt ) +( -- ) +uart_int: + ; + + +( Print a byte out the UART ) +( c -- ) +uart_putc: + ( Wait for available space in the Tx FIFO ) +_uart_putc_wait: + #32 uart_iflag @8 + #8 0x04i8 & jz _uart_putc_wait + + ( Write byte to UART data register ) + #32 uart_data !8 drop ; + + +( Print an ASCIIZ string out the UART ) +( &s -- ) +uart_puts: +_uart_puts_loop: + dup @8 dup jz _uart_puts_done + call uart_putc + #8 0x01i8 + jmp _uart_puts_loop +_uart_puts_done: + drop drop ; + + +( Print a hex byte ) +( b -- ) +uart_put_hex8: + dup #8 0xf0i8 & lsr lsr lsr lsr + #32 uart_xdigit_lut + @8 call uart_putc + #8 0x0fi8 & + #32 uart_xdigit_lut + @8 call uart_putc + ; + + +uart_xdigit_lut: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" diff --git a/projects/cpu_0/asm/vga_console.asm b/projects/cpu_0/asm/vga_console.asm new file mode 100644 index 0000000..3111cc0 --- /dev/null +++ b/projects/cpu_0/asm/vga_console.asm @@ -0,0 +1,59 @@ +( Initialize VGA hardware to some reasonable defaults ) +vga_reset: + ( Write palette to VGA controller ) + #8 0x00i8 #32 vga_pal #8 0x00i8 + !8 drop ( black ) + #8 0x60i8 #32 vga_pal #8 0x01i8 + !8 drop + #8 0x03i8 #32 vga_pal #8 0x02i8 + !8 drop + #8 0x01i8 #32 vga_pal #8 0x03i8 + !8 drop ( dark blue ) + #8 0x6ci8 #32 vga_pal #8 0x04i8 + !8 drop + #8 0x0di8 #32 vga_pal #8 0x05i8 + !8 drop + #8 0x61i8 #32 vga_pal #8 0x06i8 + !8 drop + #8 0x6di8 #32 vga_pal #8 0x07i8 + !8 drop ( light gray ) + #8 0x92i8 #32 vga_pal #8 0x08i8 + !8 drop ( dark gray ) + #8 0xe0i8 #32 vga_pal #8 0x09i8 + !8 drop + #8 0x1ci8 #32 vga_pal #8 0x0ai8 + !8 drop + #8 0x13i8 #32 vga_pal #8 0x0bi8 + !8 drop ( light blue ) + #8 0xfci8 #32 vga_pal #8 0x0ci8 + !8 drop + #8 0x1fi8 #32 vga_pal #8 0x0di8 + !8 drop + #8 0xe3i8 #32 vga_pal #8 0x0ei8 + !8 drop + #8 0xffi8 #32 vga_pal #8 0x0fi8 + !8 drop ( white ) + + ( TODO: Reload tile memory? ) + + ( Initialize console ) + #8 0x00i8 #32 vga_cursor_loc !32 drop ( Set the cursor to the beginning of the screen ) + #8 0x3bi8 #32 vga_cursor_col !8 drop ( Set the cursor color to light blue on dark blue ) + + ( Clear screen ) + #32 vga_scr #32 0x00003b20i32 #32 4800i32 call mem_set_16 + + ; + + +( Print a character to the VGA display ) +( c -- ) +vga_console_putc: + #32 vga_scr #32 vga_cursor_loc @32 + dup >r + !8 drop + #32 vga_cursor_col @8 r> #8 1i8 + !8 drop + #32 vga_cursor_loc dup @32 #8 0x02i8 + swap !32 drop + ; + + +( Print an ASCIIZ string out the VGA display ) +( &s -- ) +vga_console_puts: +_vga_console_puts_loop: + dup @8 dup jz _vga_console_puts_done + call vga_console_putc + #8 0x01i8 + jmp _vga_console_puts_loop +_vga_console_puts_done: + drop drop ; + + +( ---------------------------------------------------------------------------- ) +( RAM variables ) + + +vga_cursor_loc=0x01000000 +vga_cursor_col=0x01000004