Files
prog8/codeGenM68k/docs/kernel-example.asm
T
2026-07-04 23:18:03 +02:00

412 lines
9.6 KiB
NASM

; A working m68k kernel for use in QEMU `-M virt` m68k machine.
; It parses the bootinfo chunks, prints stuff to the uart output, and reads input as well.
section .text,code
xref _end_of_code
global _start
_start: move.l #$fffc,sp
bsr bootinfo_parse
move.l ram_top,d0
beq 1$
sub.l #256,d0
move.l d0,sp
1$:
movea.l #str_welcome,a0
bsr puts
2$: bsr getchar
move.b d0,d1
move.b d1,(a0)
bsr putchar
cmpi.b #13,d1
bne 3$
move.b #10,d0
bsr putchar
3$: cmpi.b #$1b,d1
bne 2$
bsr do_halt
bra 2$
; ============================================================
; bootinfo_parse -- iterate bootinfo records and print them
; ============================================================
bootinfo_parse:
move.l d2,-(sp)
move.l d4,-(sp)
moveq #0,d4
move.l #_end_of_code,d0
addq.l #1,d0
lsr.l #1,d0
lsl.l #1,d0
movea.l d0,a2
bi_loop:
clr.l d0
move.w (a2)+,d0
beq bi_done
move.l d0,d2
cmpi.w #2,d2
bne 1$
moveq #1,d4
1$:
clr.l d1
move.w (a2)+,d1
move.l a2,a3
lea (-4,a2,d1.l),a2
subq.l #4,d1
movea.l #str_indent,a0
bsr puts
move.l a3,d0
subq.l #4,d0
bsr puthex8
movea.l #str_colon_space,a0
bsr puts
move.l d2,d0
bsr bi_print_tag
bsr bi_newline
movea.l #str_pad,a0
bsr puts
move.l a3,-(sp)
move.l d1,-(sp)
move.l d2,-(sp)
bsr bi_print_data
add.w #12,sp
bsr bi_newline
bra bi_loop
bi_done:
tst.l d4
bne 1$
movea.l #str_indent,a0
bsr puts
movea.l #str_no_cputype,a0
bsr puts
bsr bi_newline
1$: move.l (sp)+,d4
move.l (sp)+,d2
rts
bi_newline:
movea.l #str_newline,a0
bra puts
; ============================================================
; bi_print_tag -- print tag name for value in d0
; ============================================================
bi_print_tag:
cmpi.w #1,d0
beq bi_tag_machtype
cmpi.w #2,d0
beq bi_tag_cputype
cmpi.w #3,d0
beq bi_tag_fputype
cmpi.w #4,d0
beq bi_tag_mmutype
cmpi.w #5,d0
beq bi_tag_memchunk
cmpi.w #6,d0
beq bi_tag_ramdisk
cmpi.w #7,d0
beq bi_tag_cmdline
cmpi.w #8,d0
beq bi_tag_rngseed
cmpi.w #$8000,d0
beq bi_tag_version
cmpi.w #$8001,d0
beq bi_tag_pic
cmpi.w #$8002,d0
beq bi_tag_rtc
cmpi.w #$8003,d0
beq bi_tag_tty
cmpi.w #$8004,d0
beq bi_tag_virtio
cmpi.w #$8005,d0
beq bi_tag_ctrl
movea.l #str_hex_prefix,a0
bsr puts
bsr puthex8
rts
bi_tag_machtype: movea.l #str_machtype,a0
bra puts
bi_tag_cputype: movea.l #str_cputype,a0
bra puts
bi_tag_fputype: movea.l #str_fputype,a0
bra puts
bi_tag_mmutype: movea.l #str_mmutype,a0
bra puts
bi_tag_memchunk: movea.l #str_memchunk,a0
bra puts
bi_tag_ramdisk: movea.l #str_ramdisk,a0
bra puts
bi_tag_cmdline: movea.l #str_cmdline,a0
bra puts
bi_tag_rngseed: movea.l #str_rngseed,a0
bra puts
bi_tag_version: movea.l #str_version,a0
bra puts
bi_tag_pic: movea.l #str_pic,a0
bra puts
bi_tag_rtc: movea.l #str_rtc,a0
bra puts
bi_tag_tty: movea.l #str_tty,a0
bra puts
bi_tag_ctrl: movea.l #str_ctrl,a0
bra puts
bi_tag_virtio: movea.l #str_virtio,a0
bra puts
; ============================================================
; bi_print_data -- print data based on tag type
; stack args (low to high): tag, size, data_ptr
; ============================================================
bi_print_data:
move.l 4(sp),d0
move.l 8(sp),d1
movea.l 12(sp),a3
cmpi.w #1,d0
beq bi_data_machtype
cmpi.w #2,d0
beq bi_data_cputype
cmpi.w #3,d0
beq bi_data_u32
cmpi.w #4,d0
beq bi_data_u32
cmpi.w #$8000,d0
beq bi_data_u32
cmpi.w #5,d0
beq bi_data_memchunk
cmpi.w #6,d0
beq bi_data_base_size
cmpi.w #7,d0
beq bi_data_str
cmpi.w #8,d0
beq bi_data_hex
cmpi.w #$8001,d0
beq bi_data_base_count
cmpi.w #$8002,d0
beq bi_data_base_count
cmpi.w #$8003,d0
beq bi_data_base_count
cmpi.w #$8004,d0
beq bi_data_base_count
cmpi.w #$8005,d0
beq bi_data_base_count
bi_data_hex:
move.l d1,d3
1$: move.b (a3)+,d0
bsr puthex2
subq.l #1,d3
beq 2$
movea.l #str_space,a0
bsr puts
bra 1$
2$: rts
bi_data_u32:
move.l (a3),d0
bra puthex8
bi_data_memchunk:
move.l (a3),-(sp)
movea.l #str_mem_at,a0
bsr puts
move.l (sp)+,d0
bsr puthex8
movea.l #str_to,a0
bsr puts
move.l 4(a3),d0
add.l (a3),d0
move.l d0,ram_top
bsr puthex8
movea.l #str_size,a0
bsr puts
move.l 4(a3),d0
bra puthex8
bi_data_base_size:
movea.l #str_base,a0
bsr puts
move.l (a3),d0
bsr puthex8
movea.l #str_size,a0
bsr puts
move.l 4(a3),d0
bra puthex8
bi_data_base_count:
movea.l #str_base,a0
bsr puts
move.l (a3),d0
bsr puthex8
movea.l #str_count,a0
bsr puts
move.l 4(a3),d0
bra puthex8
bi_data_str:
movea.l a3,a0
bra puts
bi_data_machtype:
move.l (a3),d0
cmpi.l #14,d0
beq 1$
bra puthex8
1$: movea.l #str_mach_virt,a0
bra puts
bi_data_cputype:
move.l (a3),d0
beq 6$
btst #0,d0
bne 1$
btst #1,d0
bne 2$
btst #2,d0
bne 3$
btst #3,d0
bne 4$
btst #4,d0
bne 5$
bra puthex8
1$: movea.l #str_cpu68020,a0
bra puts
2$: movea.l #str_cpu68030,a0
bra puts
3$: movea.l #str_cpu68040,a0
bra puts
4$: movea.l #str_cpu68060,a0
bra puts
5$: movea.l #str_coldfire,a0
bra puts
6$: movea.l #str_cpu68000,a0
bra puts
; ============================================================
puts: move.b (a0)+,d0
beq puts_rts
bsr putchar
bra puts
puts_rts:
rts
; ============================================================
puthex8:
move.l d2,-(sp)
move.l d3,-(sp)
move.l d0,d2
moveq #28,d3
1$: move.l d2,d0
lsr.l d3,d0
and.b #$f,d0
add.b #'0',d0
cmp.b #'9',d0
bls 2$
add.b #7,d0
2$: bsr putchar
subq.l #4,d3
bpl 1$
move.l (sp)+,d3
move.l (sp)+,d2
rts
; ============================================================
puthex2:
move.l d2,-(sp)
move.l d3,-(sp)
move.l d0,d2
moveq #4,d3
1$: move.l d2,d0
lsr.l d3,d0
and.b #$f,d0
add.b #'0',d0
cmp.b #'9',d0
bls 2$
add.b #7,d0
2$: bsr putchar
subq.l #4,d3
bpl 1$
move.l (sp)+,d3
move.l (sp)+,d2
rts
; ============================================================
putchar:
movea.l #$ff008000,a1
move.l d0,(a1)
rts
; ============================================================
getchar:
suba.l #16,sp
movea.l #$ff008004,a1
1$: move.l (a1),d0
tst.l d0
beq 1$
movea.l #$ff008010,a1
move.l sp,(a1)
movea.l #$ff008014,a1
move.l #1,(a1)
movea.l #$ff008008,a1
move.l #3,(a1)
move.b (sp),d0
adda.l #16,sp
rts
; ============================================================
do_halt:
movea.l #$ff009004,a1
move.l #2,(a1)
rts
; ============================================================
; Strings
; ============================================================
str_indent: dc.b " ",0
str_colon_space: dc.b ": ",0
str_pad: dc.b " ",0
str_newline: dc.b 10,0
str_base: dc.b "base=0x",0
str_size: dc.b " size=0x",0
str_count: dc.b " count=0x",0
str_mem_at: dc.b "mem at 0x",0
str_to: dc.b " - 0x",0
str_space: dc.b " ",0
str_hex_prefix: dc.b "TAG_0x",0
str_mach_virt: dc.b "MACH_VIRT",0
str_cpu68000: dc.b "CPU_68000",0
str_cpu68020: dc.b "CPU_68020",0
str_cpu68030: dc.b "CPU_68030",0
str_cpu68040: dc.b "CPU_68040",0
str_cpu68060: dc.b "CPU_68060",0
str_coldfire: dc.b "ColdFire",0
str_no_cputype: dc.b "(no BI_CPUTYPE - assuming CPU_68000)",0
str_machtype: dc.b "BI_MACHTYPE",0
str_cputype: dc.b "BI_CPUTYPE",0
str_fputype: dc.b "BI_FPUTYPE",0
str_mmutype: dc.b "BI_MMUTYPE",0
str_memchunk: dc.b "BI_MEMCHUNK",0
str_ramdisk: dc.b "BI_RAMDISK",0
str_cmdline: dc.b "BI_COMMAND_LINE",0
str_rngseed: dc.b "BI_RNG_SEED",0
str_version: dc.b "BI_VIRT_QEMU_VER",0
str_pic: dc.b "BI_VIRT_GF_PIC",0
str_rtc: dc.b "BI_VIRT_GF_RTC",0
str_tty: dc.b "BI_VIRT_GF_TTY",0
str_ctrl: dc.b "BI_VIRT_CTRL",0
str_virtio: dc.b "BI_VIRT_VIRTIO",0
str_welcome: dc.b "Hello from m68k! (ESC to halt)",10,0
align 4
ram_top: dc.l 0