boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

hex2.hex1 (31017B)


      1 ## Copyright (C) 2017 Jeremiah Orians
      2 ## Copyright (C) 2020 Sanne Wouda
      3 ## This file is part of stage0.
      4 ##
      5 ## stage0 is free software: you can redistribute it and/or modify
      6 ## it under the terms of the GNU General Public License as published by
      7 ## the Free Software Foundation, either version 3 of the License, or
      8 ## (at your option) any later version.
      9 ##
     10 ## stage0 is distributed in the hope that it will be useful,
     11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 ## GNU General Public License for more details.
     14 ##
     15 ## You should have received a copy of the GNU General Public License
     16 ## along with stage0.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 #:ELF_base
     19 
     20 7F 45 4C 46                    # e_ident[EI_MAG0-3] ELF's magic number
     21 
     22 02                             # e_ident[EI_CLASS] Indicating 64 bit
     23 01                             # e_ident[EI_DATA] Indicating little endianness
     24 01                             # e_ident[EI_VERSION] Indicating original elf
     25 
     26 03                             # e_ident[EI_OSABI] Set at 0 because none cares
     27 00                             # e_ident[EI_ABIVERSION] See above
     28 
     29 00 00 00 00 00 00 00           # e_ident[EI_PAD]
     30 02 00                          # e_type Indicating Executable
     31 B7 00                          # e_machine Indicating AArch64
     32 01 00 00 00                    # e_version Indicating original elf
     33 
     34 78 00 60 00 00 00 00 00          # e_entry Address of the entry point
     35 40 00 00 00 00 00 00 00 # e_phoff Address of program header table
     36 00 00 00 00 00 00 00 00 # e_shoff Address of section header table
     37 
     38 00 00 00 00                    # e_flags
     39 40 00                          # e_ehsize Indicating our 64 Byte header
     40 
     41 38 00                          # e_phentsize size of a program header table
     42 01 00                          # e_phnum number of entries in program table
     43 
     44 00 00                          # e_shentsize size of a section header table
     45 00 00                          # e_shnum number of entries in section table
     46 
     47 00 00                          # e_shstrndx index of the section names
     48 
     49 #:ELF_program_headers
     50 #:ELF_program_header__text
     51 01 00 00 00                   # ph_type: PT-LOAD = 1
     52 07 00 00 00                   # ph_flags: PF-X|PF-W|PF-R = 7
     53 00 00 00 00 00 00 00 00                   # ph_offset
     54 00 00 60 00 00 00 00 00                     # ph_vaddr
     55 00 00 60 00 00 00 00 00                     # ph_physaddr
     56 21 07 00 00 00 00 00 00             # ph_filesz
     57 21 07 00 00 00 00 00 00             # ph_memsz
     58 01 00 00 00 00 00 00 00                   # ph_align
     59 
     60     # Register usage:
     61     # X0, X1, X2, X3 => Temps
     62     # X15 => Flag
     63     # X14 => High bits
     64     # X13 => IP
     65     # X12 => MALLOC
     66     # X11 => HEAD
     67 
     68     # Struct format: (size 24)
     69     # NEXT => 0
     70     # TARGET => 8
     71     # NAME => 16
     72 
     73 #:ELF_text
     74 
     75 # Where the ELF Header is going to hit
     76 # Simply jump to _start
     77 # Our main function
     78 #:_start
     79     000080d2                    ; SET_X0_TO_0                   # Get current pointer
     80     ^~m 94                      ; ^~malloc FCALL                # Get current HEAP
     81     ec0300aa                    ; SET_X12_FROM_X0               # Setup MALLOC
     82     00007091                    ; ADD_X0_X0_12MB                # Create space for temp [12MB]
     83     ^~m 94                      ; ^~malloc FCALL                # Give ourselves 81920 bytes to work with
     84 
     85     e10b40f9                    ; LDR_X1_[SP,16]                # Get the actual input name
     86     600c8092                    ; SET_X0_TO_FCNTL_H_AT_FDCWD    # AT_FDCWD, relative to current working directory
     87     020080d2                    ; SET_X2_TO_0                   # Prepare file as read only
     88     080780d2                    ; SET_X8_TO_SYS_OPENAT          # The syscall number for openat(), aarch64 has no open()
     89     010000d4                    ; SYSCALL                       # Open file!
     90     e90300aa                    ; SET_X9_FROM_X0                # Preserve the file pointer we were given
     91 
     92     e10f40f9                    ; LDR_X1_[SP,24]                # Get the output name
     93     600c8092                    ; SET_X0_TO_FCNTL_H_AT_FDCWD    # AT_FDCWD, relative to current working directory
     94     224880d2                    ; SET_X2_TO_577                 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC
     95     033880d2                    ; SET_X3_TO_448                 # Prepare file as RWX for owner only (700 in octal)
     96     080780d2                    ; SET_X8_TO_SYS_OPENAT          # The syscall number for openat(), aarch64 has no open()
     97     010000d4                    ; SYSCALL                       # Open file!
     98     1f0000f1                    ; CMP_X0_TO_0                   # Check for missing output
     99     4d000054                    ; SKIP_INST_LE                  # Have real output
    100     ^~s 14                      ; ^~_start_out FBRANCH
    101     200080d2                    ; SET_X0_TO_1                   # Use stdout
    102 
    103 :s
    104     ea0300aa                    ; SET_X10_FROM_X0               # Preserve the file pointer we were given
    105 
    106     ^~C 94                      ; ^~ClearScratch FCALL          # Zero scratch
    107     0f008092                    ; SET_X15_TO_MINUS_1            # Our flag for byte processing
    108     0e0080d2                    ; SET_X14_TO_0                  # temp storage for the sum
    109     0d0ca0d2                    ; SET_X13_TO_0x00600000         # Our starting IP
    110     0b0080d2                    ; SET_X11_TO_0                  # HEAD = NULL
    111     ^~F 94                      ; ^~First_pass FCALL            # Process it
    112 
    113     # rewind input file
    114     e00309aa                    ; SET_X0_FROM_X9                # Using our input file
    115     010080d2                    ; SET_X1_TO_0                   # Offset
    116     020080d2                    ; SET_X2_TO_0                   # Whence SEEK_SET
    117     c80780d2                    ; SET_X8_TO_SYS_LSEEK           # lseek
    118     010000d4                    ; SYSCALL
    119 
    120     0f008092                    ; SET_X15_TO_MINUS_1            # Our flag for byte processing
    121     0e0080d2                    ; SET_X14_TO_0                  # temp storage for the sum
    122     0d0ca0d2                    ; SET_X13_TO_0x00600000         # Our starting IP
    123     ^~S 94                      ; ^~Second_pass FCALL           # Process it
    124 
    125     # program completed Successfully
    126     000080d2                    ; SET_X0_TO_0                   # All is well
    127     a80b80d2                    ; SET_X8_TO_SYS_EXIT            # put the exit syscall number in x8
    128     010000d4                    ; SYSCALL
    129 
    130 
    131 :F ; :First_pass
    132     fe0f1ff8                    ; PUSH_LR                       # push lr
    133 :a ; :First_pass_loop
    134     ^~R 94                      ; ^~Read_byte FCALL
    135 
    136     # Deal with EOF
    137     1f1000b1                    ; CMP_X0_TO_MINUS_4
    138     41000054                    ; SKIP_INST_NE
    139     ^~d 14                      ; ^~First_pass_done FBRANCH
    140 
    141     # Check for :
    142     1fe800f1                    ; CMP_X0_TO_58
    143     40000054                    ; SKIP_INST_EQ
    144     ^~b 14                      ; ^~First_pass_0 FBRANCH
    145 
    146     # Deal with label
    147     e0030caa                    ; SET_X0_FROM_X12               # ENTRY
    148     8c610091                    ; ADD_X12_X12_24                #^~ CALLOC
    149     0c0800f9                    ; STR_X12_[X0,16]               # ENTRY->NAME = TOKEN
    150     0d0400f9                    ; STR_X13_[X0,8]                # ENTRY->TARGET = IP
    151     0b0000f9                    ; STR_X11_[X0]                  # ENTRY->NEXT = HEAD
    152     eb0300aa                    ; SET_X11_FROM_X0               # HEAD = ENTRY
    153     e1030caa                    ; SET_X1_FROM_X12               # Write Starting after struct
    154     ^~J 94                      ; ^~consume_token FCALL         # Collect whole string
    155     ec0301aa                    ; SET_X12_FROM_X1               # Update HEAP
    156     ^~a 17                      ; ^~First_pass_loop RBRANCH
    157 
    158 :b ; :First_pass_0
    159     # Check for !
    160     1f8400f1                    ; CMP_X0_TO_33
    161     41000054                    ; SKIP_INST_NE
    162     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    163 
    164     # Check for @
    165     1f0001f1                    ; CMP_X0_TO_64
    166     41000054                    ; SKIP_INST_NE
    167     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    168 
    169     # Check for $
    170     1f9000f1                    ; CMP_X0_TO_36
    171     41000054                    ; SKIP_INST_NE
    172     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    173 
    174     # Check for %
    175     1f9400f1                    ; CMP_X0_TO_37
    176     41000054                    ; SKIP_INST_NE
    177     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    178 
    179     # Check for &
    180     1f9800f1                    ; CMP_X0_TO_38
    181     41000054                    ; SKIP_INST_NE
    182     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    183 
    184     # Check for ~
    185     1ff801f1                    ; CMP_X0_TO_126
    186     41000054                    ; SKIP_INST_NE
    187     ^~Z 14                      ; ^~First_pass_pointer FBRANCH
    188 
    189     # Deal with everything else
    190     ^~x 94                      ; ^~hex FCALL                   # Process our char
    191 
    192     # Deal with EOF
    193     1f1000b1                    ; CMP_X0_TO_MINUS_4
    194     41000054                    ; SKIP_INST_NE
    195     ^~d 14                      ; ^~First_pass_done FBRANCH
    196 
    197     # deal with -1 values
    198     1f0000f1                    ; CMP_X0_TO_0
    199     4a000054                    ; SKIP_INST_GE
    200     ^~a 17                      ; ^~First_pass_loop RBRANCH
    201 
    202     # deal with toggle
    203     ff0100f1                    ; CMP_X15_TO_0
    204     41000054                    ; SKIP_INST_NE
    205     ^~c 14                      ; ^~First_pass_1 FBRANCH
    206     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    207 
    208 :c ; :First_pass_1
    209     ef032faa                    ; NOT_X15_X15
    210     ^~a 17                      ; ^~First_pass_loop RBRANCH
    211 
    212 :Z ; :First_pass_pointer
    213     # Deal with Pointer to label
    214     ^~e 94                      ; ^~Update_Pointer FCALL        # Increment IP
    215     41000018                    ; LOAD_W1_AHEAD                 # Using scratch
    216     02000014                    ; SKIP_32_DATA
    217     &1                          ; &scratch
    218     ^~J 94                      ; ^~consume_token FCALL         # Read token
    219     ^~C 94                      ; ^~ClearScratch FCALL          # Throw away token
    220     1ff800f1                    ; CMP_X0_TO_62                  # check for '>'
    221     40000054                    ; SKIP_INST_EQ                  # Loop again
    222     ^~a 17                      ; ^~First_pass_loop RBRANCH
    223 
    224     # Deal with %label>label case
    225     41000018                    ; LOAD_W1_AHEAD                 # Write to scratch
    226     02000014                    ; SKIP_32_DATA
    227     &1                          ; &scratch
    228     ^~J 94                      ; ^~consume_token FCALL         # get token
    229     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    230     ^~a 17                      ; ^~First_pass_loop RBRANCH     # Loop again
    231 
    232 :d ; :First_pass_done
    233     fe0741f8                    ; POP_LR                        # pop lr
    234     c0035fd6                    ; RETURN
    235 
    236 :e ; :Update_Pointer
    237     # Check for !
    238     1f8400f1                    ; CMP_X0_TO_33
    239     41000054                    ; SKIP_INST_NE
    240     ^~i 14                      ; ^~Update_Pointer_1 FBRANCH
    241 
    242     # Check for @
    243     1f0001f1                    ; CMP_X0_TO_64
    244     41000054                    ; SKIP_INST_NE
    245     ^~h 14                      ; ^~Update_Pointer_2 FBRANCH
    246 
    247     # Check for $
    248     1f9000f1                    ; CMP_X0_TO_36
    249     41000054                    ; SKIP_INST_NE
    250     ^~h 14                      ; ^~Update_Pointer_2 FBRANCH
    251 
    252     # Check for ~
    253     1ff801f1                    ; CMP_X0_TO_126
    254     41000054                    ; SKIP_INST_NE
    255     ^~g 14                      ; ^~Update_Pointer_3 FBRANCH
    256 
    257     # Check for %
    258     1f9400f1                    ; CMP_X0_TO_37
    259     41000054                    ; SKIP_INST_NE
    260     ^~f 14                      ; ^~Update_Pointer_4 FBRANCH
    261 
    262     # Check for &
    263     1f9800f1                    ; CMP_X0_TO_38
    264     41000054                    ; SKIP_INST_NE
    265     ^~f 14                      ; ^~Update_Pointer_4 FBRANCH
    266 
    267     # deal with bad input
    268     ^~Y 14                      ; ^~fail FBRANCH
    269 
    270 :f ; :Update_Pointer_4
    271     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    272 :g ; :Update_Pointer_3
    273     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    274 :h ; :Update_Pointer_2
    275     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    276 :i ; Update_Pointer_1
    277     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    278     c0035fd6                    ; RETURN
    279 
    280 
    281 :S ; :Second_pass
    282     fe0f1ff8                    ; PUSH_LR                       # push lr
    283 
    284     # x7 marks whether we need to do a word-aligned pointer
    285 :j ; :Second_pass_loop
    286     070080d2                    ; SET_X7_TO_0
    287 :k ; :Second_pass_align
    288     ^~R 94                      ; ^~Read_byte FCALL
    289 
    290     # Deal with EOF
    291     1f1000b1                    ; CMP_X0_TO_MINUS_4
    292     41000054                    ; SKIP_INST_NE
    293     ^~w 14                      ; ^~Second_pass_done FBRANCH
    294 
    295     # Deal with ^
    296     1f7801f1                    ; CMP_X0_TO_94
    297     41000054                    ; SKIP_INST_NE
    298     ^~l 14                      ; ^~Second_pass_align_0 FBRANCH
    299 
    300     # Simply drop the label
    301     1fe800f1                    ; CMP_X0_TO_58
    302     40000054                    ; SKIP_INST_EQ
    303     ^~n 14                      ; ^~Second_pass_0 FBRANCH
    304 
    305     41000018                    ; LOAD_W1_AHEAD                 # Using scratch
    306     02000014                    ; SKIP_32_DATA
    307     &1                          ; &scratch
    308     ^~J 94                      ; ^~consume_token FCALL         # Read token
    309     ^~C 94                      ; ^~ClearScratch FCALL          # Throw away token
    310 
    311     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    312 
    313 :l ; :Second_pass_align_0
    314     e70327aa                    ; NOT_X7_X7                     # toggle alignment
    315     ^~k 17                      ; ^~Second_pass_align RBRANCH
    316 
    317 :n ; :Second_pass_0
    318     # Deal with % pointer
    319     1f9400f1                    ; CMP_X0_TO_37
    320     41000054                    ; SKIP_INST_NE
    321     ^~o 14                      ; ^~StorePointer_rel4 FBRANCH
    322 
    323     # Deal with ~ pointer
    324     1ff801f1                    ; CMP_X0_TO_126
    325     41000054                    ; SKIP_INST_NE
    326     ^~q 14                      ; ^~StorePointer_rel3 FBRANCH
    327 
    328     # Deal with @ pointer
    329     1f0001f1                    ; CMP_X0_TO_64
    330     41000054                    ; SKIP_INST_NE
    331     ^~r 14                      ; ^~StorePointer_rel2 FBRANCH
    332 
    333     # Deal with ! pointer
    334     1f8400f1                    ; CMP_X0_TO_33
    335     41000054                    ; SKIP_INST_NE
    336     ^~t 14                      ; ^~StorePointer_rel1 FBRANCH
    337 
    338     # Deal with & pointer
    339     1f9800f1                    ; CMP_X0_TO_38
    340     41000054                    ; SKIP_INST_NE
    341     ^~u 14                      ; ^~StorePointer_abs4 FBRANCH
    342 
    343     # Deal with $ pointer
    344     1f9000f1                    ; CMP_X0_TO_36
    345     41000054                    ; SKIP_INST_NE
    346     ^~v 14                      ; ^~StorePointer_abs2 FBRANCH
    347 
    348     # Deal with everything else
    349     ^~x 94                      ; ^~hex FCALL                   # Process our char
    350 
    351     # Deal with EOF
    352     1f1000b1                    ; CMP_X0_TO_MINUS_4
    353     41000054                    ; SKIP_INST_NE
    354     ^~w 14                      ; ^~Second_pass_done FBRANCH
    355 
    356     # deal with -1 values
    357     1f0000f1                    ; CMP_X0_TO_0
    358     4a000054                    ; SKIP_INST_GE
    359     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    360 
    361     # deal with toggle
    362     ff0100f1                    ; CMP_X15_TO_0
    363     41000054                    ; SKIP_INST_NE
    364     ^~p 14                      ; ^~print FBRANCH
    365 
    366     # process first byte of pair
    367     ee0300aa                    ; SET_X14_FROM_X0
    368     0f0080d2                    ; SET_X15_TO_0
    369     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    370 
    371     # process second byte of pair
    372 :p ; :print
    373     # update the sum and store in output
    374     00100e8b                    ; ADD_X0_X0_X14_LSL_4
    375 
    376     # Print our first Hex
    377     220080d2                    ; SET_X2_TO_1                   # set the size of chars we want
    378     ^~I 94                      ; ^~print_chars FCALL
    379 
    380     # flip the toggle
    381     ef032faa                    ; NOT_X15_X15
    382 
    383     ad050091                    ; ADD_X13_X13_1                 # Increment IP
    384     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    385 
    386 :o ; :StorePointer_rel4
    387     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    388     000002cb                    ; SUB_X0_X0_X2                  # target - ip
    389     470000b4                    ; CBZ_X7_PAST_INST
    390     00fc4293                    ; ASR_X0_X0_2
    391     820080d2                    ; SET_X2_TO_4                   # set the size of chars we want
    392     ^~I 94                      ; ^~print_chars FCALL
    393     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    394     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    395 
    396 :q ; :StorePointer_rel3
    397     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    398     000002cb                    ; SUB_X0_X0_X2                  # target - ip
    399     470000b4                    ; CBZ_X7_PAST_INST
    400     00fc4293                    ; ASR_X0_X0_2
    401     620080d2                    ; SET_X2_TO_3                   # set the size of chars we want
    402     ^~I 94                      ; ^~print_chars FCALL
    403     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    404     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    405 
    406 :r ; :StorePointer_rel2
    407     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    408     000002cb                    ; SUB_X0_X0_X2                  # target - ip
    409     470000b4                    ; CBZ_X7_PAST_INST
    410     00fc4293                    ; ASR_X0_X0_2
    411     420080d2                    ; SET_X2_TO_2                   # set the size of chars we want
    412     ^~I 94                      ; ^~print_chars FCALL
    413     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    414     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    415 
    416 :t ; :StorePointer_rel1
    417     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    418     000002cb                    ; SUB_X0_X0_X2                  # target - ip
    419     470000b4                    ; CBZ_X7_PAST_INST
    420     00fc4293                    ; ASR_X0_X0_2
    421     220080d2                    ; SET_X2_TO_1                   # set the size of chars we want
    422     ^~I 94                      ; ^~print_chars FCALL
    423     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    424     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    425 
    426 :u ; :StorePointer_abs4
    427     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    428     820080d2                    ; SET_X2_TO_4                   # set the size of chars we want
    429     ^~I 94                      ; ^~print_chars FCALL
    430     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    431     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    432 
    433 :v ; :StorePointer_abs2
    434     ^~W 94                      ; ^~StorePointer FCALL          # Do Common
    435     420080d2                    ; SET_X2_TO_2                   # set the size of chars we want
    436     ^~I 94                      ; ^~print_chars FCALL
    437     ^~C 94                      ; ^~ClearScratch FCALL          # Clean up after ourselves
    438     ^~j 17                      ; ^~Second_pass_loop RBRANCH
    439 
    440 :w ; :Second_pass_done
    441     fe0741f8                    ; POP_LR                        # pop lr
    442     c0035fd6                    ; RETURN
    443 
    444 :x ; :hex
    445     # deal with EOF
    446     1f1000b1                    ; CMP_X0_TO_MINUS_4
    447     41000054                    ; SKIP_INST_NE
    448     ^~z 14                      ; ^~EOF FBRANCH
    449     # deal with line comments starting with #
    450     1f8c00f1                    ; CMP_X0_TO_35
    451     41000054                    ; SKIP_INST_NE
    452     ^~E 14                      ; ^~ascii_comment FBRANCH
    453     # deal with line comments starting with ;
    454     1fec00f1                    ; CMP_X0_TO_59
    455     41000054                    ; SKIP_INST_NE
    456     ^~E 14                      ; ^~ascii_comment FBRANCH
    457     # deal all ascii less than 0
    458     1fc000f1                    ; CMP_X0_TO_48
    459     4a000054                    ; SKIP_INST_GE
    460     ^~y 14                      ; ^~ascii_other FBRANCH
    461     # deal with 0-9
    462     1fe800f1                    ; CMP_X0_TO_58
    463     4a000054                    ; SKIP_INST_GE
    464     ^~A 14                      ; ^~ascii_num FBRANCH
    465     # deal with all ascii less than A
    466     1f0401f1                    ; CMP_X0_TO_65
    467     4a000054                    ; SKIP_INST_GE
    468     ^~y 14                      ; ^~ascii_other FBRANCH
    469     # deal with A-F
    470     1f1c01f1                    ; CMP_X0_TO_71
    471     4a000054                    ; SKIP_INST_GE
    472     ^~D 14                      ; ^~ascii_high FBRANCH
    473     #deal with all ascii less than a
    474     1f8401f1                    ; CMP_X0_TO_97
    475     4a000054                    ; SKIP_INST_GE
    476     ^~y 14                      ; ^~ascii_other FBRANCH
    477     #deal with a-f
    478     1f9c01f1                    ; CMP_X0_TO_103
    479     4a000054                    ; SKIP_INST_GE
    480     ^~B 14                      ; ^~ascii_low FBRANCH
    481     # The rest that remains needs to be ignored
    482 :y ; :ascii_other
    483     00008092                    ; SET_X0_TO_MINUS_1
    484     c0035fd6                    ; RETURN
    485 
    486 :z ; :EOF
    487     c0035fd6                    ; RETURN
    488 :A ; :ascii_num
    489     00c000d1                    ; SUB_X0_X0_48
    490     c0035fd6                    ; RETURN
    491 :B ; :ascii_low
    492     005c01d1                    ; SUB_X0_X0_87
    493     c0035fd6                    ; RETURN
    494 :D ; :ascii_high
    495     00dc00d1                    ; SUB_X0_X0_55
    496     c0035fd6                    ; RETURN
    497 :E ; :ascii_comment
    498     fe0f1ff8                    ; PUSH_LR                       # push lr
    499 :G ; :ascii_comment_loop
    500     ^~R 94                      ; ^~Read_byte FCALL
    501     1f3400f1                    ; CMP_X0_TO_13
    502     41000054                    ; SKIP_INST_NE
    503     ^~H 14                      ; ^~ascii_comment_cr FBRANCH
    504     1f2800f1                    ; CMP_X0_TO_10
    505     40000054                    ; SKIP_INST_EQ
    506     ^~G 17                      ; ^~ascii_comment_loop RBRANCH
    507 :H ; :ascii_comment_cr
    508     00008092                    ; SET_X0_TO_MINUS_1
    509     fe0741f8                    ; POP_LR                        # pop lr
    510     c0035fd6                    ; RETURN
    511 
    512 
    513 # Malloc isn't actually required if the program being built fits in the initial memory
    514 # However, it doesn't take much to add it.
    515 # Requires a value in X0
    516 :m
    517     c81a80d2                    ; SET_X8_TO_SYS_BRK             # the Syscall # for SYS_BRK
    518     010000d4                    ; SYSCALL                       # call the Kernel
    519     c0035fd6                    ; RETURN
    520 
    521 
    522 :R ; :Read_byte
    523     e10f1ff8                    ; PUSH_X1
    524     60008092                    ; SET_X0_TO_MINUS_4             # Put EOF in x0
    525     e00f1ff8                    ; PUSH_X0
    526 
    527     # Attempt to read 1 byte from STDIN
    528     e00309aa                    ; SET_X0_FROM_X9                # Where are we reading from
    529     e1030091                    ; SET_X1_FROM SP                # Where to put it
    530     220080d2                    ; SET_X2_TO_1                   # set the size of chars we want
    531     e80780d2                    ; SET_X8_TO_SYS_READ            # the syscall number for read
    532     010000d4                    ; SYSCALL                       # call the Kernel
    533 
    534     e0078138                    ; POP_X0SB
    535     e10741f8                    ; POP_X1
    536     c0035fd6                    ; RETURN
    537 
    538 :I ; :print_chars
    539     e00f1ff8                    ; PUSH_X0
    540     e1030091                    ; SET_X1_FROM_SP
    541     e0030aaa                    ; SET_X0_FROM_X10               # Write to target file
    542     080880d2                    ; SET_X8_TO_SYS_WRITE           # the syscall number for write
    543     010000d4                    ; SYSCALL                       # call the Kernel
    544     e00741f8                    ; POP_X0
    545     c0035fd6                    ; RETURN
    546 
    547 # Receives pointer in x1
    548 # Writes out char and updates x1
    549 # leaves with x1 8-byte aligned
    550 :J ; :consume_token
    551     fe0f1ff8                    ; PUSH_LR                       # push lr
    552 :K ; :consume_token_loop
    553     ^~R 97                      ; ^~Read_byte RCALL             # Consume_token
    554 
    555     1f1000b1                    ; CMP_X0_TO_MINUS_4
    556     41000054                    ; SKIP_INST_NE
    557     ^~L 14                      ; ^~consume_token_done FBRANCH
    558 
    559     # Check for \t
    560     1f2400f1                    ; CMP_X0_TO_9
    561     41000054                    ; SKIP_INST_NE
    562     ^~L 14                      ; ^~consume_token_done FBRANCH
    563 
    564     # Check for \n
    565     1f2800f1                    ; CMP_X0_TO_10
    566     41000054                    ; SKIP_INST_NE
    567     ^~L 14                      ; ^~consume_token_done FBRANCH
    568 
    569     # Check for ' '
    570     1f8000f1                    ; CMP_X0_TO_32
    571     41000054                    ; SKIP_INST_NE
    572     ^~L 14                      ; ^~consume_token_done FBRANCH
    573 
    574     # Check for '>'
    575     1ff800f1                    ; CMP_X0_TO_62
    576     41000054                    ; SKIP_INST_NE
    577     ^~L 14                      ; ^~consume_token_done FBRANCH
    578 
    579     # Looks like we are still reading token
    580     20140038                    ; STR_BYTE_W0_[X1]_1            # store char and update pointer
    581     ^~K 17                      ; ^~consume_token_loop RBRANCH  # loop until done
    582 
    583 :L ; :consume_token_done
    584     030080d2                    ; SET_X3_TO_0
    585 :M ; :consume_token_pad
    586     23140038                    ; STR_BYTE_W3_[X1]_1            # write at least one zero-byte
    587     3f0840f2                    ; TST_X1_7                      # is x1 8-byte aligned?
    588     40000054                    ; SKIP_INST_EQ
    589     ^~M 17                      ; ^~consume_token_pad RBRANCH
    590 
    591     fe0741f8                    ; POP_LR                        # pop lr
    592     c0035fd6                    ; RETURN
    593 
    594 # finds label matching pointer in scratch
    595 #  clobbers  x1, x3, x4, x5
    596 #  returns address in x0
    597 :N ; :GetTarget
    598     e5030baa                    ; SET_X5_FROM_X11               # Grab HEAD
    599 :O ; :GetTarget_loop
    600     44000018                    ; LOAD_W4_AHEAD                 # Reset scratch
    601     02000014                    ; SKIP_32_DATA
    602     &1                          ; &scratch
    603     a30840f9                    ; LDR_X3_[X5,16]                # I->NAME
    604 :P ; :GetTarget_loop_0
    605     60144038                    ; LDR_BYTE_W0_[X3]_1            # I->NAME[0]
    606     81144038                    ; LDR_BYTE_W1_[X4]_1            # scratch[0]
    607     1f0001eb                    ; CMP_X0_X1                     # IF TOKEN == I->NAME
    608     40000054                    ; SKIP_INST_EQ                  # Oops
    609     ^~T 14                      ; ^~GetTarget_miss FBRANCH
    610 
    611     3f0000f1                    ; CMP_X1_TO_0
    612     40000054                    ; SKIP_INST_EQ                  # Loop until
    613     ^~P 17                      ; ^~GetTarget_loop_0 RBRANCH
    614     ^~U 14                      ; ^~GetTarget_done FBRANCH      # Match
    615 
    616     # Miss
    617 :T ; :GetTarget_miss
    618     a50040f9                    ; DEREF_X5                      # I = I->NEXT
    619     bf0000f1                    ; CMP_X5_TO_0                   # IF NULL == I
    620     41000054                    ; SKIP_INST_NE                  # Abort hard
    621     ^~Y 14                      ; ^~fail FBRANCH
    622 
    623     ^~O 17                      ; ^~GetTarget_loop RBRANCH
    624 
    625 :U ; GetTarget_done
    626     a00440f9                    ; LDR_X0_[X5,8]                 # Get address
    627     c0035fd6                    ; RETURN
    628 
    629 # clobbers x3, x4
    630 :C ; ClearScratch
    631     e00f1ff8                    ; PUSH_X0
    632     44000018                    ; LOAD_W4_AHEAD                 # Where our table is
    633     02000014                    ; SKIP_32_DATA
    634     &1                          ; &scratch
    635     000080d2                    ; SET_X0_TO_0                   # Using null
    636 
    637 :V ; :ClearScratch_loop
    638     83004039                    ; LDR_BYTE_W3_[X4]              # Get current value
    639     801c0038                    ; STR_BYTE_W0_[X4,1]_WB         # Because we want nuoll
    640     7f0000f1                    ; CMP_X3_TO_0                   # Check if we hit null
    641     40000054                    ; SKIP_INST_EQ                  # Keep looping
    642     ^~V 17                      ; ^~ClearScratch_loop RBRANCH
    643 
    644     e00741f8                    ; POP_X0
    645     c0035fd6                    ; RETURN
    646 
    647 
    648 # returns target in x0, base in x2
    649 :W ; :StorePointer
    650     fe0f1ff8                    ; PUSH_LR
    651     e6030daa                    ; SET_X6_FROM_X13
    652     ^~e 97                      ; ^~Update_Pointer RCALL        # Increment IP
    653     41000018                    ; LOAD_W1_AHEAD                 # Write to scratch
    654     02000014                    ; SKIP_32_DATA
    655     &1                          ; &scratch
    656     ^~J 97                      ; ^~consume_token RCALL         # get token
    657     e00f1ff8                    ; PUSH_X0                       # Protect base_sep_p
    658     ^~N 97                      ; ^~GetTarget RCALL             # Get address of pointer
    659     ^~C 97                      ; ^~ClearScratch RCALL          # Clean up after ourselves
    660     e20306aa                    ; SET_X2_FROM_X6                # base = IP
    661     e10741f8                    ; POP_X1                        # Restore base_sep_p
    662     3ff800f1                    ; CMP_X1_TO_62                  # If base_sep_p == '>'
    663     40000054                    ; SKIP_INST_EQ                  # If not
    664     ^~X 14                      ; ^~StorePointer_done FBRANCH
    665 
    666     # Deal with %label>label case
    667     e00f1ff8                    ; PUSH_X0                       # We need to preserve main target
    668     41000018                    ; LOAD_W1_AHEAD                 # Write to scratch
    669     02000014                    ; SKIP_32_DATA
    670     &1                          ; &scratch
    671     ^~J 97                      ; ^~consume_token RCALL         # get token
    672     ^~N 97                      ; ^~GetTarget RCALL             # Get address of pointer
    673     ^~C 97                      ; ^~ClearScratch RCALL          # Clean up after ourselves
    674     e20300aa                    ; SET_X2_FROM_X0                # Use our new base
    675     e00741f8                    ; POP_X0                        # Restore main target
    676 
    677 :X ; :StorePointer_done
    678     fe0741f8                    ; POP_LR                        # pop lr
    679     c0035fd6                    ; RETURN
    680 
    681 
    682 :Y ; fail
    683     # Some shit went wrong
    684     200080d2                    ; SET_X0_TO_1                   # All is wrong
    685     a80b80d2                    ; SET_X8_TO_SYS_EXIT            # put the exit syscall number in eax
    686     010000d4                    ; SYSCALL                       # Call it a good day
    687 
    688 #:ELF_data
    689 :0
    690     0000000000000000            ; NULL64
    691 :1
    692     00                          ; NULL8
    693 
    694 #:ELF_end