summaryrefslogtreecommitdiff
path: root/src/codehandler.real.s
diff options
context:
space:
mode:
authorStephen Simpson <megazig@gmail.com>2011-10-10 22:16:35 -0500
committerStephen Simpson <megazig@gmail.com>2011-10-10 22:16:35 -0500
commit1bf7f8a471746eef9badf5f37031da6f8d88e9a2 (patch)
tree03e4e62a435d88e5fd8d9dda2d9cc848e5a16af1 /src/codehandler.real.s
parenta61758720db96f59e0fb82aab9f326d37e186a11 (diff)
downloadkamek-1bf7f8a471746eef9badf5f37031da6f8d88e9a2.tar.gz
kamek-1bf7f8a471746eef9badf5f37031da6f8d88e9a2.zip
added ability to link in .o files
tweeked MountainGoombas Launch state for always arcing up added two more goomba types to the Launch state added in codehandler. bp not working, but rest seems functional
Diffstat (limited to 'src/codehandler.real.s')
-rwxr-xr-xsrc/codehandler.real.s821
1 files changed, 821 insertions, 0 deletions
diff --git a/src/codehandler.real.s b/src/codehandler.real.s
new file mode 100755
index 0000000..37d7df5
--- /dev/null
+++ b/src/codehandler.real.s
@@ -0,0 +1,821 @@
+# initial setup
+# * add exception handling for all cases
+# many breakpoints handling
+# * add breakpoint list with addresses
+# * add breakpoint list with original values
+# allow PPC side searches
+# * u32 with number of matches
+# * list of addresses that match
+# breakpoint conditions
+# * address == foo
+# * &&
+# * r* == bar
+# * r* != bar
+# * r* > bar
+# * r* < bar
+
+.text
+
+.set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31; .set f0,0; .set f2,2; .set f3,3
+
+.globl _start
+
+gameid:
+.long 0,0
+cheatdata:
+.long frozenvalue
+.space 39*4
+
+_start:
+ stwu r1,-168(r1) # stores sp
+ stw r0,8(r1) # stores r0
+
+ mflr r0
+ stw r0,172(r1) # stores lr
+
+ mfcr r0
+ stw r0,12(r1) # stores cr
+
+ mfctr r0
+ stw r0,16(r1) # stores ctr
+
+ mfxer r0
+ stw r0,20(r1) # stores xer
+
+ stmw r3,24(r1) # saves r3-r31
+
+ mfmsr r25
+ ori r26,r25,0x2000 #enable floating point ?
+ andi. r26,r26,0xF9FF
+ mtmsr r26
+
+ stfd f2,152(r1) # stores f2
+ stfd f3,160(r1) # stores f3
+
+ lis r20, 0xCC00
+ lhz r28, 0x4010(r20)
+ ori r21, r28, 0xFF
+ sth r21, 0x4010(r20) # disable MP3 memory protection
+
+_check_state:
+ lis r31, state@h
+ ori r31, r31, state@l
+ lwz r31, 0(r31)
+ cmpwi r31, 0
+ bne- _setvalues
+
+_init_exceptions:
+ # 4,3,5,17 are trampled
+ lis r4,bphandler@h
+ ori r4,r4,bphandler@l
+ lis r3,0x8000
+ ori r3,r3,0x300 # bprw 0x80000300
+ bl writebranch
+
+ addi r3,r3,0xA00 # trace 0x80000D00
+ bl writebranch
+
+ addi r3,r3,0x600 # bpx 0x80001300
+ bl writebranch
+
+ li r5, 1
+ lis r31, state@h
+ ori r31, r31, state@l
+ stw r5, 0(r31) # set state to 1 (exception handling linked)
+
+_setvalues:
+ li r21,0
+ li r22,0x19
+ li r23,0xD0
+ lis r24,0xCD00
+
+ lis r18, frozenvalue@h
+ ori r18, r18, frozenvalue@l # read buffer just store in lowmem
+ lwz r0,172(r1) # loads lr
+ stw r0,4(r18) # stores lr
+ stw r21, 0x643C(r24) # exi speed up
+
+frozen:
+ bl exireceivebyte
+ beq finish # r3 returns 1 or 0, one for byte received ok
+
+checkcommand:
+
+ cmpwi r29, 0x04 # checks lf 8/1/32 bits write command
+ bge _nextcommand
+ cmpwi r29, 0x01
+ blt finish
+ b writedword #write value to address
+_nextcommand:
+ beq readmem
+ cmpwi r29, 0x06
+ beq freezegame
+ cmpwi r29, 0x07
+ beq unfreezegame
+ cmpwi r29, 0x08
+ beq resumegame
+ cmpwi r29, 0x09
+ beq breakpoints #ibp
+ cmpwi r29, 0x10
+ beq breakpoints #dbp
+ cmpwi r29, 0x2F
+ beq upbpdata
+ cmpwi r29, 0x30
+ beq getbpdata
+ cmpwi r29, 0x38
+ beq cancelbreakpoints
+ cmpwi r29, 0x41
+ beq uploadcode
+ cmpwi r29, 0x44
+ beq breakpoints #step
+ cmpwi r29, 0x50
+ beq pausestatus
+ cmpwi r29, 0x89
+ beq breakpoints #aligned dbp
+ cmpwi r29, 0x99
+ beq versionnumber
+ b finish
+
+#******************************************************************
+# subroutine: getpausestatus:
+# one running, two paused, three on a breakpoint
+#******************************************************************
+
+pausestatus:
+ lwz r3,0(18)
+ bl exisendbyte
+ b finish
+
+
+#******************************************************************
+# subroutine: freezegame:
+# Write a 1 to a memory location to freeze
+#******************************************************************
+
+freezegame:
+ li r4, 1
+ stw r4, 0(r18)
+ b finish
+
+#******************************************************************
+# subroutine: unfreezegame:
+# Write a 0 to a memory location to unfreeze
+#******************************************************************
+
+unfreezegame:
+ stw r21, 0(r18)
+ b resumegame
+
+#******************************************************************
+# subroutine: upload bp data:
+# receive the dp databuffer from the PC
+#******************************************************************
+
+upbpdata:
+ bl exisendbyteAA
+
+ li r16, 40*4 # 42 "registers rN" * 4
+ lis r12, regbuffer@h
+ ori r12, r12, regbuffer@l
+ b upload
+
+#******************************************************************
+# subroutine: getbp data:
+# send the dp databuffer to the PC
+#******************************************************************
+
+getbpdata:
+ li r3, 72*4 # register buffer
+ lis r12, regbuffer@h
+ ori r12, r12, regbuffer@l
+ bl exisendbuffer # send it, less than a packet
+ b finish
+
+
+#******************************************************************
+# subroutine: breakpoints:
+# handles data/instruction address breakpoints
+#******************************************************************
+
+breakpoints:
+
+ cmpwi cr6,r29,0x10 # 0x10=instruction, 0x09/0x89=data
+ cmpwi cr5,r29,0x44 # 0x44=step
+
+ lis r4, bphandler@h
+ ori r4,r4,bphandler@l #used for writebranch (=source address)
+
+ lis r3,0x8000
+ ori r3,r3,0x300 # bprw 0x80000300
+ bl writebranch
+
+ addi r3,r3,0xA00 # trace 0x80000D00
+ bl writebranch
+
+ addi r3,r3,0x600 # bpx 0x80001300
+ bl writebranch
+
+ lis r12, bpbuffer@h
+ ori r12, r12, bpbuffer@l # read buffer just store in lowmem
+
+ stw r21,0(r12) # clears inst bp
+ stw r21,4(r12) # clears data bp
+ stw r21,8(r12) # clears alignement
+
+ lis r4, regbuffer@h
+ ori r4, r4, regbuffer@l
+ lwz r9,0x18(r4)
+
+ lwz r3,0(r18)
+ cmpwi r3,2 # checks if the gecko is on a breakpoint
+ bne +12
+ beq cr5,+12
+ b bp
+ li r3,0
+ stw r3,12(r12) # if not, clears the previous "broken on" address
+
+ bne bp
+
+ bne cr5,bp
+ ori r9,r9,0x400
+ stw r9,0x18(r4)
+ b unfreezegame
+
+bp:
+ rlwinm r9,r9,0,22,20
+ stw r9,0x18(r4)
+ beq cr5,finish
+ beq cr6,+8
+ addi r12,r12,4 # if databp r12=r12+4
+
+ li r3, 4 # 4 bytes
+ bl exireceivebuffer
+
+ ble cr6,noalignement # if not aligned data bp (0x89)
+
+ addi r12,r12,4
+
+ li r3, 4 # 4 bytes
+ bl exireceivebuffer
+
+noalignement:
+ lis r4, bpbuffer@h
+ ori r4, r4, bpbuffer@l # read buffer just store in lowmem
+
+ lwz r3, 0(r4) # inst bp
+ lwz r4, 4(r4) # data bp
+ mtspr 1010, r3 # set IABR
+ mtspr 1013, r4 # set DABR
+ b finish
+
+#******************************************************************
+# subroutine: bphandler
+# Data/Instruction address breakpoint handler, save context and return
+#******************************************************************
+
+#FIXME
+bphandler:
+ mtsprg 2,r1 # sprg2 = r1
+ lis r1, regbuffer@h
+ ori r1, r1, regbuffer@l
+ mtsprg 3,r3 # sprg3 = r3
+ mfsrr1 r3 # r3=srr1
+ rlwinm r3,r3,0,22,20 # clear trace
+ stw r3, 0x18(r1)
+ rlwinm r3,r3,0,24,15
+ ori r3,r3,0x2000
+ mfsrr0 r1 # r1=srr0
+
+# rlwinm r3,r3,0,17,15 # clear hw interrupt
+ mtsrr1 r3 # restore srr1 with hw interrupt & trace cleared
+
+ lis r3,break@h
+ ori r3,r3,break@l
+ mtsrr0 r3
+ rfi
+
+break:
+ lis r3, regbuffer@h
+ ori r3, r3, regbuffer@l
+ stw r1,0x14(r3) #stores srr0
+
+ mr r1,r3
+ mfsprg r3,3
+ stmw r2,0x24(r1) #saves r2-r31
+ mr r4,r1
+ mfsprg r1,2
+
+ stw r0,0x1C(r4)
+ stw r1,0x20(r4)
+
+ mflr r3
+ stw r3, 0x9C(r4) # Store LR
+
+ mfcr r3
+ stw r3, 0x0(r4) # Store CR
+
+ mfxer r3
+ stw r3, 0x4(r4) # Store XER
+
+ mfctr r3
+ stw r3, 0x8(r4) # Store CTR
+
+ mfdsisr r3
+ stw r3, 0xC(r4) # Store DSISR
+
+ mfdar r3
+ stw r3, 0x10(r4) # Store DAR
+
+ li r9,0
+ mtspr 1010,r9 # Clear IABR
+ mtspr 1013,r9 # Clear DABR
+
+ lis r5,floatstore@h
+ ori r5,r5,floatstore@l # Set r5 to instruction address
+ lis r31,0xD004
+ ori r31,r31,0x00A0 # Set r31 to 'stfs f0,0xA0(r4)' (==0xD00400A0)
+floatloop:
+ stw r31,0(r5)
+ dcbst r0,r5
+ sync
+ icbi r0,r5
+ isync
+floatstore:
+ stfs f0,0xA0(r4)
+ addi r31,r31,4 # Advance instruction offset
+ addis r31,r31,0x20 # Advance instruction register
+ rlwinm. r16,r31,0,5,5 # Check for register > 31
+ beq floatloop
+
+skip_floating_point:
+
+ lis r5, bpbuffer@h
+ ori r5,r5,bpbuffer@l
+
+ lwz r16,0(r5) # inst bp
+ lwz r17,4(r5) # data bp
+ lwz r19,12(r5) # counter for alignment
+
+ cmpwi r19,0
+ beq _redobp
+
+ cmpwi r19,2
+ bne +24
+ lwz r9,0x14(r4)
+ addi r9,r19,3
+ stw r9,0(r5) # inst bp
+ stw r9,12(r5) # counter for alignment
+ b _executebp
+
+ cmpw r16,r19
+ beq _step
+
+ cmpw r17,r19
+ beq _step
+
+ add r9,r16,r17
+ stw r9,12(r5) # counter for alignment
+
+
+_alignementcheck:
+ lwz r16,8(r5) # bp alignment check
+ cmpwi r16,0
+ beq _executebp # no alignement = normal break
+
+ lwz r3,0x10(r4)
+ cmpw r16,r3 # we check if address = aligned address
+ bne _step # if no, we need to set a bp on the next instruction
+
+ li r16,0
+ stw r16,8(r5) # if we are on the good address we clear the aligned bp check
+ b _executebp # and we break
+
+_step:
+ li r17,0
+ stw r17,12(r5) # counter for alignment
+ lwz r9,0x18(r4)
+ ori r9,r9,0x400
+ stw r9,0x18(r4)
+ b _skipbp #and we don't break right now
+
+_redobp:
+ mtspr 1010,r16 # we set back the instbp with the original value
+ mtspr 1013,r17 # we set back the databp with the original value
+ li r9,1
+ stw r9,12(r5) # counter for alignment
+ b _skipbp # and we don't break
+
+_executebp:
+ li r5, 2
+ lis r4, frozenvalue@h
+ ori r4, r4, frozenvalue@l # Freeze once returned to let user know there is a breakpoint hit
+ stw r5, 0(r4)
+
+ li r3, 0x11
+ bl exisendbyte # tell the PC a bp has happened (send 0x11)
+
+ bl _start # bl mainloop, so you can set up a new breakpoint.
+
+_skipbp:
+ mfmsr r1
+ rlwinm r1,r1,0,31,29
+ rlwinm r1,r1,0,17,15
+ mtmsr r1 # we disable the interrupt so nothing interfers with the restore
+
+ lis r1, regbuffer@h
+ ori r1, r1, regbuffer@l
+
+ lwz r3,0x0(r1)
+ mtcr r3 # restores CR
+ lwz r3,0x14(r1)
+ mtsrr0 r3 # restores SRR0
+ lwz r3,0x18(r1)
+ mtsrr1 r3 # restores SRR1
+ lwz r3,0x9C(r1)
+ mtlr r3 # restores LR
+
+ lmw r2,0x24(r1) # restores r2-r31
+
+ lwz r0,0x1C(r1) # restores r0
+ lwz r1,0x20(r1) # restores r1
+
+ rfi # back to the game
+
+#******************************************************************
+# subroutine: write dword:
+# Write a long word value to memory sent from PC
+#******************************************************************
+
+writedword:
+ cmpwi cr5,r29,2
+ li r3, 8 # 8 bytes (location 4 / Value 4)
+
+ lis r12, dwordbuffer@h
+ ori r12, r12, dwordbuffer@l # buffer
+ bl exireceivebuffer
+
+ lwz r5, 0(r12)
+ lwz r3, 4(r12) # read the value
+ stb r3, 0(r5) # write to location
+ blt cr5,skipp
+ sth r3, 0(r5) # write to location
+ beq cr5,skipp
+ stw r3, 0(r5) # write to location
+ skipp:
+ dcbf r0, r5 # data cache block flush
+ sync
+ icbi r0, r5
+ isync
+ b finish
+
+#******************************************************************
+# subroutine: Upload :
+# Fill memory with value
+#******************************************************************
+
+uploadcode:
+ bl exisendbyteAA
+
+ li r3, 8 # 8 bytes
+ lis r12, dwordbuffer@h
+ ori r12, r12, dwordbuffer@l # buffer
+
+ bl exireceivebuffer
+
+ lwz r16, 4(r12)
+ lwz r12, 0(r12)
+
+upload:
+ lis r27, rem@h
+ ori r27, r27, rem@l # Remainder of bytes upload code
+ li r17,0xF80
+ bl _packetdivide
+ beq douploadremainder
+
+nextrecpacket:
+ mr r3,r17
+ bl exireceivebuffer # r12 start = start of buffer
+
+uploadwait:
+ bl exisendbyteAA
+ beq uploadwait
+ add r12,r12,r14
+
+ subic. r11, r11, 1 # decrease loop counter
+ bgt nextrecpacket
+
+douploadremainder: # send the remainder bytes
+ lwz r3, 0(r27) # remainder
+ cmpwi r3,0
+ beq finishupload
+ bl exireceivebuffer
+finishupload:
+ dcbf r0, r12 # data cache block flush
+ sync
+ icbi r0, r12 # instruction cache block flush
+ isync
+ b finish
+
+#******************************************************************
+# subroutine: exireceivebyte:
+# Return 1(r3) if byte receive, 0(r3) if no byte
+# Command byte is stored at 0x800027ff
+#******************************************************************
+
+exireceivebyte:
+ mflr r30
+ lis r3, 0xA000 # EXI read command
+
+ bl checkexisend
+
+ andis. r3, r16, 0x800
+ rlwinm r29,r16,16,24,31
+ mtlr r30
+ blr
+
+#******************************************************************
+# subroutine: checkexisend:
+#
+#******************************************************************
+
+checkexisend:
+
+ stw r23, 0x6814(r24) # 32mhz Port B
+ stw r3, 0x6824(r24)
+ stw r22, 0x6820(r24) # 0xCC006820 (Channel 1 Control Register)
+
+exicheckreceivewait:
+ lwz r5, 0x6820(r24)
+ andi. r5, r5, 1
+ bne exicheckreceivewait # while((exi_chan1cr)&1);
+
+ lwz r16, 0x6824(r24)
+ stw r5, 0x6814(r24)
+
+ blr
+
+#******************************************************************
+# subroutine: exireceivebuffer:
+# r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed
+#******************************************************************
+
+exireceivebuffer:
+ mflr r10 # save link register
+ mtctr r3 # counter
+ li r14,0
+
+bufferloop:
+ bl exicheckreceive
+ bl exicheckreceive
+ bl exireceivebyte
+ beq bufferloop # r3 returns 1 or 0, one for byte received ok
+
+ stbx r29, r14,r12 # store byte into buffer
+
+ addi r14, r14, 1 # increase buffer by 1
+ bdnz bufferloop
+
+ mtlr r10 # retore link register
+ blr # return to command check
+
+#******************************************************************
+# exisendbuffer:
+# r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed
+#******************************************************************
+
+exisendbuffer:
+ mflr r10 # save link register
+ mtctr r3 # r3->counter
+ li r14,0
+
+sendloop:
+ lbzx r3, r12,r14
+ bl exisendbyte
+ beq sendloop
+
+ addi r14, r14, 1 # increase buffer
+ bdnz sendloop
+ mtlr r10 # restore link register
+ blr
+
+#******************************************************************
+# exisendbyte:12345678
+# r3 byte to send, returns 1 if sent, 0 if fail (!!! called by breakpoint)
+#******************************************************************
+exisendbyteAA:
+ li r3,0xAA
+
+exisendbyte: # r3, send value
+ mflr r30
+ slwi r3, r3, 20 # (sendbyte<<20);
+ oris r3, r3, 0xB000 # 0xB0000000 | (OR)
+ li r22,0x19
+ li r23,0xD0
+ lis r24,0xCD00
+
+ bl checkexisend
+
+ extrwi. r3, r16, 1,5 # returns either 0 or 1, one for byte received ok
+ mtlr r30
+ blr
+
+#******************************************************************
+# subroutine: exicheckrecieve:
+# Return 1(r3) lf byte receive, 0(r3) lf no byte
+#******************************************************************
+
+exicheckreceive:
+ mflr r30
+exicheckreceive2:
+ lis r3, 0xD000 # EXI check status command
+
+ bl checkexisend
+
+ rlwinm. r3,r16,6,31,31 # returns either 0 or 1 for r3
+
+ beq exicheckreceive2
+ mtlr r30
+ blr
+
+#******************************************************************
+# Readmem: (reads a memory range back to PC)
+# r3 byte to send, returns 1 lf sent, 0 lf fail
+#******************************************************************
+
+readmem:
+ bl exisendbyteAA
+
+ li r3, 8 # 8 bytes
+ lis r12, dwordbuffer@h
+ ori r12, r12, dwordbuffer@l # buffer
+
+ bl exireceivebuffer
+
+ lwz r5, 4(r12)
+ lwz r12, 0(r12)
+
+ lis r27, rem@h
+ ori r27, r27, rem@l # place holder for remainder bytes
+
+ ori r17, r21, 0xF800 # 64K packet
+ sub r16, r5, r12 # memrange = (*endlocation - *startlocation)
+
+ bl _packetdivide
+
+nextsendpacket:
+ bgt transfer #compares r11 and 0
+ lwz r17, 0(r27) # remainder
+ cmpwi r17,0
+ beq finish
+transfer:
+ mr r3,r17 # number of bytes
+ bl exisendbuffer
+
+bytewait1:
+ bl exicheckreceive
+ bl exicheckreceive
+ bl exireceivebyte
+ beq bytewait1 # r3 returns 1 or 0, one for byte received ok
+ cmpwi r29, 0xCC # cancel code
+ beq finish
+ cmpwi r29, 0xBB # retry code
+ beq transfer
+ cmpwi r29, 0xAA
+ bne bytewait1
+ add r12,r12,r14
+ subic. r11, r11, 1 # decrease loop counter
+ blt finish
+ b nextsendpacket
+
+#******************************************************************
+# Cancel Breakpoints
+# Clears instruction and data and step breakpoints
+#******************************************************************
+
+cancelbreakpoints:
+ mtspr 1013, r21 # clear the DABR
+ mtspr 1010, r21 # clear the IABR
+ lis r4, regbuffer@h
+ ori r4, r4, regbuffer@l
+ lwz r9,0x18(r4)
+ rlwinm r9,r9,0,22,20
+ stw r9,0x18(r4)
+ b finish
+
+#******************************************************************
+# subroutine: version number
+# Sends back the current gecko version number.
+#******************************************************************
+
+versionnumber:
+ li r3, 0x80 #0x80 = Wii, 0x81 = NGC
+ bl exisendbyte
+ #b finish
+
+#******************************************************************
+# Finish
+# Check if the gecko has been paused. if no return to game
+#******************************************************************
+
+finish:
+ lwz r4, 0(r18)
+ cmpwi r4, 0 # check to see if we have frozen the game
+ bne frozen # loop around if we have
+ # (changed to return for the bp)
+
+resumegame:
+
+ sth r28,0x4010(r20) # restore memory protection value
+
+ lfd f2,152(r1) # loads f2
+ lfd f3,160(r1) # loads f3
+
+ mfmsr r25
+
+ lwz r0,172(r1)
+ mtlr r0 # restores lr
+
+ lwz r0,12(r1)
+ mtcr r0 # restores cr
+
+ lwz r0,16(r1)
+ mtctr r0 # restores ctr
+
+ lwz r0,20(r1)
+ mtxer r0 # restores xer
+
+ lmw r3,24(r1) # restores r3-r31
+
+ lwz r0,8(r1) # loads r0
+
+ addi r1,r1,168
+
+ isync
+
+ blr # return back to game
+
+#******************************************************************
+# Write branch
+# r3 - source (our mastercode location)
+# r4 - destination (lowmem area 0x80001800 address which will branch to
+#******************************************************************
+writebranch:
+
+ subf r17, r3, r4 # subtract r3 from r4 and place in r17
+ lis r5, 0x4800 # 0x48000000
+ rlwimi r5,r17,0,6,29
+ stw r5, 0(r3) # result in r3
+
+ dcbf r0, r3 # data cache block flush
+ sync
+ icbi r0, r3
+ isync
+
+ blr # return
+
+
+#******************************************************************
+# Packet Divide
+# Used by the down/up routines to calculate the number of packet to send
+#******************************************************************
+
+_packetdivide:
+ divw. r11, r16, r17 # fullpackets = memrange / 0xF80 (r11 is full packets)
+ mullw r10, r11, r17
+ subf r10, r10, r16 # r10 holds remainder byte counter
+ stw r10, 0(r27) # store remainder
+ blr
+
+#==================================================================
+
+frozenvalue: #frozen value, then LR
+.long 0,0
+dwordbuffer:
+.long 0,0
+rem:
+.long 0
+bpbuffer:
+.long 0 #inst address to bp on
+.long 0 #data address to bp on
+.long 0 #alignement check
+.long 0 #counter for alignement
+
+regbuffer:
+.space 72*4
+
+state:
+.long 0 # 0=none 1=linked 2=???
+
+.align 3
+
+codelist:
+.space 2*4
+.end
+
+