Home | History | Annotate | Line # | Download | only in xxboot
      1 ;	$NetBSD: start.S,v 1.1 2014/02/24 07:23:43 skrll Exp $
      2 
      3 ; Copyright (c) 2003 ITOH Yasufumi.
      4 ; All rights reserved.
      5 ;
      6 ; Redistribution and use in source and binary forms, with or without
      7 ; modification, are permitted provided that the following conditions
      8 ; are met:
      9 ; 1. Redistributions of source code must retain the above copyright
     10 ;    notice, this list of conditions and the following disclaimer.
     11 ; 2. Redistributions in binary forms are unlimited.
     12 ;
     13 ; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS''
     14 ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15 ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16 ; PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
     17 ; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18 ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19 ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20 ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21 ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22 ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23 ; THE POSSIBILITY OF SUCH DAMAGE.
     24 
     25 	.level	1.0
     26 
     27 	.code
     28 	.origin	0
     29 	;
     30 	; LIF (Logical Interchange Format) header
     31 	;
     32 lifhdr:	.byte	0x80,0x00	; LIF magic
     33 	.string	"NetBSD"	; volume label (6 chars, fill with space)
     34 	.origin	0xf0
     35 	; 0xf0
     36 lif_ipl_addr:
     37 	.word	top-lifhdr	; start at 4KB (must be 2KB aligned)
     38 lif_ipl_size:
     39 	.word	0x00001000	; size 4KB (must be 2KB aligned)
     40 lif_ipl_entry:
     41 	.word	$START$-top	; entry offset
     42 
     43 	; ipl part 1 starts here
     44 	.origin	4096
     45 top:
     46 	;
     47 	; IPL startup
     48 	;
     49 	; arg0 = interact flag (1: interactive, 0: otherwise)
     50 	; arg1 = address of first doubleword past the end of ipl part 1
     51 	;
     52 	.export $START$,entry
     53 $START$:
     54 	b,n	start			; 0: entry address
     55 
     56 ; version of interface of primary to secondary boot
     57 BOOT_IF_VERSION:	.equ	0
     58 ; version 0: arg0 = interact flag, arg1 = version (0),
     59 ;	     arg2 = end addr, arg3 = selected boot partition
     60 ;	     r1, r3 - r22, r28, r29, r31 = cleared to zeros
     61 
     62 cksum:		.word	0		; 4: checksum will be stored here
     63 version:	.word	BOOT_IF_VERSION	; 8: version of interface
     64 rsvd1:		.word	0		; 12: future use
     65 rsvd2:		.word	0		; 16: future use
     66 rsvd3:		.word	0		; 20: future use
     67 
     68 start:
     69 	; set data pointer for relocatable data access
     70 	blr	%r0,%r27
     71 	; get PSW at entry
     72 	ssm	0,%r4
     73 	.export	$global$,data
     74 $global$:
     75 
     76 	; save parameters for main
     77 	copy	%arg0,%r3
     78 
     79 tmpdiskbufsz:		.equ	0x1000	; 4KB
     80 tmpdiskbuf_labelsec:	.equ	0x0200	; dbtob(LABELSECTOR)
     81 tmpdiskbuf_labelsecsz:	.equ	512
     82 tmpdiskbuf_part2:	.equ	0x0400
     83 tmpdiskbuf_part2sz:	.equ	0x0400
     84 tmpdiskbuf_part3:	.equ	0x0A00
     85 tmpdiskbuf_part3sz:	.equ	0x0600
     86 
     87 part1sz:		.equ	0x1000
     88 
     89 	; get next free address
     90 	.import	_end,data
     91 	addil	L%_end-$global$,%r27;%r1
     92 	ldo	R%_end-$global$(%r1),%r1
     93 
     94 	; 32bit environment (and this code) requires stack is 64byte aligned.
     95 	ldi	64-1,%r2
     96 	add	%r1,%r2,%r1
     97 	andcm	%r1,%r2,%r6			; r6 = tmp disk buffer
     98 	ldo	tmpdiskbufsz+64(%r6),%sp	; tmp stack
     99 
    100 	bl	print,%rp
    101 	ldo	str_startup-$global$(%r27),%arg0
    102 
    103 	;
    104 	; read part 2 and 3 of ipl (see README.ipl)
    105 	;
    106 
    107 	; read disk blocks which contains ipl part 2 and part 3
    108 	copy	%r6,%arg0
    109 	ldi	0,%arg2			; offset = 0
    110 	bl	boot_input,%rp
    111 	ldi	tmpdiskbufsz,%arg1	; read size
    112 
    113 	; part 2 address
    114 	ldo	top-$global$+part1sz(%r27),%r19
    115 
    116 	; copy part 2
    117 	ldo	tmpdiskbuf_part2(%r6),%r20
    118 	addi,tr	tmpdiskbuf_part2sz/4,%r0,%r2	; loop count, skip next
    119 cpipl2:	stws,ma		%r1,4(0,%r19)		; write to dst
    120 	addib,uv,n	-1,%r2,cpipl2		; check loop condition
    121 	ldws,ma		4(0,%r20),%r1		; read from src
    122 
    123 	; copy part 3
    124 	; (r19 already has destination address of part 3)
    125 	ldo	tmpdiskbuf_part3(%r6),%r20
    126 	addi,tr	tmpdiskbuf_part3sz/4,%r0,%r2	; loop count, skip next
    127 cpipl3:	stws,ma		%r1,4(0,%r19)		; write to dst
    128 	addib,uv,n	-1,%r2,cpipl3		; check loop condition
    129 	ldws,ma		4(0,%r20),%r1		; read from src
    130 
    131 	; flush data cache / invalidate instruction cache
    132 	ldo	top-$global$+part1sz(%r27),%r1	; part 2 address
    133 	ldi	16,%r20		; 16: cache line size
    134 flipl:	fdc	0(0,%r1)	; flush data cache line at r1
    135 	comb,<	%r1,%r19,flipl
    136 	fic,m	%r20(0,%r1)	; flush instruction cache line at r1, r1 += 16
    137 	sync			; I/O operation is guaranteed to finish
    138 				; in eight instructions after sync
    139 	;
    140 	; Now, whole the IPL is loaded
    141 	;
    142 
    143 	; clear BSS
    144 	.import	_edata,data
    145 	addil	L%_edata-$global$,%r27;%r1
    146 	ldo	R%_edata-$global$(%r1),%r1
    147 clrbss:	comb,<	%r1,%r6,clrbss
    148 	stws,ma	%r0,4(0,%r1)
    149 
    150 	; we have read disklabel -- save it for later use
    151 	.import	labelsector,data
    152 	addil	L%labelsector-$global$,%r27;%r1
    153 	ldo	R%labelsector-$global$(%r1),%r20
    154 	ldo	tmpdiskbuf_labelsec(%r6),%r21
    155 	addi,tr	tmpdiskbuf_labelsecsz/4,%r0,%r2	; loop count, skip next
    156 cplbl:	stws,ma		%r1,4(0,%r20)		; write to dst
    157 	addib,uv,n	-1,%r2,cplbl		; check loop condition
    158 	ldws,ma		4(0,%r21),%r1		; read from src
    159 
    160 	; set stack
    161 	; (r6 points at free space, 64byte aligned)
    162 	; 32bit environment (and this code) requires stack is 64byte aligned.
    163 	ldo	64(%r6),%sp	; 64 > 48: frame marker (32) + args(up to 4)
    164 
    165 	; stack usage
    166 	;	12bytes	arguments
    167 	;	32	frame marker
    168 
    169 	; parameters for main
    170 	copy	%r3,%arg0
    171 	copy	%r4,%arg2
    172 
    173 	.import	ipl_main,entry
    174 	bl	ipl_main,%rp
    175 	copy	%sp,%arg1
    176 
    177 	; main returned --- perform reset
    178 	bl	print,%rp
    179 	ldo	str_reset-$global$(%r27),%arg0
    180 	; FALLTHROUGH
    181 
    182 IOMOD_CMD:		.equ	0xFFFC0000 + (4*12)
    183 IOMOD_CMD_STOP:		.equ	0
    184 IOMOD_CMD_RESET:	.equ	5
    185 
    186 ; void reboot(void)
    187 ; void halt(void)
    188 	.export reboot,entry
    189 	.export halt,entry
    190 reboot:
    191 	addi,tr	IOMOD_CMD_RESET,%r0,%r1	; %r1 = IOMOD_CMD_RESET, skip next
    192 halt:	ldi	IOMOD_CMD_STOP,%r1
    193 iomcmd:	ldil	L%IOMOD_CMD,%r2
    194 	ldo	R%IOMOD_CMD(%r2),%r2
    195 	stwas	%r1,0(%r2)
    196 	b,n	.
    197 
    198 str_startup:
    199 	.string		"\r\n\n"
    200 	.stringz	"NetBSD/hppa FFS/LFS Primary Bootstrap\r\n\n"
    201 str_reset:
    202 	.stringz	"\r\nresetting..."
    203 	.align	4
    204 
    205 ; void dispatch(unsigned interactive, unsigned top, unsigned end, int part,
    206 ;		unsigned entry)
    207 	.export	dispatch,entry
    208 dispatch:
    209 	; flush data cache / invalidate instruction cache
    210 	ldi	16,%r20		; 16: cache line size
    211 flush:	fdc	0(0,%arg1)	; flush data cache line at arg1
    212 	comb,<	%arg1,%arg2,flush
    213 	fic,m	%r20(0,%arg1)	; flush instruction cache line at arg1, arg1+=16
    214 	sync
    215 	copy	%r0,%r1		; I/O operation is guaranteed to finish
    216 	copy	%r0,%r3		; in eight instructions after sync
    217 	copy	%r0,%r4
    218 	copy	%r0,%r5		; while waiting, clear unused registers
    219 	copy	%r0,%r6		; for future compatibility
    220 	copy	%r0,%r7
    221 	copy	%r0,%r8
    222 	copy	%r0,%r9
    223 	copy	%r0,%r10
    224 	copy	%r0,%r11
    225 	copy	%r0,%r12
    226 	copy	%r0,%r13
    227 	copy	%r0,%r14
    228 	copy	%r0,%r15
    229 	copy	%r0,%r16
    230 	copy	%r0,%r17
    231 	copy	%r0,%r18
    232 	copy	%r0,%r19
    233 	copy	%r0,%r20
    234 	copy	%r0,%r21
    235 	copy	%r0,%r22
    236 	copy	%r0,%r28	; r23-r26: arg3-arg0, r27: dp
    237 	copy	%r0,%r29	; r30: sp
    238 	copy	%r0,%r31
    239 	ldw	-52(%sp),%arg1			; arg4: exec address
    240 	ldo	reboot-$global$(%r27),%rp	; reboot if returns
    241 	bv	%r0(%arg1)			; execute
    242 	ldi	BOOT_IF_VERSION,%arg1
    243 
    244 ;
    245 ;	IODC subroutines
    246 ;
    247 PZ_MEM_CONSOLE:		.equ	0x3a0
    248 PZ_MEM_BOOT:		.equ	0x3d0
    249 PZ_MEM_KEYBOARD:	.equ	0x400
    250 
    251 DEV_PATH:		.equ	0x00
    252 DEV_LAYERS:		.equ	0x08
    253 DEV_HPA:		.equ	0x20	; hard physical address space
    254 DEV_SPA:		.equ	0x24	; soft physical address space
    255 DEV_IODC_ENTRY:		.equ	0x28
    256 DEV_CLASS:		.equ	0x2c
    257 DEV_CL_DUPLEX:		.equ	0x7	; full-duplex console class
    258 
    259 IODC_ENTRY_IO_BOOTIN:		.equ	0
    260 IODC_ENTRY_IO_CONSOLEIN:	.equ	2
    261 IODC_ENTRY_IO_CONSOLEOUT:	.equ	3
    262 
    263 ; call_iodc
    264 ; inputs:
    265 ;	%ret0	IODC base in page zero
    266 ;	%rp	return address
    267 ;	%r29	arg 8
    268 ;	%r19	arg 7
    269 ;	%r20	arg 6
    270 ;	%r21	arg 5
    271 ;	%r25	arg 1
    272 ; outputs
    273 ;	all scratch regs	undefined, unless defined by the IODC call
    274 call_iodc:
    275 	; set common arguments in registers
    276 	addil	L%retbuf-$global$,%r27;%r1
    277 	ldo	R%retbuf-$global$(%r1),%r22	; arg4: return buffer
    278 	ldo	DEV_LAYERS(%ret0),%arg3		; arg3: layer
    279 	ldw	DEV_SPA(%ret0),%arg2		; arg2: spa
    280 	ldw	DEV_HPA(%ret0),%arg0		; arg0: hpa
    281 	; check if narrow or wide mode
    282 	ssm	0,%r1				; get PSW
    283 	bb,<	%r1,4,call_iodc_64		; if W, call in 64bit mode
    284 	ldw	DEV_IODC_ENTRY(%ret0),%r1	; ENTRY_IO address
    285 
    286 	; narrow mode
    287 	stw	%r29,-68(%sp)			; arg8: maxsize / lang
    288 	stw	%r19,-64(%sp)			; arg7: size
    289 	stw	%r20,-60(%sp)			; arg6: buf
    290 	stw	%r21,-56(%sp)			; arg5: devaddr / unused
    291 	bv	%r0(%r1)			; call ENTRY_IO
    292 	stw	%r22,-52(%sp)			; arg4: return buffer
    293 
    294 call_iodc_64:
    295 	.allow	2.0
    296 	; On PA64 convention, arg0 - arg7 are passed in registers.
    297 	; Parameters are placed in INCREASING order.
    298 	; The argument pointer points at the first stack parameter.
    299 	; stack usage:
    300 	;	64bytes	allocated for register arguments arg0-arg7
    301 	;	 8	arg8 (argument pointer points here)
    302 	;	16	frame marker
    303 	std	%r29,-16-8(%sp)			; arg8: maxsize / lang
    304 ;	std	%sp,-8(%sp)			; psp in frame marker
    305 	bv	%r0(%r1)			; call ENTRY_IO
    306 	ldo	-16-8(%sp),%r29			; argument pointer
    307 	.allow
    308 
    309 ;
    310 ; console output
    311 ;
    312 ; void putch(int)
    313 ; void print(const char *string)
    314 	.align	4
    315 	.export putch,entry
    316 	.export print,entry
    317 putch:
    318 	stwm	%arg0,128(%sp)		; fake up a string on the stack
    319 	stb	%r0,-124(%sp)		; (see stack usage below)
    320 	addi,tr	-125,%sp,%arg0		; string address, skip next
    321 print:
    322 	.proc
    323 	.callinfo	frame=128,save_rp,no_unwind
    324 	.entry
    325 	ldo	128(%sp),%sp
    326 	stw	%rp,-128-20(%sp)
    327 
    328 	; stack usage:
    329 	;	36byte	IODC buffer (assume %sp was 64byte aligned)
    330 	;	 4	saved reg
    331 	;	88	arguments, frame marker
    332 	;		32bit: 36 (arguments) + 32 (frame marker)
    333 	;		64bit: 72 (arguments) + 16 (frame marker)
    334 prbufsiz:	.equ	36
    335 
    336 	; save callee-saves
    337 	stw	%r3,-92(%sp)
    338 
    339 	copy	%arg0,%r3
    340 
    341 prloop:
    342 	copy	%r0,%r19
    343 	ldi	prbufsiz,%r20
    344 	ldo	-128(%sp),%r1
    345 
    346 strloop:
    347 	ldb	0(%r3),%r2
    348 	comb,=	%r2,%r0,endstr
    349 	stbs,ma	%r2,1(0,%r1)
    350 	ldo	1(%r19),%r19
    351 	comb,<>	%r19,%r20,strloop
    352 	ldo	1(%r3),%r3
    353 
    354 endstr:
    355 	comb,=,n	%r19,%r0,endpr
    356 
    357 	; see IODC 3-51
    358 	; arg0 hpa
    359 	; arg1 option (ENTRY_IO_CONSOLEOUT (3))
    360 	; arg2 spa
    361 	; arg3 ID_addr (pointer to LAYER)
    362 	; arg4 R_addr (pointer to return buffer (64word?))
    363 	; arg5 unused (0)
    364 	; arg6 memaddr (64byte-aligned) string buffer
    365 	; arg7 reqsize
    366 	; arg8 lang (0)
    367 	ldi	PZ_MEM_CONSOLE,%ret0		; IODC base in page zero
    368 	copy	%r0,%r29			; arg8: lang
    369 ;	copy	%r19,%r19			; arg7: size
    370 	ldo	-128(%sp),%r20			; arg6: buf
    371 ;	copy	%r0,%r21			; arg5: unused
    372 	bl	call_iodc,%rp
    373 	ldi	IODC_ENTRY_IO_CONSOLEOUT,%arg1	; arg1: option
    374 	b,n	prloop
    375 
    376 endpr:
    377 	; restore callee-saves
    378 	ldw	-92(%sp),%r3
    379 
    380 	; return subroutine
    381 	ldw	-128-20(%sp),%rp
    382 	bv	%r0(%rp)
    383 	.exit
    384 	ldo	-128(%sp),%sp
    385 	.procend
    386 
    387 ;
    388 ; console input
    389 ;
    390 ; int getch(void)
    391 	.align	4
    392 	.export	getch,entry
    393 getch:
    394 	.proc
    395 	.callinfo	frame=192,save_rp,no_unwind
    396 	.entry
    397 	stw	%rp,-20(%sp)
    398 	ldo	192(%sp),%sp
    399 
    400 	; stack usage:
    401 	;	64byte	IODC buffer (assume %sp was 64byte aligned)
    402 	;	40	unused
    403 	;	88	arguments, frame marker
    404 	;		32bit: 36 (arguments) + 32 (frame marker)
    405 	;		64bit: 72 (arguments) + 16 (frame marker)
    406 
    407 	; check if console is full or half duplex
    408 	ldw	PZ_MEM_CONSOLE+DEV_CLASS(%r0),%r1	; device class
    409 	extru	%r1,31,4,%r1				; right 4bits are valid
    410 	ldi	PZ_MEM_CONSOLE,%ret0
    411 	comib,=,n	DEV_CL_DUPLEX,%r1,getch_console	; use CONSOLE if full
    412 	ldi	PZ_MEM_KEYBOARD,%ret0			; otherwise KEYBOARD
    413 getch_console:
    414 
    415 	; see IODC 3-50
    416 	; arg0 hpa
    417 	; arg1 option (ENTRY_IO_CONSOLEIN (2))
    418 	; arg2 spa
    419 	; arg3 ID_addr (pointer to LAYER)
    420 	; arg4 R_addr (pointer to return buffer (64word?))
    421 	; arg5 unused (0)
    422 	; arg6 memaddr (64byte-aligned, must have 64byte) data buffer
    423 	; arg7 reqsize
    424 	; arg8 lang (0)
    425 ;	copy	%rp,%rp				; IODC base in page zero
    426 	copy	%r0,%r29			; arg8: lang
    427 	ldi	1,%r19				; arg7: size (1)
    428 	ldo	-192(%sp),%r20			; arg6: buf
    429 ;	copy	%r0,%r21			; arg5: unused
    430 	bl	call_iodc,%rp
    431 	ldi	IODC_ENTRY_IO_CONSOLEIN,%arg1	; arg1: option
    432 
    433 	; make return value
    434 	comb,<>	%ret0,%r0,getch_ret		; return -1 on error
    435 	ldi	-1,%ret0
    436 	ldi	1,%r19
    437 
    438 	; check if narrow or wide mode
    439 	ssm	0,%r1				; get PSW
    440 	bb,<	%r1,4,getch_64
    441 	addil	L%retbuf-$global$,%r27;%r1
    442 	ldw	R%retbuf-$global$(%r1),%r2	; ret[0]
    443 	comclr,<>	%r19,%r2,%ret0		; return 0 if no char available
    444 getch_retc:
    445 	ldb	-192(%sp),%ret0			;  otherwise return the char
    446 
    447 getch_ret:
    448 	; return subroutine
    449 	ldw	-192-20(%sp),%rp
    450 	bv	%r0(%rp)
    451 	.exit
    452 	ldo	-192(%sp),%sp
    453 
    454 getch_64:
    455 	.allow	2.0
    456 	ldd	R%retbuf-$global$(%r1),%r2	; ret[0] (64bit)
    457 	b	getch_retc
    458 	cmpclr,*<>	%r19,%r2,%ret0		; return 0 if no char available
    459 	.allow
    460 	.procend
    461 
    462 ;
    463 ; read boot device
    464 ;
    465 ; void boot_input(void *buf, unsigned len, unsigned pos)
    466 	.align	4
    467 	.export boot_input,entry
    468 boot_input:
    469 	.proc
    470 	.callinfo	frame=128,save_rp,no_unwind
    471 	.entry
    472 	stw	%rp,-20(%sp)
    473 	ldo	128(%sp),%sp
    474 
    475 	; stack usage:
    476 	;	40byte	unused (alignment)
    477 	;	88	arguments, frame marker
    478 	;		32bit: 36 (arguments) + 32 (frame marker)
    479 	;		64bit: 72 (arguments) + 16 (frame marker)
    480 
    481 	; see IODC 3-46
    482 	; arg0 hpa
    483 	; arg1 option (ENTRY_IO_BOOTIN (0))
    484 	; arg2 spa
    485 	; arg3 ID_addr (pointer to LAYER)
    486 	; arg4 R_addr (pointer to return buffer (64word?))
    487 	; arg5 devaddr
    488 	; arg6 memaddr (64byte-aligned) string buffer
    489 	; arg7 reqsize
    490 	; arg8 maxsize
    491 	ldi	PZ_MEM_BOOT,%ret0		; IODC base in page zero
    492 	copy	%arg1,%r29			; arg8: maxsize
    493 	copy	%arg1,%r19			; arg7: size
    494 	copy	%arg0,%r20			; arg6: buf
    495 	copy	%arg2,%r21			; arg5: devaddr
    496 	bl	call_iodc,%rp
    497 	ldi	IODC_ENTRY_IO_BOOTIN,%arg1	; arg1: option
    498 
    499 	; return subroutine
    500 	ldw	-128-20(%sp),%rp
    501 	bv	%r0(%rp)
    502 	.exit
    503 	ldo	-128(%sp),%sp
    504 	.procend
    505 
    506 ;
    507 ;	utilities
    508 ;	optimized for size
    509 ;
    510 
    511 ; int strcmp(const char *str1, const char *str2)
    512 	.align	4
    513 	.export		strcmp,entry
    514 strcmp:
    515 	.proc
    516 	.callinfo	frame=0,no_calls
    517 	.entry
    518 	ldbs,ma		1(0,%arg0),%r1
    519 strcmp_loop:
    520 	comb,=		%r1,%r0,strcmp_eos
    521 	ldbs,ma		1(0,%arg1),%r19
    522 	comb,=,n	%r1,%r19,strcmp_loop
    523 	ldbs,ma		1(0,%arg0),%r1
    524 strcmp_eos:
    525 	bv		%r0(%rp)
    526 	.exit
    527 	sub		%r1,%r19,%ret0
    528 	.procend
    529 
    530 ; void memcpy(void *dst, const void *src, unsigned len)
    531 	.align	4
    532 	.export		memcpy,entry
    533 	.export		memmove,entry
    534 memcpy:
    535 memmove:
    536 	.proc
    537 	.callinfo	no_unwind		; multiple exit points
    538 	.entry
    539 ;	copy		%arg0,%ret0		; uncomment this to conform ANSI
    540 	comb,<<,n	%arg0,%arg1,memcpy0	; copy forward or backward?
    541 	add		%arg0,%arg2,%arg0	; dst end address
    542 	add,tr		%arg1,%arg2,%arg1	; src end address, skip next
    543 memcpy_bwd:
    544 	stbs,mb		%r1,-1(0,%arg0)		; write to dst
    545 	addib,uv,n	-1,%arg2,memcpy_bwd	; check loop condition
    546 	ldbs,mb		-1(0,%arg1),%r1		; read from src
    547 	bv,n		%r0(%rp)		; return subroutine
    548 memcpy_fwd:
    549 	stbs,ma		%r1,1(0,%arg0)		; write to dst
    550 memcpy0:
    551 	addib,uv,n	-1,%arg2,memcpy_fwd	; check loop condition
    552 	ldbs,ma		1(0,%arg1),%r1		; read from src
    553 	.exit
    554 	bv,n		%r0(%rp)		; return subroutine
    555 	.procend
    556 
    557 ;
    558 ;	string table
    559 ;	placed here to save space
    560 ;
    561 	.export	str_seekseq, data
    562 	.export	str_startup, data
    563 	.export	str_bit_firmware, data
    564 	.export	str_crlf, data
    565 	.export	str_space, data
    566 	.export	str_rubout, data
    567 str_seekseq:
    568 	.stringz	"repositioning media...\r\n"
    569 str_bit_firmware:
    570 	.stringz	"bit firmware\r\n"
    571 str_rubout:
    572 	.byte		0x08, 0x20, 0x08, 0x00	; "\b \b"
    573 
    574 	.export	str_bootpart, data
    575 str_bootpart:
    576 	.string		"boot partition (a-p, ! to reboot) [a]:"
    577 str_space:
    578 	.stringz	" "
    579 	.export	str_booting_part, data
    580 str_booting_part:
    581 	.string		"\r\nbooting from partition _"
    582 str_crlf:
    583 	.stringz	"\r\n"
    584 	.export	str_warn_2GB, data
    585 str_warn_2GB:
    586 	.stringz	"boot partition exceeds 2GB boundary\r\n"
    587 	.export	str_warn_unused, data
    588 str_warn_unused:
    589 	.stringz	"unused partition\r\n"
    590 	.export	str_nolabel, data
    591 str_nolabel:
    592 	.stringz	"no disklabel\r\n"
    593 
    594 	.export	str_filesystem, data
    595 str_filesystem:
    596 	.stringz	"filesystem: _FS\r\n"
    597 	.export	str_nofs, data
    598 str_nofs:
    599 	.stringz	"no filesystem found\r\n"
    600 	.export	str_lookup, data
    601 	.export	str_loading, data
    602 	.export	str_at, data
    603 	.export	str_dddot, data
    604 	.export	str_done, data
    605 str_lookup:
    606 	.stringz	"looking up "
    607 str_loading:
    608 	.stringz	"loading "
    609 str_at:
    610 	.stringz	" at 0x"
    611 str_dddot:
    612 	.stringz	"..."
    613 str_done:
    614 	.stringz	"done\r\n"
    615 
    616 	.export	str_boot1, data
    617 	.export	str_boot2, data
    618 	.export	str_boot3, data
    619 str_boot1:
    620 	.stringz	"boot.hp700"
    621 str_boot2:
    622 	.stringz	"boot"
    623 str_boot3:
    624 	.stringz	"usr/mdec/boot"
    625 
    626 	.export	str_noboot, data
    627 str_noboot:
    628 	.stringz	"no secondary boot found\r\n"
    629 
    630 	.export	str_ukfmt, data
    631 str_ukfmt:
    632 	.stringz	": unknown format -- exec from top\r\n"
    633 
    634 	.bss
    635 	.align	64
    636 retbuf:	.block	32*8		; *4 for narrow mode / *8 for wide mode
    637 
    638 	.export diskbuf,data
    639 	.align	64
    640 diskbuf:
    641 	.block	2048
    642