mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-09-10 07:39:25 -04:00
642 lines
16 KiB
ArmAsm
642 lines
16 KiB
ArmAsm
; $NetBSD: start.S,v 1.1 2014/02/24 07:23:43 skrll Exp $
|
|
|
|
; Copyright (c) 2003 ITOH Yasufumi.
|
|
; All rights reserved.
|
|
;
|
|
; Redistribution and use in source and binary forms, with or without
|
|
; modification, are permitted provided that the following conditions
|
|
; are met:
|
|
; 1. Redistributions of source code must retain the above copyright
|
|
; notice, this list of conditions and the following disclaimer.
|
|
; 2. Redistributions in binary forms are unlimited.
|
|
;
|
|
; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS''
|
|
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
|
|
; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
; THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
.level 1.0
|
|
|
|
.code
|
|
.origin 0
|
|
;
|
|
; LIF (Logical Interchange Format) header
|
|
;
|
|
lifhdr: .byte 0x80,0x00 ; LIF magic
|
|
.string "NetBSD" ; volume label (6 chars, fill with space)
|
|
.origin 0xf0
|
|
; 0xf0
|
|
lif_ipl_addr:
|
|
.word top-lifhdr ; start at 4KB (must be 2KB aligned)
|
|
lif_ipl_size:
|
|
.word 0x00001000 ; size 4KB (must be 2KB aligned)
|
|
lif_ipl_entry:
|
|
.word $START$-top ; entry offset
|
|
|
|
; ipl part 1 starts here
|
|
.origin 4096
|
|
top:
|
|
;
|
|
; IPL startup
|
|
;
|
|
; arg0 = interact flag (1: interactive, 0: otherwise)
|
|
; arg1 = address of first doubleword past the end of ipl part 1
|
|
;
|
|
.export $START$,entry
|
|
$START$:
|
|
b,n start ; 0: entry address
|
|
|
|
; version of interface of primary to secondary boot
|
|
BOOT_IF_VERSION: .equ 0
|
|
; version 0: arg0 = interact flag, arg1 = version (0),
|
|
; arg2 = end addr, arg3 = selected boot partition
|
|
; r1, r3 - r22, r28, r29, r31 = cleared to zeros
|
|
|
|
cksum: .word 0 ; 4: checksum will be stored here
|
|
version: .word BOOT_IF_VERSION ; 8: version of interface
|
|
rsvd1: .word 0 ; 12: future use
|
|
rsvd2: .word 0 ; 16: future use
|
|
rsvd3: .word 0 ; 20: future use
|
|
|
|
start:
|
|
; set data pointer for relocatable data access
|
|
blr %r0,%r27
|
|
; get PSW at entry
|
|
ssm 0,%r4
|
|
.export $global$,data
|
|
$global$:
|
|
|
|
; save parameters for main
|
|
copy %arg0,%r3
|
|
|
|
tmpdiskbufsz: .equ 0x1000 ; 4KB
|
|
tmpdiskbuf_labelsec: .equ 0x0200 ; dbtob(LABELSECTOR)
|
|
tmpdiskbuf_labelsecsz: .equ 512
|
|
tmpdiskbuf_part2: .equ 0x0400
|
|
tmpdiskbuf_part2sz: .equ 0x0400
|
|
tmpdiskbuf_part3: .equ 0x0A00
|
|
tmpdiskbuf_part3sz: .equ 0x0600
|
|
|
|
part1sz: .equ 0x1000
|
|
|
|
; get next free address
|
|
.import _end,data
|
|
addil L%_end-$global$,%r27;%r1
|
|
ldo R%_end-$global$(%r1),%r1
|
|
|
|
; 32bit environment (and this code) requires stack is 64byte aligned.
|
|
ldi 64-1,%r2
|
|
add %r1,%r2,%r1
|
|
andcm %r1,%r2,%r6 ; r6 = tmp disk buffer
|
|
ldo tmpdiskbufsz+64(%r6),%sp ; tmp stack
|
|
|
|
bl print,%rp
|
|
ldo str_startup-$global$(%r27),%arg0
|
|
|
|
;
|
|
; read part 2 and 3 of ipl (see README.ipl)
|
|
;
|
|
|
|
; read disk blocks which contains ipl part 2 and part 3
|
|
copy %r6,%arg0
|
|
ldi 0,%arg2 ; offset = 0
|
|
bl boot_input,%rp
|
|
ldi tmpdiskbufsz,%arg1 ; read size
|
|
|
|
; part 2 address
|
|
ldo top-$global$+part1sz(%r27),%r19
|
|
|
|
; copy part 2
|
|
ldo tmpdiskbuf_part2(%r6),%r20
|
|
addi,tr tmpdiskbuf_part2sz/4,%r0,%r2 ; loop count, skip next
|
|
cpipl2: stws,ma %r1,4(0,%r19) ; write to dst
|
|
addib,uv,n -1,%r2,cpipl2 ; check loop condition
|
|
ldws,ma 4(0,%r20),%r1 ; read from src
|
|
|
|
; copy part 3
|
|
; (r19 already has destination address of part 3)
|
|
ldo tmpdiskbuf_part3(%r6),%r20
|
|
addi,tr tmpdiskbuf_part3sz/4,%r0,%r2 ; loop count, skip next
|
|
cpipl3: stws,ma %r1,4(0,%r19) ; write to dst
|
|
addib,uv,n -1,%r2,cpipl3 ; check loop condition
|
|
ldws,ma 4(0,%r20),%r1 ; read from src
|
|
|
|
; flush data cache / invalidate instruction cache
|
|
ldo top-$global$+part1sz(%r27),%r1 ; part 2 address
|
|
ldi 16,%r20 ; 16: cache line size
|
|
flipl: fdc 0(0,%r1) ; flush data cache line at r1
|
|
comb,< %r1,%r19,flipl
|
|
fic,m %r20(0,%r1) ; flush instruction cache line at r1, r1 += 16
|
|
sync ; I/O operation is guaranteed to finish
|
|
; in eight instructions after sync
|
|
;
|
|
; Now, whole the IPL is loaded
|
|
;
|
|
|
|
; clear BSS
|
|
.import _edata,data
|
|
addil L%_edata-$global$,%r27;%r1
|
|
ldo R%_edata-$global$(%r1),%r1
|
|
clrbss: comb,< %r1,%r6,clrbss
|
|
stws,ma %r0,4(0,%r1)
|
|
|
|
; we have read disklabel -- save it for later use
|
|
.import labelsector,data
|
|
addil L%labelsector-$global$,%r27;%r1
|
|
ldo R%labelsector-$global$(%r1),%r20
|
|
ldo tmpdiskbuf_labelsec(%r6),%r21
|
|
addi,tr tmpdiskbuf_labelsecsz/4,%r0,%r2 ; loop count, skip next
|
|
cplbl: stws,ma %r1,4(0,%r20) ; write to dst
|
|
addib,uv,n -1,%r2,cplbl ; check loop condition
|
|
ldws,ma 4(0,%r21),%r1 ; read from src
|
|
|
|
; set stack
|
|
; (r6 points at free space, 64byte aligned)
|
|
; 32bit environment (and this code) requires stack is 64byte aligned.
|
|
ldo 64(%r6),%sp ; 64 > 48: frame marker (32) + args(up to 4)
|
|
|
|
; stack usage
|
|
; 12bytes arguments
|
|
; 32 frame marker
|
|
|
|
; parameters for main
|
|
copy %r3,%arg0
|
|
copy %r4,%arg2
|
|
|
|
.import ipl_main,entry
|
|
bl ipl_main,%rp
|
|
copy %sp,%arg1
|
|
|
|
; main returned --- perform reset
|
|
bl print,%rp
|
|
ldo str_reset-$global$(%r27),%arg0
|
|
; FALLTHROUGH
|
|
|
|
IOMOD_CMD: .equ 0xFFFC0000 + (4*12)
|
|
IOMOD_CMD_STOP: .equ 0
|
|
IOMOD_CMD_RESET: .equ 5
|
|
|
|
; void reboot(void)
|
|
; void halt(void)
|
|
.export reboot,entry
|
|
.export halt,entry
|
|
reboot:
|
|
addi,tr IOMOD_CMD_RESET,%r0,%r1 ; %r1 = IOMOD_CMD_RESET, skip next
|
|
halt: ldi IOMOD_CMD_STOP,%r1
|
|
iomcmd: ldil L%IOMOD_CMD,%r2
|
|
ldo R%IOMOD_CMD(%r2),%r2
|
|
stwas %r1,0(%r2)
|
|
b,n .
|
|
|
|
str_startup:
|
|
.string "\r\n\n"
|
|
.stringz "NetBSD/hppa FFS/LFS Primary Bootstrap\r\n\n"
|
|
str_reset:
|
|
.stringz "\r\nresetting..."
|
|
.align 4
|
|
|
|
; void dispatch(unsigned interactive, unsigned top, unsigned end, int part,
|
|
; unsigned entry)
|
|
.export dispatch,entry
|
|
dispatch:
|
|
; flush data cache / invalidate instruction cache
|
|
ldi 16,%r20 ; 16: cache line size
|
|
flush: fdc 0(0,%arg1) ; flush data cache line at arg1
|
|
comb,< %arg1,%arg2,flush
|
|
fic,m %r20(0,%arg1) ; flush instruction cache line at arg1, arg1+=16
|
|
sync
|
|
copy %r0,%r1 ; I/O operation is guaranteed to finish
|
|
copy %r0,%r3 ; in eight instructions after sync
|
|
copy %r0,%r4
|
|
copy %r0,%r5 ; while waiting, clear unused registers
|
|
copy %r0,%r6 ; for future compatibility
|
|
copy %r0,%r7
|
|
copy %r0,%r8
|
|
copy %r0,%r9
|
|
copy %r0,%r10
|
|
copy %r0,%r11
|
|
copy %r0,%r12
|
|
copy %r0,%r13
|
|
copy %r0,%r14
|
|
copy %r0,%r15
|
|
copy %r0,%r16
|
|
copy %r0,%r17
|
|
copy %r0,%r18
|
|
copy %r0,%r19
|
|
copy %r0,%r20
|
|
copy %r0,%r21
|
|
copy %r0,%r22
|
|
copy %r0,%r28 ; r23-r26: arg3-arg0, r27: dp
|
|
copy %r0,%r29 ; r30: sp
|
|
copy %r0,%r31
|
|
ldw -52(%sp),%arg1 ; arg4: exec address
|
|
ldo reboot-$global$(%r27),%rp ; reboot if returns
|
|
bv %r0(%arg1) ; execute
|
|
ldi BOOT_IF_VERSION,%arg1
|
|
|
|
;
|
|
; IODC subroutines
|
|
;
|
|
PZ_MEM_CONSOLE: .equ 0x3a0
|
|
PZ_MEM_BOOT: .equ 0x3d0
|
|
PZ_MEM_KEYBOARD: .equ 0x400
|
|
|
|
DEV_PATH: .equ 0x00
|
|
DEV_LAYERS: .equ 0x08
|
|
DEV_HPA: .equ 0x20 ; hard physical address space
|
|
DEV_SPA: .equ 0x24 ; soft physical address space
|
|
DEV_IODC_ENTRY: .equ 0x28
|
|
DEV_CLASS: .equ 0x2c
|
|
DEV_CL_DUPLEX: .equ 0x7 ; full-duplex console class
|
|
|
|
IODC_ENTRY_IO_BOOTIN: .equ 0
|
|
IODC_ENTRY_IO_CONSOLEIN: .equ 2
|
|
IODC_ENTRY_IO_CONSOLEOUT: .equ 3
|
|
|
|
; call_iodc
|
|
; inputs:
|
|
; %ret0 IODC base in page zero
|
|
; %rp return address
|
|
; %r29 arg 8
|
|
; %r19 arg 7
|
|
; %r20 arg 6
|
|
; %r21 arg 5
|
|
; %r25 arg 1
|
|
; outputs
|
|
; all scratch regs undefined, unless defined by the IODC call
|
|
call_iodc:
|
|
; set common arguments in registers
|
|
addil L%retbuf-$global$,%r27;%r1
|
|
ldo R%retbuf-$global$(%r1),%r22 ; arg4: return buffer
|
|
ldo DEV_LAYERS(%ret0),%arg3 ; arg3: layer
|
|
ldw DEV_SPA(%ret0),%arg2 ; arg2: spa
|
|
ldw DEV_HPA(%ret0),%arg0 ; arg0: hpa
|
|
; check if narrow or wide mode
|
|
ssm 0,%r1 ; get PSW
|
|
bb,< %r1,4,call_iodc_64 ; if W, call in 64bit mode
|
|
ldw DEV_IODC_ENTRY(%ret0),%r1 ; ENTRY_IO address
|
|
|
|
; narrow mode
|
|
stw %r29,-68(%sp) ; arg8: maxsize / lang
|
|
stw %r19,-64(%sp) ; arg7: size
|
|
stw %r20,-60(%sp) ; arg6: buf
|
|
stw %r21,-56(%sp) ; arg5: devaddr / unused
|
|
bv %r0(%r1) ; call ENTRY_IO
|
|
stw %r22,-52(%sp) ; arg4: return buffer
|
|
|
|
call_iodc_64:
|
|
.allow 2.0
|
|
; On PA64 convention, arg0 - arg7 are passed in registers.
|
|
; Parameters are placed in INCREASING order.
|
|
; The argument pointer points at the first stack parameter.
|
|
; stack usage:
|
|
; 64bytes allocated for register arguments arg0-arg7
|
|
; 8 arg8 (argument pointer points here)
|
|
; 16 frame marker
|
|
std %r29,-16-8(%sp) ; arg8: maxsize / lang
|
|
; std %sp,-8(%sp) ; psp in frame marker
|
|
bv %r0(%r1) ; call ENTRY_IO
|
|
ldo -16-8(%sp),%r29 ; argument pointer
|
|
.allow
|
|
|
|
;
|
|
; console output
|
|
;
|
|
; void putch(int)
|
|
; void print(const char *string)
|
|
.align 4
|
|
.export putch,entry
|
|
.export print,entry
|
|
putch:
|
|
stwm %arg0,128(%sp) ; fake up a string on the stack
|
|
stb %r0,-124(%sp) ; (see stack usage below)
|
|
addi,tr -125,%sp,%arg0 ; string address, skip next
|
|
print:
|
|
.proc
|
|
.callinfo frame=128,save_rp,no_unwind
|
|
.entry
|
|
ldo 128(%sp),%sp
|
|
stw %rp,-128-20(%sp)
|
|
|
|
; stack usage:
|
|
; 36byte IODC buffer (assume %sp was 64byte aligned)
|
|
; 4 saved reg
|
|
; 88 arguments, frame marker
|
|
; 32bit: 36 (arguments) + 32 (frame marker)
|
|
; 64bit: 72 (arguments) + 16 (frame marker)
|
|
prbufsiz: .equ 36
|
|
|
|
; save callee-saves
|
|
stw %r3,-92(%sp)
|
|
|
|
copy %arg0,%r3
|
|
|
|
prloop:
|
|
copy %r0,%r19
|
|
ldi prbufsiz,%r20
|
|
ldo -128(%sp),%r1
|
|
|
|
strloop:
|
|
ldb 0(%r3),%r2
|
|
comb,= %r2,%r0,endstr
|
|
stbs,ma %r2,1(0,%r1)
|
|
ldo 1(%r19),%r19
|
|
comb,<> %r19,%r20,strloop
|
|
ldo 1(%r3),%r3
|
|
|
|
endstr:
|
|
comb,=,n %r19,%r0,endpr
|
|
|
|
; see IODC 3-51
|
|
; arg0 hpa
|
|
; arg1 option (ENTRY_IO_CONSOLEOUT (3))
|
|
; arg2 spa
|
|
; arg3 ID_addr (pointer to LAYER)
|
|
; arg4 R_addr (pointer to return buffer (64word?))
|
|
; arg5 unused (0)
|
|
; arg6 memaddr (64byte-aligned) string buffer
|
|
; arg7 reqsize
|
|
; arg8 lang (0)
|
|
ldi PZ_MEM_CONSOLE,%ret0 ; IODC base in page zero
|
|
copy %r0,%r29 ; arg8: lang
|
|
; copy %r19,%r19 ; arg7: size
|
|
ldo -128(%sp),%r20 ; arg6: buf
|
|
; copy %r0,%r21 ; arg5: unused
|
|
bl call_iodc,%rp
|
|
ldi IODC_ENTRY_IO_CONSOLEOUT,%arg1 ; arg1: option
|
|
b,n prloop
|
|
|
|
endpr:
|
|
; restore callee-saves
|
|
ldw -92(%sp),%r3
|
|
|
|
; return subroutine
|
|
ldw -128-20(%sp),%rp
|
|
bv %r0(%rp)
|
|
.exit
|
|
ldo -128(%sp),%sp
|
|
.procend
|
|
|
|
;
|
|
; console input
|
|
;
|
|
; int getch(void)
|
|
.align 4
|
|
.export getch,entry
|
|
getch:
|
|
.proc
|
|
.callinfo frame=192,save_rp,no_unwind
|
|
.entry
|
|
stw %rp,-20(%sp)
|
|
ldo 192(%sp),%sp
|
|
|
|
; stack usage:
|
|
; 64byte IODC buffer (assume %sp was 64byte aligned)
|
|
; 40 unused
|
|
; 88 arguments, frame marker
|
|
; 32bit: 36 (arguments) + 32 (frame marker)
|
|
; 64bit: 72 (arguments) + 16 (frame marker)
|
|
|
|
; check if console is full or half duplex
|
|
ldw PZ_MEM_CONSOLE+DEV_CLASS(%r0),%r1 ; device class
|
|
extru %r1,31,4,%r1 ; right 4bits are valid
|
|
ldi PZ_MEM_CONSOLE,%ret0
|
|
comib,=,n DEV_CL_DUPLEX,%r1,getch_console ; use CONSOLE if full
|
|
ldi PZ_MEM_KEYBOARD,%ret0 ; otherwise KEYBOARD
|
|
getch_console:
|
|
|
|
; see IODC 3-50
|
|
; arg0 hpa
|
|
; arg1 option (ENTRY_IO_CONSOLEIN (2))
|
|
; arg2 spa
|
|
; arg3 ID_addr (pointer to LAYER)
|
|
; arg4 R_addr (pointer to return buffer (64word?))
|
|
; arg5 unused (0)
|
|
; arg6 memaddr (64byte-aligned, must have 64byte) data buffer
|
|
; arg7 reqsize
|
|
; arg8 lang (0)
|
|
; copy %rp,%rp ; IODC base in page zero
|
|
copy %r0,%r29 ; arg8: lang
|
|
ldi 1,%r19 ; arg7: size (1)
|
|
ldo -192(%sp),%r20 ; arg6: buf
|
|
; copy %r0,%r21 ; arg5: unused
|
|
bl call_iodc,%rp
|
|
ldi IODC_ENTRY_IO_CONSOLEIN,%arg1 ; arg1: option
|
|
|
|
; make return value
|
|
comb,<> %ret0,%r0,getch_ret ; return -1 on error
|
|
ldi -1,%ret0
|
|
ldi 1,%r19
|
|
|
|
; check if narrow or wide mode
|
|
ssm 0,%r1 ; get PSW
|
|
bb,< %r1,4,getch_64
|
|
addil L%retbuf-$global$,%r27;%r1
|
|
ldw R%retbuf-$global$(%r1),%r2 ; ret[0]
|
|
comclr,<> %r19,%r2,%ret0 ; return 0 if no char available
|
|
getch_retc:
|
|
ldb -192(%sp),%ret0 ; otherwise return the char
|
|
|
|
getch_ret:
|
|
; return subroutine
|
|
ldw -192-20(%sp),%rp
|
|
bv %r0(%rp)
|
|
.exit
|
|
ldo -192(%sp),%sp
|
|
|
|
getch_64:
|
|
.allow 2.0
|
|
ldd R%retbuf-$global$(%r1),%r2 ; ret[0] (64bit)
|
|
b getch_retc
|
|
cmpclr,*<> %r19,%r2,%ret0 ; return 0 if no char available
|
|
.allow
|
|
.procend
|
|
|
|
;
|
|
; read boot device
|
|
;
|
|
; void boot_input(void *buf, unsigned len, unsigned pos)
|
|
.align 4
|
|
.export boot_input,entry
|
|
boot_input:
|
|
.proc
|
|
.callinfo frame=128,save_rp,no_unwind
|
|
.entry
|
|
stw %rp,-20(%sp)
|
|
ldo 128(%sp),%sp
|
|
|
|
; stack usage:
|
|
; 40byte unused (alignment)
|
|
; 88 arguments, frame marker
|
|
; 32bit: 36 (arguments) + 32 (frame marker)
|
|
; 64bit: 72 (arguments) + 16 (frame marker)
|
|
|
|
; see IODC 3-46
|
|
; arg0 hpa
|
|
; arg1 option (ENTRY_IO_BOOTIN (0))
|
|
; arg2 spa
|
|
; arg3 ID_addr (pointer to LAYER)
|
|
; arg4 R_addr (pointer to return buffer (64word?))
|
|
; arg5 devaddr
|
|
; arg6 memaddr (64byte-aligned) string buffer
|
|
; arg7 reqsize
|
|
; arg8 maxsize
|
|
ldi PZ_MEM_BOOT,%ret0 ; IODC base in page zero
|
|
copy %arg1,%r29 ; arg8: maxsize
|
|
copy %arg1,%r19 ; arg7: size
|
|
copy %arg0,%r20 ; arg6: buf
|
|
copy %arg2,%r21 ; arg5: devaddr
|
|
bl call_iodc,%rp
|
|
ldi IODC_ENTRY_IO_BOOTIN,%arg1 ; arg1: option
|
|
|
|
; return subroutine
|
|
ldw -128-20(%sp),%rp
|
|
bv %r0(%rp)
|
|
.exit
|
|
ldo -128(%sp),%sp
|
|
.procend
|
|
|
|
;
|
|
; utilities
|
|
; optimized for size
|
|
;
|
|
|
|
; int strcmp(const char *str1, const char *str2)
|
|
.align 4
|
|
.export strcmp,entry
|
|
strcmp:
|
|
.proc
|
|
.callinfo frame=0,no_calls
|
|
.entry
|
|
ldbs,ma 1(0,%arg0),%r1
|
|
strcmp_loop:
|
|
comb,= %r1,%r0,strcmp_eos
|
|
ldbs,ma 1(0,%arg1),%r19
|
|
comb,=,n %r1,%r19,strcmp_loop
|
|
ldbs,ma 1(0,%arg0),%r1
|
|
strcmp_eos:
|
|
bv %r0(%rp)
|
|
.exit
|
|
sub %r1,%r19,%ret0
|
|
.procend
|
|
|
|
; void memcpy(void *dst, const void *src, unsigned len)
|
|
.align 4
|
|
.export memcpy,entry
|
|
.export memmove,entry
|
|
memcpy:
|
|
memmove:
|
|
.proc
|
|
.callinfo no_unwind ; multiple exit points
|
|
.entry
|
|
; copy %arg0,%ret0 ; uncomment this to conform ANSI
|
|
comb,<<,n %arg0,%arg1,memcpy0 ; copy forward or backward?
|
|
add %arg0,%arg2,%arg0 ; dst end address
|
|
add,tr %arg1,%arg2,%arg1 ; src end address, skip next
|
|
memcpy_bwd:
|
|
stbs,mb %r1,-1(0,%arg0) ; write to dst
|
|
addib,uv,n -1,%arg2,memcpy_bwd ; check loop condition
|
|
ldbs,mb -1(0,%arg1),%r1 ; read from src
|
|
bv,n %r0(%rp) ; return subroutine
|
|
memcpy_fwd:
|
|
stbs,ma %r1,1(0,%arg0) ; write to dst
|
|
memcpy0:
|
|
addib,uv,n -1,%arg2,memcpy_fwd ; check loop condition
|
|
ldbs,ma 1(0,%arg1),%r1 ; read from src
|
|
.exit
|
|
bv,n %r0(%rp) ; return subroutine
|
|
.procend
|
|
|
|
;
|
|
; string table
|
|
; placed here to save space
|
|
;
|
|
.export str_seekseq, data
|
|
.export str_startup, data
|
|
.export str_bit_firmware, data
|
|
.export str_crlf, data
|
|
.export str_space, data
|
|
.export str_rubout, data
|
|
str_seekseq:
|
|
.stringz "repositioning media...\r\n"
|
|
str_bit_firmware:
|
|
.stringz "bit firmware\r\n"
|
|
str_rubout:
|
|
.byte 0x08, 0x20, 0x08, 0x00 ; "\b \b"
|
|
|
|
.export str_bootpart, data
|
|
str_bootpart:
|
|
.string "boot partition (a-p, ! to reboot) [a]:"
|
|
str_space:
|
|
.stringz " "
|
|
.export str_booting_part, data
|
|
str_booting_part:
|
|
.string "\r\nbooting from partition _"
|
|
str_crlf:
|
|
.stringz "\r\n"
|
|
.export str_warn_2GB, data
|
|
str_warn_2GB:
|
|
.stringz "boot partition exceeds 2GB boundary\r\n"
|
|
.export str_warn_unused, data
|
|
str_warn_unused:
|
|
.stringz "unused partition\r\n"
|
|
.export str_nolabel, data
|
|
str_nolabel:
|
|
.stringz "no disklabel\r\n"
|
|
|
|
.export str_filesystem, data
|
|
str_filesystem:
|
|
.stringz "filesystem: _FS\r\n"
|
|
.export str_nofs, data
|
|
str_nofs:
|
|
.stringz "no filesystem found\r\n"
|
|
.export str_lookup, data
|
|
.export str_loading, data
|
|
.export str_at, data
|
|
.export str_dddot, data
|
|
.export str_done, data
|
|
str_lookup:
|
|
.stringz "looking up "
|
|
str_loading:
|
|
.stringz "loading "
|
|
str_at:
|
|
.stringz " at 0x"
|
|
str_dddot:
|
|
.stringz "..."
|
|
str_done:
|
|
.stringz "done\r\n"
|
|
|
|
.export str_boot1, data
|
|
.export str_boot2, data
|
|
.export str_boot3, data
|
|
str_boot1:
|
|
.stringz "boot.hp700"
|
|
str_boot2:
|
|
.stringz "boot"
|
|
str_boot3:
|
|
.stringz "usr/mdec/boot"
|
|
|
|
.export str_noboot, data
|
|
str_noboot:
|
|
.stringz "no secondary boot found\r\n"
|
|
|
|
.export str_ukfmt, data
|
|
str_ukfmt:
|
|
.stringz ": unknown format -- exec from top\r\n"
|
|
|
|
.bss
|
|
.align 64
|
|
retbuf: .block 32*8 ; *4 for narrow mode / *8 for wide mode
|
|
|
|
.export diskbuf,data
|
|
.align 64
|
|
diskbuf:
|
|
.block 2048
|