diff options
Diffstat (limited to 'arch/s390x/boot')
-rw-r--r-- | arch/s390x/boot/Makefile | 37 | ||||
-rw-r--r-- | arch/s390x/boot/ipldump.S | 178 | ||||
-rw-r--r-- | arch/s390x/boot/ipleckd.S | 303 | ||||
-rw-r--r-- | arch/s390x/boot/iplfba.S | 131 |
4 files changed, 649 insertions, 0 deletions
diff --git a/arch/s390x/boot/Makefile b/arch/s390x/boot/Makefile new file mode 100644 index 000000000..fb112b964 --- /dev/null +++ b/arch/s390x/boot/Makefile @@ -0,0 +1,37 @@ +# +# Makefile for the linux s390-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +OBJCOPY = $(CROSS_COMPILE)objcopy + +O_TARGET := + +include $(TOPDIR)/Rules.make + +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + +%.lnk: %.o + $(LD) -Ttext 0x0 -o $@ $< + +%.boot: %.lnk + $(OBJCOPY) -O binary $< $@ + +image: $(CONFIGURE) $(TOPDIR)/vmlinux \ + iplfba.boot ipleckd.boot ipldump.boot + $(OBJCOPY) -O binary $(TOPDIR)/vmlinux image + $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aU] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map + +listing: ../../../vmlinux + $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing + +dep: + +clean: + rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + diff --git a/arch/s390x/boot/ipldump.S b/arch/s390x/boot/ipldump.S new file mode 100644 index 000000000..84150b5af --- /dev/null +++ b/arch/s390x/boot/ipldump.S @@ -0,0 +1,178 @@ +/* + * arch/s390/boot/ipldump.S + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * Tape dump ipl record. Put it on a tape and ipl from it and it will + * write a dump of the real storage after the ipl record on that tape. + */ + +#include <asm/setup.h> +#include <asm/lowcore.h> + +#define IPL_BS 1024 + .org 0 + .long 0x00080000,0x80000000+_start # The first 24 bytes are loaded + .long 0x07000000,0x60000001 # by ipl to addresses 0-23. + .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 # svc old psw + .long 0x00000000,0x00000000 # program check old psw + .long 0x00000000,0x00000000 # machine check old psw + .long 0x00000000,0x00000000 # io old psw + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x000a0000,0x00000058 # external new psw + .long 0x000a0000,0x00000060 # svc new psw + .long 0x000a0000,0x00000068 # program check new psw + .long 0x000a0000,0x00000070 # machine check new psw + .long 0x00080000,0x80000000+.Lioint # io new psw + + .org 0x100 + .globl _start +_start: + l %r1,0xb8 # load ipl subchannel number +# +# find out memory size +# + mvc 104(8),.Lpcmem0 # setup program check handler + slr %r3,%r3 + lhi %r2,1 + sll %r2,20 +.Lloop0: + l %r0,0(%r3) # test page + ar %r3,%r2 # add 1M + jnm .Lloop0 # r1 < 0x80000000 -> loop +.Lchkmem0: + n %r3,.L4malign0 # align to multiples of 4M + st %r3,.Lmemsize # store memory size +.Lmemok: + +# +# first write a tape mark +# + bras %r14,.Ltapemark +# +# write real storage to tape +# + slr %r2,%r2 # start at address 0 + bras %r14,.Lwriter # load ramdisk +# +# write another tape mark +# + bras %r14,.Ltapemark +# +# everything written, stop processor +# + lpsw .Lstopped +# +# subroutine for writing to tape +# Paramters: +# R1 = device number +# R2 = start address +# R3 = length +.Lwriter: + st %r14,.Lldret + la %r12,.Lorbread # r12 = address of orb + la %r5,.Lirb # r5 = address of irb + st %r2,.Lccwwrite+4 # initialize CCW data addresses + lctl %c6,%c6,.Lcr6 + slr %r2,%r2 +.Lldlp: + lhi %r6,3 # 3 retries +.Lssch: + ssch 0(%r12) # write chunk of IPL_BS bytes + jnz .Llderr +.Lw4end: + bras %r14,.Lwait4io + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lrecov + l %r0,.Lccwwrite+4 # update CCW data addresses + ahi %r0,IPL_BS + st %r0,.Lccwwrite+4 + clr %r0,%r3 # enough ? + jl .Lldlp +.Ldone: + l %r14,.Lldret + br %r14 # r2 contains the total size +.Lrecov: + bras %r14,.Lsense # do the sensing + brct %r6,.Lssch # dec. retry count & branch + j .Llderr +.Ltapemark: + st %r14,.Lldret + la %r12,.Lorbmark # r12 = address of orb + la %r5,.Lirb # r5 = address of irb + lctl %c6,%c6,.Lcr6 + ssch 0(%r12) # write a tape mark + jnz .Llderr + bras %r14,.Lwait4io + l %r14,.Lldret + br %r14 +# +# Sense subroutine +# +.Lsense: + st %r14,.Lsnsret + la %r7,.Lorbsense + ssch 0(%r7) # start sense command + jnz .Llderr + bras %r14,.Lwait4io + l %r14,.Lsnsret + tm 8(%r5),0x82 # do we have a problem ? + jnz .Llderr + br %r14 +# +# Wait for interrupt subroutine +# +.Lwait4io: + lpsw .Lwaitpsw +.Lioint: + c %r1,0xb8 # compare subchannel number + jne .Lwait4io + tsch 0(%r5) + slr %r0,%r0 + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lwtexit + tm 8(%r5),0x04 # got device end ? + jz .Lwait4io +.Lwtexit: + br %r14 +.Llderr: + lpsw .Lcrash + + .align 8 +.Lorbread: + .long 0x00000000,0x0080ff00,.Lccwwrite + .align 8 +.Lorbsense: + .long 0x00000000,0x0080ff00,.Lccwsense + .align 8 +.Lorbmark: + .long 0x00000000,0x0080ff00,.Lccwmark + .align 8 +.Lccwwrite: + .long 0x01200000+IPL_BS,0x00000000 +.Lccwsense: + .long 0x04200001,0x00000000 +.Lccwmark: + .long 0x1f200001,0x00000000 +.Lwaitpsw: + .long 0x020a0000,0x80000000+.Lioint + +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lcr6: .long 0xff000000 + .align 8 +.Lcrash:.long 0x000a0000,0x00000000 +.Lstopped: .long 0x000a0000,0x00001234 +.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 +.L4malign0:.long 0xffc00000 +.Lmemsize:.long 0 +.Lldret:.long 0 +.Lsnsret: .long 0 + + .org IPL_BS + diff --git a/arch/s390x/boot/ipleckd.S b/arch/s390x/boot/ipleckd.S new file mode 100644 index 000000000..d66a8d684 --- /dev/null +++ b/arch/s390x/boot/ipleckd.S @@ -0,0 +1,303 @@ +# +# arch/s390/boot/ipleckd.S +# IPL record for 3380/3390 DASD +# +# S390 version +# Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation +# Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com> +# +# +# FIXME: should use the countarea to determine the blocksize +# FIXME: should insert zeroes into memory when filling holes +# FIXME: calculate blkpertrack from rdc data and blksize + +# change 09/20/00 removed obsolete store of ipldevice to textesegment + +# Usage of registers +# r1: ipl subchannel ( general use, dont overload without save/restore !) +# r10: +# r13: base register index to 0x0000 +# r14: callers address +# r15: temporary save register (we have no stack!) + +# storage layout: + +#include <asm/lowcore.h> + + .org 0 +.psw: .long 0x00080000,0x80000000+_start +.ccw1: .long 0x06000000,0x00001000 # Re-Read enough of bootsector to start +.ccw2: .long 0x00000000,0x00000000 # read countarea of record 1 to s/w. + + .org 0x58 +.Lextn: .long 0x000a0000,0x00000000+.Lextn +.Lsvcn: .long 0x000a0000,0x00000000+.Lsvcn +.Lprgn: .long 0x00080000,0x00000000+.Lecs +.Lmcn: .long 0x000a0000,0x00000000+.Lmcn +.Lion: .long 0x00080000,0x80000000+.Lionewaddr + + .org 0xe0 +.Llstad:.long 0x00000000,0x00000000 # sectorno + ct of bootlist + + .org 0xf0 # Lets start now... +_start: .globl _start + l %r1,__LC_SUBCHANNEL_ID # get IPL-subchannel from lowcore + st %r1,__LC_IPLDEV # keep it for reipl + stsch .Lrdcdata + oi .Lrdcdata+5,0x84 # enable ssch and multipath mode +.Lecs: xi .Lrdcdata+27,0x01 # enable concurrent sense + msch .Lrdcdata + xi .Lprgn,6 # restore Wait and d/a bit in PCnew PSW + l %r2,.Lparm + mvc 0x0(8,%r2),.Lnull # set parmarea to null + lctl %c6,%c6,.Lc6 # enable all interrupts +.Lrdc: # read device characteristics + la %r6,.Lrdcccw + st %r6,.Lorb+8 # store cp-address to orb + bras %r15,.Lssch # start I/O + oi .Llodata+1,0x80 + lh %r5,.Lcountarea+6 # init r5 from countarea + stcm %r5,3,.Lrdccw+2 # and store into rd template *FIXME* + stcm %r5,3,.Llodata+14 # and store into lodata *FIXME* +.Lbootlist: + l %r2,.Llstad + l %r3,.Lblklst + lhi %r4,1 + bras %r14,.Lreadblks +.Lloader: + l %r10,.Lblklst # r10 is index to bootlist + lhi %r5,4 # r5: skip 4 blocks = firstpage.... +.Lkloop: + clc .Lnull(8),0(%r10) # test blocklist + jz .Lchkparm # end of list? + l %r2,0(%r10) # get startblock to r2 + slr %r4,%r4 # erase r4 + icm %r4,1,7(%r10) # get blockcount + slr %r3,%r3 # get address to r3 + icm %r3,0xe,4(%r10) + chi %r5,0 # still blocks to skip? + jz .Ldoread # no: start reading + cr %r5,%r4 # #skipblocks >= blockct? + jm .L007 # no: skip the blocks one by one +.L006: + sr %r5,%r4 # decrease number of blocks to skip + j .Lkcont # advance to next entry +.L007: + ahi %r2,1 # skip 1 block... + bctr %r4,0 # update blockct + ah %r3,.Lcountarea+6 # increment address + bct %r5,.L007 # 4 blocks skipped? +.Ldoread: + ltr %r2,%r2 # test startblock + jz .Lzeroes # startblocks is zero (hole) +.Ldiskread: + bras %r14,.Lreadblks + j .Lkcont +.Lzeroes: + lr %r2,%r3 +.L001: slr %r3,%r3 + icm %r3,3,.Lcountarea+6 # get blocksize + slr %r5,%r5 # no bytes to move +.L008: mvcle %r2,%r4,0 # fill zeroes to storage + jo .L008 # until block is filled + brct %r4,.L001 # skip to next block +.Lkcont: + ahi %r10,8 + j .Lkloop +.Lchkparm: + lm %r3,%r4,.Lstart # load .Lstart and .Lparm + clc 0x0(4,%r4),.Lnull + je .Lrunkern + mvc 0x480(128,%r3),0(%r4) # move 1k-0x80 to parmarea + mvc 0x500(256,%r3),0x80(%r4) + mvc 0x600(256,%r3),0x180(%r4) + mvc 0x700(256,%r3),0x280(%r4) +.Lrunkern: +# lhi %r2,17 +# sll %r2,12 +# st %r1,0xc6c(%r2) # store iplsubchannel to lowcore +# st %r1,0xc6c # store iplsubchannel to lowcore + br %r3 +# This function does the start IO +# r2: number of first block to read ( input by caller ) +# r3: address to read data to ( input by caller ) +# r4: number of blocks to read ( input by caller ) +# r5: destroyed +# r6: blocks per track ( input by caller ) +# r7: number of heads +# r8: +# r9: +# r10: +# r11: temporary register +# r12: local use for base address +# r13: base address for module +# r14: address of caller for subroutine +# r15: temporary save register (since we have no stack) +.Lreadblks: + la %r12,.Ldeccw + st %r12,8+.Lorb # store cpaddr to orb + ahi %r12,0x10 # increment r12 to point to rdccw + oi 1(%r12),0x40 # set CC in rd template + # first setup the read CCWs + lr %r15,%r4 # save number or blocks + slr %r7,%r7 + icm %r7,3,.Lrdcdata+14 # load heads to r7 + lhi %r6,9 + clc .Lrdcdata+3(2),.L9345 + je .L011 + lhi %r6,10 + clc .Lrdcdata+3(2),.L3380 + je .L011 + lhi %r6,12 + clc .Lrdcdata+3(2),.L3390 + je .L011 + bras %r14,.Ldisab +.L011: + # loop for nbl times +.Lrdloop: + mvc 0(8,%r12),.Lrdccw # copy template to this ccw + st %r3,4(%r12) # store target address to this ccw + bct %r4,.L005 # decrement no of blks still to do + ni 1(%r12),0x3f # delete CC from last ccw + lr %r4,%r15 # restore number of blocks + # read CCWs are setup now + stcm %r4,3,.Llodata+2 # store blockno to lodata clears r4 + ar %r4,%r2 # r4 (clear): ebl = blk + nbl + bctr %r4,0 # decrement r4 ( last blk touched + srda %r2,32 # trk = blk / bpt, bot = blk % bpt + dr %r2,%r6 # r3: trk, r2: bot + ahi %r2,1 # bot++ ( we start counting at 1 ) + stcm %r2,1,.Llodata+12 # store bot to lodata + xr %r2,%r2 # cy = trk / heads, hd = trk % heads + dr %r2,%r7 # r3: cy, r2: hd + sll %r3,16 # combine to CCHH in r3 + or %r3,%r2 + st %r3,.Ldedata+8 # store cchh to dedata + st %r3,.Llodata+4 # store cchh to lodata + st %r3,.Llodata+8 # store cchh to lodata + lr %r15,%r5 # save r5 + srda %r4,32 # tr2 = ebl / bpt + dr %r4,%r6 # r5: tr2, r4: bot2 + xr %r4,%r4 # cy2 = tr2 / heads, hd2 = hd2 % heads + dr %r4,%r7 # r5: cy2, r4: hd2 + stcm %r5,3,.Ldedata+12 # store cy2,hd2 to dedata + stcm %r4,3,.Ldedata+14 # store cy2,hd2 to dedata + lr %r5,%r15 # restore r5 + # CCWs are setup now, arent they? + bras %r15,.Lssch # start I/O + br %r14 # return to caller +.L005: + ah %r3,.Lcountarea+6 # add blocksize to target address + ahi %r12,8 # add sizeof(ccw) to base address + j .Lrdloop +# end of function +# This function does the start IO +# r1: Subchannel number +# r8: ORB address +# r9: IRB address +.Lssch: + lhi %r13,10 # initialize retries +.L012: + ssch .Lorb # start I/O + jz .Ltpi # ok? + bras %r14,.Ldisab # error +.Ltpi: + lpsw .Lwaitpsw # load wait-PSW +.Lionewaddr: + c %r1,0xb8 # compare to ipl subhchannel + jnz .Ltpi # not equal: loop + clc 0xbc(4),.Lorb # cross check the intparm + jnz .Ltpi # not equal: loop + tsch .Lirb # get status + tm .Lirb+9,0xff # channel status ? + jz .L003 # CS == 0x00 + bras %r14,.Ldisab # error +.L003: + tm .Lirb+8,0xf3 # DS different from CE/DE + jz .L004 # ok ? + bct %r13,.L012 # retries <= 5 ? + bras %r14,.Ldisab # error +.L004: + tm .Lirb+8,0x04 # DE set? + jz .Ltpi # DE not set, loop +.Lsschend: + br %r15 # return to caller +# end of function +# In case of error goto disabled wait with %r14 containing the caller +.Ldisab: + st %r14,.Ldisabpsw+4 + lpsw .Ldisabpsw + +# FIXME pre-initialized data should be listed first +# NULLed storage can be taken from anywhere ;) +.Lblklst: + .long 0x00002000 + .align 8 +.Ldisabpsw: + .long 0x000a0000,0x00000000 +.Lwaitpsw: + .long 0x020a0000,0x00000000+.Ltpi +.Lorb: + .long 0x0049504c,0x0080ff00 # intparm is " IPL" +.Lc6: .long 0xff000000 +.Lstart: + .long 0x00010000 # do not separate .Lstart and .Lparm +.Lparm: + .long 0x00008000 # they are loaded with a LM +.L3390: + .word 0x3390 +.L9345: + .word 0x9345 +.L3380: + .word 0x3380 +.Lnull: + .long 0x00000000,0x00000000 + .align 4 +.Lrdcdata: + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 +.Lirb: + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 +.Lcountarea: + .word 0x0000 # cyl; + .word 0x0000 # head; + .byte 0x00 # record; + .byte 0x00 # key length; + .word 0x0000 # data length == blocksize; +.Ldedata: + .long 0x40c00000,0x00000000 + .long 0x00000000,0x00000000 +.Llodata: + .long 0x06000001,0x00000000 + .long 0x00000000,0x01000000 + .long 0x12345678 + .org 0x7c8 +.Lrdcccw: # CCW read device characteristics + .long 0x64400040,0x00000000+.Lrdcdata + .long 0x63400010,0x00000000+.Ldedata + .long 0x47400010,0x00000000+.Llodata + .long 0x12000008,0x00000000+.Lcountarea +.Ldeccw: + .long 0x63400010,0x00000000+.Ldedata +.Lloccw: + .long 0x47400010,0x00000000+.Llodata +.Lrdccw: + .long 0x86400000,0x00000000 + .org 0x800 +# end of pre initialized data is here CCWarea follows +# from here we load 1k blocklist +# end of function + diff --git a/arch/s390x/boot/iplfba.S b/arch/s390x/boot/iplfba.S new file mode 100644 index 000000000..732a9848c --- /dev/null +++ b/arch/s390x/boot/iplfba.S @@ -0,0 +1,131 @@ +# +# Ipl block for fba devices +# Copyright (C) 1998 IBM Corporation +# Author(s): Martin Schwidefsky +# +# startup for ipl at address 0 +# start with restart + +# The first 24 byes are loaded by ipl to addresses 0-23 (a PSW and two CCWs). +# The CCWs on 8-23 are used as a continuation of the implicit ipl channel +# program. The fba ipl loader only uses the CCW on 8-15 to load the first 512 +# byte block to location 0-511 (the reading starts again at block 0, byte 0). +# The second CCW is used to store the location of the load list. + .org 0 + .long 0x00080000,0x80000000+_start # The first 24 byte are loaded + .long 0x02000000,0x20000200 # by ipl to addresses 0-23. + .long 0x00000001,0x00000001 # (PSW, one CCW & loadlist info). + + .globl _start +_start: + basr %r13,0 +.LPG0: + l %r1,0xb8 # load ipl subchannel number + lhi %r2,0x200 # location for the loadlist + lm %r3,%r4,0x10 # blocknr and length of loadlist + bras %r14,.Lloader # load loadlist + + lhi %r11,0x400 + lhi %r12,0x200 # load address of loadlist + l %r3,0(%r12) # get first block number + l %r4,4(%r12) # get first block count + la %r12,8(%r12) + j .Llistloop + .org 0x50 +.Llistloop: + lr %r2,%r11 # load address + lr %r5,%r4 # block count + mhi %r5,512 + la %r11,0(%r5,%r11) # update load address + bras %r14,.Lloader # load chunk of the image + l %r3,0(%r12) # get next block number + icm %r4,15,4(%r12) # get next block count + la %r12,8(%r12) + jnz .Llistloop + +# +# everything loaded, go for it +# + l %r1,.Lstart-.LPG0(%r13) + br %r1 + +# +# subroutine for loading a sequence of block from fba +# %r2: load address (24 bit address) +# %r3: number of first block (unsigned long) +# %r4: number of blocks to load (unsigned short) +# + .org 0xC0 +.Lloader: + la %r5,.Llo-.LPG0(%r13) + sth %r4,2(%r5) # initialize block count + st %r3,4(%r5) # initialize block number + la %r5,.Lccws-.LPG0(%r13) + mhi %r4,512 + sth %r4,22(%r5) # initialize byte count + icm %r2,8,16(%r5) + st %r2,16(%r5) # initialize CCW data address + + slr %r2,%r2 + la %r3,.Lorb-.LPG0(%r13) # r2 = address of orb into r2 + la %r4,.Ltinfo-.LPG0(%r13) # r3 = address of tpi info block + la %r5,.Lirb-.LPG0(%r13) # r4 = address of irb + + lctl %c6,%c6,.Lc6-.LPG0(%r13) +.Lldlp: + ssch 0(%r3) # read blocks +.Ltpi: + tpi 0(%r4) # test pending interrupt + jz .Ltpi + c %r1,0(%r4) # compare subchannel number + jne .Ltpi + tsch 0(%r5) + slr %r0,%r0 + tm 8(%r5),0x82 # do we have a problem ? + jnz .Ldwpsw + tm 8(%r5),0x04 # got device end ? + jz .Ltpi +.Lexit: + br %r14 + + .align 8 +.Ldwpsw:.long 0x000a0000,0x00000000 +.Lorb: .long 0x00000000,0x0000ff00,.Lccws +.Ltinfo:.long 0 +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lc6: .long 0xff000000 +.Lloadp:.long 0,0 +.Lparm: .long 0x10400 +.Lstart:.long 0x10000 + .align 8 +.Lccws: .long 0x63000000+.Lde,0x60000010 # define extent + .long 0x43000000+.Llo,0x60000008 # locate +# offset 1 in read CCW: data address (24 bit) +# offset 6 in read CCW: number of bytes (16 bit) + .long 0x42000000,0x20000000 # read +.Lde: .long 0x40000200,0x00000000 + .long 0x00000000,0x00001000 +# offset 2 in .Llo: block count (unsigned short) +# offset 4 in .Llo: block number (unsigned long) +.Llo: .long 0x06000000,0x00000000 + + .org 0x200 + .long 0x00000002,0x0000007f + .long 0x00000081,0x0000007f + .long 0x00000100,0x0000007f + .long 0x0000017f,0x0000007f + .long 0x000001fe,0x0000007f + .long 0x0000027d,0x0000007f + .long 0x000002fc,0x0000007f + .long 0x0000037b,0x0000007f + .long 0x000003fa,0x0000007f + .long 0x00000479,0x0000007f + .long 0x000004f8,0x0000007f + .long 0x00000577,0x0000007f + .long 0x000005f6,0x0000007f + .long 0x00000675,0x0000007f + .long 0x000006f4,0x0000007f + .long 0x00000773,0x0000003f + .long 0x00000000,0x00000000 + .org 0x400 + |