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