hex2pp.P1 (66945B)
1 ## hex2pp.P1 -- P1 implementation of the hex2++ assembler/linker. 2 ## 3 ## Mirrors hex2pp/hex2pp.c. See docs/HEX2pp.md for the full spec; brief: 4 ## 5 ## Input is scanned once. Label definitions are recorded into a table 6 ## on the fly; label references emit zero placeholders and append a 7 ## fixup record. After the scan, fixups are resolved against the 8 ## completed label table and patched into the output buffer. 9 ## 10 ## Active syntax: 11 ## digits in current byte mode -> raw bytes (HEX or BINARY) 12 ## :NAME -> label definition 13 ## SIGIL NAME [- OTHER] -> label reference (! @ $ ~ % &) 14 ## .align N [PATTERN] -> pad to N-byte boundary 15 ## .fill N B -> N copies of byte B 16 ## .scope / .endscope -> nestable local-label scope 17 ## .ptrsize N -> width of '%' and '&' (4 or 8) 18 ## # ... / ; ... -> line comment 19 ## 20 ## Multi-byte reference values are emitted little-endian by default. 21 ## 22 ## Invocation: hex2pp [-B ADDR] [-E|-e] [-b] [-N] IN OUT 23 ## 24 ## P1 ABI: a0..a3 arg/return, t0..t2 caller-saved temps. Non-leaf 25 ## functions use enter_0 / eret. Entry is the portable p1_main 26 ## (a0=argc, a1=argv); the backend-owned :_start stub captures argc/argv 27 ## from the native entry state and sys_exits p1_main's return value. 28 ## 29 ## chmod note: the seed P1 mnemonic table only exposes openat/read/write/ 30 ## exit. We encode the desired final mode (0750 or 0640) directly in 31 ## openat's mode argument at file-creation time, achieving the same 32 ## resulting file permissions as the C reference's fopen+chmod. 33 34 ## --- Caps ------------------------------------------------------------------ 35 ## Mirrors hex2pp.c constants. Stored as 8-byte little-endian. 36 DEFINE H2_INPUT_CAP 0000000800000000 37 DEFINE H2_OUTPUT_CAP 0000000800000000 38 DEFINE H2_TEXT_CAP 0000800000000000 39 DEFINE H2_LABEL_CAP 0000100000000000 40 DEFINE H2_TOKEN_CAP 0010000000000000 41 DEFINE H2_SCOPE_CAP 2000000000000000 42 DEFINE H2_FIXUP_CAP 0000100000000000 43 DEFINE H2_SCOPE_HISTORY_CAP 0000400000000000 44 45 ## openat / mode constants (Linux generic). 46 DEFINE H2_O_WRONLY_CREAT_TRUNC 4102000000000000 47 DEFINE H2_O_RDONLY 0000000000000000 48 DEFINE H2_MODE_0750 E801000000000000 49 DEFINE H2_MODE_0640 A001000000000000 50 DEFINE H2_AT_FDCWD 9CFFFFFFFFFFFFFF 51 52 DEFINE ZERO8 '0000000000000000' 53 DEFINE ZERO4 '00000000' 54 55 ## --- BSS layout (offsets from ELF_end) ------------------------------------- 56 ## Each "_ptr" is a one-word slot in the executable's static data; p1_main's 57 ## bss_init_loop initializes each to ELF_end + OFF_*. Arenas live past 58 ## ELF_end (covered by the segment's memsz; the loader zero-initializes). 59 ## 60 ## Region sizes (matching the C caps): 61 ## scope_stack 32 * 8 = 256 B 62 ## line_scratch = 64 B 63 ## name_buf = 4096 B (used by read_directive_name) 64 ## label_buf = 4096 B (unused since single-pass refactor) 65 ## other_buf = 4096 B (unused since single-pass refactor) 66 ## pat_buf = 4096 B 67 ## ev_bytes = 8 B 68 ## df_byte = 8 B 69 ## input_buf = 128 MiB 70 ## output_buf = 128 MiB 71 ## text_buf = 8 MiB 72 ## labels = 32 MiB (1<<20 * 32 B) 73 ## fixups = 96 MiB (1<<20 * 96 B) 74 ## scope_history = 32 MiB (1<<22 * 8 B) 75 ## 76 ## Compact cumulative offsets in 8-byte little-endian hex. 77 DEFINE H2_OFF_scope_stack 0000000000000000 78 DEFINE H2_OFF_line_scratch 0001000000000000 79 DEFINE H2_OFF_name_buf 4001000000000000 80 DEFINE H2_OFF_label_buf 4011000000000000 81 DEFINE H2_OFF_other_buf 4021000000000000 82 DEFINE H2_OFF_pat_buf 4031000000000000 83 DEFINE H2_OFF_ev_bytes 4041000000000000 84 DEFINE H2_OFF_df_byte 5041000000000000 85 ## input_buf: 0x00004200 + 128 MiB 86 ## output_buf: 0x08004200 + 128 MiB 87 ## text_buf: 0x10004200 + 8 MiB 88 ## labels: 0x10804200 + 32 MiB 89 ## fixups: 0x12804200 + 96 MiB 90 ## scope_history: 0x18804200 + 32 MiB (end at ~424 MiB; ELF p_memsz is 512 MiB). 91 DEFINE H2_OFF_input_buf 0042000000000000 92 DEFINE H2_OFF_output_buf 0042000800000000 93 DEFINE H2_OFF_text_buf 0042001000000000 94 DEFINE H2_OFF_labels 0042801000000000 95 DEFINE H2_OFF_fixups 0042801200000000 96 DEFINE H2_OFF_scope_history 0042801800000000 97 98 ## --- p1_main: argv parse -> load input -> two passes -> write -> exit ------ 99 100 :p1_main 101 enter_0 102 103 # Save argc / argv before anything clobbers them. 104 la_a2 &saved_argc 105 st_a0,a2,0 106 la_a2 &saved_argv 107 st_a1,a2,0 108 109 # Init BSS pointer slots from ELF_end via table walk. 110 la_t0 &ELF_end 111 la_t1 &bss_init_tbl 112 la_t2 &bss_init_tbl_end 113 :bss_init_loop 114 la_br &bss_init_done 115 beq_t1,t2 116 ld_a2,t1,0 117 ld_a3,t1,8 118 add_a3,a3,t0 119 st_a3,a2,0 120 addi_t1,t1,16 121 la_br &bss_init_loop 122 b 123 :bss_init_done 124 125 # Default ptrsize = 4. 126 li_t0 %4 %0 127 la_a2 &ptrsize 128 st_t0,a2,0 129 130 # ---- Argv loop -------------------------------------------------------- 131 # i = 1 132 li_t0 %1 %0 133 la_a2 &arg_idx 134 st_t0,a2,0 135 :arg_loop 136 la_a0 &arg_idx 137 ld_t0,a0,0 138 la_a1 &saved_argc 139 ld_t1,a1,0 140 la_br &arg_done 141 beq_t0,t1 142 la_br &arg_done 143 blt_t1,t0 144 145 # arg_ptr = argv[i] 146 la_a0 &saved_argv 147 ld_a1,a0,0 148 li_t2 p1wordshift 149 shl_t2,t0,t2 150 add_a1,a1,t2 151 ld_a0,a1,0 152 la_a2 &arg_ptr 153 st_a0,a2,0 154 155 # Match against known short flags. 156 la_a1 &opt_B 157 li_a2 %2 %0 158 la_br &str_eq 159 call 160 la_br &arg_is_B 161 bnez_a0 162 163 la_a0 &arg_ptr 164 ld_a0,a0,0 165 la_a1 &opt_E 166 li_a2 %2 %0 167 la_br &str_eq 168 call 169 la_br &arg_is_big 170 bnez_a0 171 172 la_a0 &arg_ptr 173 ld_a0,a0,0 174 la_a1 &opt_e 175 li_a2 %2 %0 176 la_br &str_eq 177 call 178 la_br &arg_is_little 179 bnez_a0 180 181 la_a0 &arg_ptr 182 ld_a0,a0,0 183 la_a1 &opt_b 184 li_a2 %2 %0 185 la_br &str_eq 186 call 187 la_br &arg_is_binary 188 bnez_a0 189 190 la_a0 &arg_ptr 191 ld_a0,a0,0 192 la_a1 &opt_N 193 li_a2 %2 %0 194 la_br &str_eq 195 call 196 la_br &arg_is_nonexec 197 bnez_a0 198 199 # Unrecognised. If first byte is '-' (and string len > 1), error. 200 la_a0 &arg_ptr 201 ld_a0,a0,0 202 lb_t0,a0,0 203 li_t1 %45 %0 204 la_br &arg_is_positional 205 bne_t0,t1 206 lb_t0,a0,1 207 la_br &arg_is_positional 208 beqz_t0 209 la_br &err_unknown_arg 210 b 211 212 :arg_is_positional 213 # First positional = input path; second = output path; third = error. 214 la_a0 &input_path 215 ld_t0,a0,0 216 la_br &arg_pos_set_out 217 bnez_t0 218 la_a1 &arg_ptr 219 ld_t0,a1,0 220 st_t0,a0,0 221 la_br &arg_loop_next 222 b 223 :arg_pos_set_out 224 la_a0 &output_path 225 ld_t0,a0,0 226 la_br &err_extra_positional 227 bnez_t0 228 la_a1 &arg_ptr 229 ld_t0,a1,0 230 st_t0,a0,0 231 la_br &arg_loop_next 232 b 233 234 :arg_is_B 235 # -B requires a value in the next argv slot. 236 la_a0 &arg_idx 237 ld_t0,a0,0 238 addi_t0,t0,1 239 st_t0,a0,0 240 la_a1 &saved_argc 241 ld_t1,a1,0 242 la_br &err_missing_value 243 beq_t0,t1 244 la_br &err_missing_value 245 blt_t1,t0 246 la_a0 &saved_argv 247 ld_a1,a0,0 248 li_t2 p1wordshift 249 shl_t2,t0,t2 250 add_a1,a1,t2 251 ld_a0,a1,0 252 la_br &parse_long 253 call 254 la_a1 &base_address 255 st_a0,a1,0 256 la_br &arg_loop_next 257 b 258 259 :arg_is_big 260 li_t0 %1 %0 261 la_a1 &big_endian 262 st_t0,a1,0 263 la_br &arg_loop_next 264 b 265 266 :arg_is_little 267 li_t0 %0 %0 268 la_a1 &big_endian 269 st_t0,a1,0 270 la_br &arg_loop_next 271 b 272 273 :arg_is_binary 274 li_t0 %1 %0 275 la_a1 &byte_mode 276 st_t0,a1,0 277 la_br &arg_loop_next 278 b 279 280 :arg_is_nonexec 281 li_t0 %1 %0 282 la_a1 &non_executable 283 st_t0,a1,0 284 la_br &arg_loop_next 285 b 286 287 :arg_loop_next 288 la_a0 &arg_idx 289 ld_t0,a0,0 290 addi_t0,t0,1 291 st_t0,a0,0 292 la_br &arg_loop 293 b 294 295 :arg_done 296 la_a0 &input_path 297 ld_t0,a0,0 298 la_br &err_missing_positional 299 beqz_t0 300 la_a0 &output_path 301 ld_t0,a0,0 302 la_br &err_missing_positional 303 beqz_t0 304 305 # ---- Load input file ------------------------------------------------- 306 la_br &load_input 307 call 308 309 # ---- Single scan: builds labels + fixup list ------------------------- 310 li_t0 %0 %0 311 la_a0 &ip 312 st_t0,a0,0 313 la_a0 &output_used 314 st_t0,a0,0 315 la_a0 &scope_depth 316 st_t0,a0,0 317 la_a0 &scope_seq 318 st_t0,a0,0 319 la_a0 &ptrsize_used 320 st_t0,a0,0 321 li_t0 %4 %0 322 la_a0 &ptrsize 323 st_t0,a0,0 324 la_br &process_input 325 call 326 la_a0 &scope_depth 327 ld_t0,a0,0 328 la_br &err_scope_unclosed 329 bnez_t0 330 331 # ---- Resolve fixups -------------------------------------------------- 332 la_br &patch_fixups 333 call 334 335 # Clear cur_path so any post-fixup error reports without file:line. 336 li_t0 %0 %0 337 la_a0 &cur_path 338 st_t0,a0,0 339 340 la_br &write_output 341 call 342 343 li_a0 %0 %0 344 eret 345 346 ## --- Input loader ---------------------------------------------------------- 347 ## load_input(): openat(input_path), read into input_buf until EOF. 348 :load_input 349 enter_0 350 # fd = openat(AT_FDCWD, input_path, O_RDONLY, 0) 351 li_a0 sys_openat 352 li_a1 H2_AT_FDCWD 353 la_a2 &input_path 354 ld_a2,a2,0 355 li_a3 H2_O_RDONLY 356 li_t0 %0 %0 357 syscall 358 la_br &err_open_input 359 bltz_a0 360 la_a1 &input_fd 361 st_a0,a1,0 362 363 :li_read_loop 364 la_a0 &input_len 365 ld_t0,a0,0 366 li_t1 H2_INPUT_CAP 367 la_br &err_input_too_big 368 beq_t0,t1 369 la_br &err_input_too_big 370 blt_t1,t0 371 372 # n = read(fd, input_buf + input_len, INPUT_CAP - input_len) 373 la_a0 &input_fd 374 ld_a1,a0,0 375 la_a2 &input_buf_ptr 376 ld_a2,a2,0 377 add_a2,a2,t0 378 sub_a3,t1,t0 379 li_a0 sys_read 380 syscall 381 la_br &li_eof 382 beqz_a0 383 la_br &err_read 384 bltz_a0 385 386 la_a1 &input_len 387 ld_t0,a1,0 388 add_t0,t0,a0 389 st_t0,a1,0 390 la_br &li_read_loop 391 b 392 393 :li_eof 394 eret 395 396 ## --- Process input: scan one pass over input_buf --------------------------- 397 :process_input 398 enter_0 399 # cur_path = input_path; cur_line = 1 400 la_a0 &input_path 401 ld_t0,a0,0 402 la_a1 &cur_path 403 st_t0,a1,0 404 li_t0 %1 %0 405 la_a1 &cur_line 406 st_t0,a1,0 407 408 # scan_pos = input_buf; scan_end = input_buf + input_len 409 la_a0 &input_buf_ptr 410 ld_t0,a0,0 411 la_a1 &scan_pos 412 st_t0,a1,0 413 la_a0 &input_len 414 ld_t1,a0,0 415 add_t0,t0,t1 416 la_a1 &scan_end 417 st_t0,a1,0 418 419 :scan_loop 420 la_br &skip_ws_and_comments 421 call 422 la_a0 &scan_pos 423 ld_t0,a0,0 424 la_a1 &scan_end 425 ld_t1,a1,0 426 la_br &scan_done 427 beq_t0,t1 428 la_br &scan_done 429 blt_t1,t0 430 lb_a0,t0,0 431 432 li_t1 %58 %0 433 la_br &handle_label_def 434 beq_a0,t1 435 li_t1 %46 %0 436 la_br &handle_directive 437 beq_a0,t1 438 li_t1 %33 %0 439 la_br &handle_ref 440 beq_a0,t1 441 li_t1 %64 %0 442 la_br &handle_ref 443 beq_a0,t1 444 li_t1 %36 %0 445 la_br &handle_ref 446 beq_a0,t1 447 li_t1 %126 %0 448 la_br &handle_ref 449 beq_a0,t1 450 li_t1 %37 %0 451 la_br &handle_ref 452 beq_a0,t1 453 li_t1 %38 %0 454 la_br &handle_ref 455 beq_a0,t1 456 la_br &is_byte_digit 457 call 458 la_br &handle_byte_stream 459 bnez_a0 460 la_br &err_unexpected_char 461 b 462 463 :handle_label_def 464 # consume ':' 465 la_a0 &scan_pos 466 ld_t0,a0,0 467 addi_t0,t0,1 468 st_t0,a0,0 469 # scan_name -> length in a0, pointer in sn_start (no copy). 470 la_br &scan_name 471 call 472 la_a1 &name_len 473 st_a0,a1,0 474 # dotted = (name[0] == '.') AND scope_depth > 0 475 la_a0 &sn_start 476 ld_a0,a0,0 477 lb_t0,a0,0 478 li_t1 %46 %0 479 la_br &handle_label_global 480 bne_t0,t1 481 la_a0 &scope_depth 482 ld_t0,a0,0 483 la_br &handle_label_global 484 beqz_t0 485 # scope_id = scope_stack[scope_depth-1] 486 addi_t0,t0,neg1 487 la_a1 &scope_stack_ptr 488 ld_a1,a1,0 489 shli_t2,t0,3 490 add_a1,a1,t2 491 ld_t0,a1,0 492 la_a2 &name_scope 493 st_t0,a2,0 494 la_br &handle_label_dispatch 495 b 496 :handle_label_global 497 li_t0 %0 %0 498 la_a2 &name_scope 499 st_t0,a2,0 500 :handle_label_dispatch 501 la_a0 &sn_start 502 ld_a0,a0,0 503 la_a1 &name_len 504 ld_a1,a1,0 505 la_a2 &name_scope 506 ld_a2,a2,0 507 la_br &define_label 508 call 509 la_br &scan_loop 510 b 511 512 :handle_directive 513 # consume '.' 514 la_a0 &scan_pos 515 ld_t0,a0,0 516 addi_t0,t0,1 517 st_t0,a0,0 518 la_a0 &name_buf_ptr 519 ld_a0,a0,0 520 li_a1 H2_TOKEN_CAP 521 la_br &read_directive_name 522 call 523 la_a1 &name_len 524 st_a0,a1,0 525 526 # Dispatch by length, then memcmp. 527 la_a0 &name_len 528 ld_t0,a0,0 529 li_t1 %5 %0 530 la_br &dir_check_4 531 bne_t0,t1 532 # Could be "align" or "scope". 533 la_a0 &name_buf_ptr 534 ld_a0,a0,0 535 la_a1 &kw_align 536 li_a2 %5 %0 537 la_br &mem_eq 538 call 539 la_br &dir_call_align 540 bnez_a0 541 la_a0 &name_buf_ptr 542 ld_a0,a0,0 543 la_a1 &kw_scope 544 li_a2 %5 %0 545 la_br &mem_eq 546 call 547 la_br &dir_call_scope 548 bnez_a0 549 la_br &err_unknown_directive 550 b 551 :dir_check_4 552 li_t1 %4 %0 553 la_br &dir_check_8 554 bne_t0,t1 555 la_a0 &name_buf_ptr 556 ld_a0,a0,0 557 la_a1 &kw_fill 558 li_a2 %4 %0 559 la_br &mem_eq 560 call 561 la_br &dir_call_fill 562 bnez_a0 563 la_br &err_unknown_directive 564 b 565 :dir_check_8 566 li_t1 %8 %0 567 la_br &dir_check_7 568 bne_t0,t1 569 la_a0 &name_buf_ptr 570 ld_a0,a0,0 571 la_a1 &kw_endscope 572 li_a2 %8 %0 573 la_br &mem_eq 574 call 575 la_br &dir_call_endscope 576 bnez_a0 577 la_br &err_unknown_directive 578 b 579 :dir_check_7 580 li_t1 %7 %0 581 la_br &err_unknown_directive 582 bne_t0,t1 583 la_a0 &name_buf_ptr 584 ld_a0,a0,0 585 la_a1 &kw_ptrsize 586 li_a2 %7 %0 587 la_br &mem_eq 588 call 589 la_br &dir_call_ptrsize 590 bnez_a0 591 la_br &err_unknown_directive 592 b 593 594 :dir_call_align 595 la_br &do_align 596 call 597 la_br &scan_loop 598 b 599 :dir_call_fill 600 la_br &do_fill 601 call 602 la_br &scan_loop 603 b 604 :dir_call_scope 605 la_br &do_scope_open 606 call 607 la_br &scan_loop 608 b 609 :dir_call_endscope 610 la_br &do_scope_close 611 call 612 la_br &scan_loop 613 b 614 :dir_call_ptrsize 615 la_br &do_ptrsize 616 call 617 la_br &scan_loop 618 b 619 620 :handle_ref 621 # a0 holds the sigil byte; advance past it then process_reference. 622 la_a1 &cur_sigil 623 st_a0,a1,0 624 la_a0 &scan_pos 625 ld_t0,a0,0 626 addi_t0,t0,1 627 st_t0,a0,0 628 la_br &process_reference 629 call 630 la_br &scan_loop 631 b 632 633 :handle_byte_stream 634 la_br &parse_byte_stream 635 call 636 la_br &scan_loop 637 b 638 639 :scan_done 640 eret 641 642 ## --- Lex helpers ----------------------------------------------------------- 643 644 ## skip_ws_and_comments(): advance scan_pos past whitespace and #/; comments. 645 ## Updates cur_line on '\n'. 646 :skip_ws_and_comments 647 enter_0 648 :swc_loop 649 la_a0 &scan_pos 650 ld_t0,a0,0 651 la_a1 &scan_end 652 ld_t1,a1,0 653 la_br &swc_done 654 beq_t0,t1 655 la_br &swc_done 656 blt_t1,t0 657 lb_a0,t0,0 658 la_br &is_space_any 659 call 660 la_br &swc_after_ws_check 661 beqz_a0 662 # whitespace: bump cur_line on '\n', advance scan_pos. 663 la_a0 &scan_pos 664 ld_t0,a0,0 665 lb_a0,t0,0 666 li_t1 %10 %0 667 la_br &swc_advance 668 bne_a0,t1 669 la_a1 &cur_line 670 ld_t2,a1,0 671 addi_t2,t2,1 672 st_t2,a1,0 673 :swc_advance 674 la_a0 &scan_pos 675 ld_t0,a0,0 676 addi_t0,t0,1 677 st_t0,a0,0 678 la_br &swc_loop 679 b 680 :swc_after_ws_check 681 # is_space_any clobbered a0; re-read the byte at scan_pos. 682 la_a0 &scan_pos 683 ld_t0,a0,0 684 lb_a0,t0,0 685 li_t1 %35 %0 686 la_br &swc_consume_comment 687 beq_a0,t1 688 li_t1 %59 %0 689 la_br &swc_consume_comment 690 beq_a0,t1 691 la_br &swc_done 692 b 693 :swc_consume_comment 694 :swc_cc_loop 695 la_a0 &scan_pos 696 ld_t0,a0,0 697 la_a1 &scan_end 698 ld_t1,a1,0 699 la_br &swc_loop 700 beq_t0,t1 701 la_br &swc_loop 702 blt_t1,t0 703 lb_a0,t0,0 704 li_t1 %10 %0 705 la_br &swc_loop 706 beq_a0,t1 707 addi_t0,t0,1 708 la_a1 &scan_pos 709 st_t0,a1,0 710 la_br &swc_cc_loop 711 b 712 :swc_done 713 eret 714 715 ## skip_inline_ws(): like skip_ws_and_comments but does NOT cross '\n'. 716 :skip_inline_ws 717 enter_0 718 :siw_loop 719 la_a0 &scan_pos 720 ld_t0,a0,0 721 la_a1 &scan_end 722 ld_t1,a1,0 723 la_br &siw_done 724 beq_t0,t1 725 la_br &siw_done 726 blt_t1,t0 727 lb_a0,t0,0 728 li_t1 %32 %0 729 la_br &siw_advance 730 beq_a0,t1 731 li_t1 %9 %0 732 la_br &siw_advance 733 beq_a0,t1 734 li_t1 %13 %0 735 la_br &siw_advance 736 beq_a0,t1 737 li_t1 %12 %0 738 la_br &siw_advance 739 beq_a0,t1 740 li_t1 %11 %0 741 la_br &siw_advance 742 beq_a0,t1 743 li_t1 %35 %0 744 la_br &siw_consume_comment 745 beq_a0,t1 746 li_t1 %59 %0 747 la_br &siw_consume_comment 748 beq_a0,t1 749 la_br &siw_done 750 b 751 :siw_advance 752 la_a0 &scan_pos 753 ld_t0,a0,0 754 addi_t0,t0,1 755 st_t0,a0,0 756 la_br &siw_loop 757 b 758 :siw_consume_comment 759 :siw_cc_loop 760 la_a0 &scan_pos 761 ld_t0,a0,0 762 la_a1 &scan_end 763 ld_t1,a1,0 764 la_br &siw_done 765 beq_t0,t1 766 la_br &siw_done 767 blt_t1,t0 768 lb_a0,t0,0 769 li_t1 %10 %0 770 la_br &siw_done 771 beq_a0,t1 772 addi_t0,t0,1 773 la_a1 &scan_pos 774 st_t0,a1,0 775 la_br &siw_cc_loop 776 b 777 :siw_done 778 eret 779 780 ## is_space_any(a0=c) -> a0=0/1. Whitespace = ' ' \t \n \r \f \v. 781 :is_space_any 782 li_t0 %32 %0 783 la_br &isa_yes 784 beq_a0,t0 785 li_t0 %9 %0 786 la_br &isa_yes 787 beq_a0,t0 788 li_t0 %10 %0 789 la_br &isa_yes 790 beq_a0,t0 791 li_t0 %13 %0 792 la_br &isa_yes 793 beq_a0,t0 794 li_t0 %12 %0 795 la_br &isa_yes 796 beq_a0,t0 797 li_t0 %11 %0 798 la_br &isa_yes 799 beq_a0,t0 800 li_a0 %0 %0 801 ret 802 :isa_yes 803 li_a0 %1 %0 804 ret 805 806 ## is_name_terminator(a0=c) -> a0=0/1. Terminators: ws, '-', '>', '#', ';'. 807 ## Spills c into a BSS slot since is_space_any clobbers a0. 808 :is_name_terminator 809 enter_0 810 la_a1 &nt_c 811 st_a0,a1,0 812 la_br &is_space_any 813 call 814 la_br &nt_yes 815 bnez_a0 816 la_a0 &nt_c 817 ld_a0,a0,0 818 li_t0 %45 %0 819 la_br &nt_yes 820 beq_a0,t0 821 li_t0 %62 %0 822 la_br &nt_yes 823 beq_a0,t0 824 li_t0 %35 %0 825 la_br &nt_yes 826 beq_a0,t0 827 li_t0 %59 %0 828 la_br &nt_yes 829 beq_a0,t0 830 li_a0 %0 %0 831 eret 832 :nt_yes 833 li_a0 %1 %0 834 eret 835 836 ## is_byte_digit(a0=c) -> a0=0/1. Mode-aware (HEX vs BINARY). 837 :is_byte_digit 838 la_a1 &byte_mode 839 ld_t0,a1,0 840 la_br &ibd_bin 841 bnez_t0 842 # HEX: 0-9, a-f, A-F 843 li_t1 %48 %0 844 la_br &ibd_no 845 blt_a0,t1 846 li_t1 %57 %0 847 la_br &ibd_yes 848 blt_a0,t1 849 la_br &ibd_yes 850 beq_a0,t1 851 li_t1 %65 %0 852 la_br &ibd_no 853 blt_a0,t1 854 li_t1 %70 %0 855 la_br &ibd_yes 856 blt_a0,t1 857 la_br &ibd_yes 858 beq_a0,t1 859 li_t1 %97 %0 860 la_br &ibd_no 861 blt_a0,t1 862 li_t1 %102 %0 863 la_br &ibd_yes 864 blt_a0,t1 865 la_br &ibd_yes 866 beq_a0,t1 867 la_br &ibd_no 868 b 869 :ibd_bin 870 li_t1 %48 %0 871 la_br &ibd_yes 872 beq_a0,t1 873 li_t1 %49 %0 874 la_br &ibd_yes 875 beq_a0,t1 876 la_br &ibd_no 877 b 878 :ibd_yes 879 li_a0 %1 %0 880 ret 881 :ibd_no 882 li_a0 %0 %0 883 ret 884 885 ## byte_digit_value(a0=c) -> a0=value (0..15). Caller guarantees c is a 886 ## valid digit for the current byte mode. 887 :byte_digit_value 888 li_t0 %57 %0 889 la_br &bdv_alpha 890 blt_t0,a0 891 li_t1 %48 %0 892 sub_a0,a0,t1 893 ret 894 :bdv_alpha 895 li_t0 %96 %0 896 la_br &bdv_lower 897 blt_t0,a0 898 li_t1 %55 %0 899 sub_a0,a0,t1 900 ret 901 :bdv_lower 902 li_t1 %87 %0 903 sub_a0,a0,t1 904 ret 905 906 ## byte_digit_count() -> a0. 2 for HEX, 8 for BINARY. 907 :byte_digit_count 908 la_a0 &byte_mode 909 ld_t0,a0,0 910 la_br &bdc_bin 911 bnez_t0 912 li_a0 %2 %0 913 ret 914 :bdc_bin 915 li_a0 %8 %0 916 ret 917 918 ## scan_name() -> a0=length, sn_start=pointer into input buffer at name start. 919 ## Advances scan_pos past the name. Fatal on empty. 920 :scan_name 921 enter_0 922 la_a0 &scan_pos 923 ld_t0,a0,0 924 la_a1 &sn_start 925 st_t0,a1,0 926 :sn_loop 927 la_a0 &scan_pos 928 ld_t0,a0,0 929 la_a1 &scan_end 930 ld_t1,a1,0 931 la_br &sn_done 932 beq_t0,t1 933 la_br &sn_done 934 blt_t1,t0 935 lb_a0,t0,0 936 la_br &is_name_terminator 937 call 938 la_br &sn_done 939 bnez_a0 940 la_a0 &scan_pos 941 ld_t0,a0,0 942 addi_t0,t0,1 943 st_t0,a0,0 944 la_br &sn_loop 945 b 946 :sn_done 947 la_a0 &scan_pos 948 ld_t0,a0,0 949 la_a1 &sn_start 950 ld_t1,a1,0 951 sub_a0,t0,t1 952 la_br &err_empty_name 953 beqz_a0 954 eret 955 956 ## read_name(a0=out_buf, a1=max) -> a0=length. Reads scan_pos into out_buf 957 ## until is_name_terminator or scan_end. Fatal on overflow / empty. 958 ## (Kept for reference; superseded by scan_name in single-pass refactor.) 959 :read_name 960 enter_0 961 la_a2 &rn_out 962 st_a0,a2,0 963 la_a2 &rn_max 964 st_a1,a2,0 965 li_t0 %0 %0 966 la_a2 &rn_n 967 st_t0,a2,0 968 :rn_loop 969 la_a0 &scan_pos 970 ld_t0,a0,0 971 la_a1 &scan_end 972 ld_t1,a1,0 973 la_br &rn_done 974 beq_t0,t1 975 la_br &rn_done 976 blt_t1,t0 977 lb_a0,t0,0 978 la_br &is_name_terminator 979 call 980 la_br &rn_done 981 bnez_a0 982 la_a1 &rn_n 983 ld_t0,a1,0 984 la_a0 &rn_max 985 ld_t1,a0,0 986 la_br &err_name_too_long 987 beq_t0,t1 988 # store char 989 la_a0 &scan_pos 990 ld_a0,a0,0 991 lb_a3,a0,0 992 la_a1 &rn_out 993 ld_a1,a1,0 994 add_a1,a1,t0 995 sb_a3,a1,0 996 addi_t0,t0,1 997 la_a1 &rn_n 998 st_t0,a1,0 999 la_a0 &scan_pos 1000 ld_t0,a0,0 1001 addi_t0,t0,1 1002 st_t0,a0,0 1003 la_br &rn_loop 1004 b 1005 :rn_done 1006 la_a1 &rn_n 1007 ld_a0,a1,0 1008 la_br &err_empty_name 1009 beqz_a0 1010 eret 1011 1012 ## read_directive_name(a0=out_buf, a1=max) -> a0=length. Like read_name but 1013 ## terminates on first non-alpha byte. 1014 :read_directive_name 1015 enter_0 1016 la_a2 &rn_out 1017 st_a0,a2,0 1018 la_a2 &rn_max 1019 st_a1,a2,0 1020 li_t0 %0 %0 1021 la_a2 &rn_n 1022 st_t0,a2,0 1023 :rdn_loop 1024 la_a0 &scan_pos 1025 ld_t0,a0,0 1026 la_a1 &scan_end 1027 ld_t1,a1,0 1028 la_br &rdn_done 1029 beq_t0,t1 1030 la_br &rdn_done 1031 blt_t1,t0 1032 lb_a0,t0,0 1033 # accept [A-Za-z] 1034 li_t1 %65 %0 1035 la_br &rdn_check_lower 1036 blt_a0,t1 1037 li_t1 %90 %0 1038 la_br &rdn_consume 1039 blt_a0,t1 1040 la_br &rdn_consume 1041 beq_a0,t1 1042 :rdn_check_lower 1043 li_t1 %97 %0 1044 la_br &rdn_done 1045 blt_a0,t1 1046 li_t1 %122 %0 1047 la_br &rdn_consume 1048 blt_a0,t1 1049 la_br &rdn_consume 1050 beq_a0,t1 1051 la_br &rdn_done 1052 b 1053 :rdn_consume 1054 la_a1 &rn_n 1055 ld_t0,a1,0 1056 la_a2 &rn_max 1057 ld_t1,a2,0 1058 la_br &err_name_too_long 1059 beq_t0,t1 1060 la_a2 &rn_out 1061 ld_a2,a2,0 1062 add_a2,a2,t0 1063 sb_a0,a2,0 1064 addi_t0,t0,1 1065 la_a1 &rn_n 1066 st_t0,a1,0 1067 la_a0 &scan_pos 1068 ld_t0,a0,0 1069 addi_t0,t0,1 1070 st_t0,a0,0 1071 la_br &rdn_loop 1072 b 1073 :rdn_done 1074 la_a1 &rn_n 1075 ld_a0,a1,0 1076 la_br &err_empty_directive 1077 beqz_a0 1078 eret 1079 1080 ## read_decimal() -> a0=value. Fatal on no digits. 1081 :read_decimal 1082 enter_0 1083 li_t0 %0 %0 1084 la_a0 &rd_val 1085 st_t0,a0,0 1086 la_a0 &rd_saw 1087 st_t0,a0,0 1088 :rd_loop 1089 la_a0 &scan_pos 1090 ld_t0,a0,0 1091 la_a1 &scan_end 1092 ld_t1,a1,0 1093 la_br &rd_done 1094 beq_t0,t1 1095 la_br &rd_done 1096 blt_t1,t0 1097 lb_a0,t0,0 1098 li_t1 %48 %0 1099 la_br &rd_done 1100 blt_a0,t1 1101 li_t1 %57 %0 1102 la_br &rd_done 1103 blt_t1,a0 1104 # acc = acc * 10 + (c - '0') 1105 la_a1 &rd_val 1106 ld_a2,a1,0 1107 li_t1 %10 %0 1108 mul_a2,a2,t1 1109 li_t1 %48 %0 1110 sub_a0,a0,t1 1111 add_a2,a2,a0 1112 st_a2,a1,0 1113 li_t0 %1 %0 1114 la_a1 &rd_saw 1115 st_t0,a1,0 1116 la_a0 &scan_pos 1117 ld_t0,a0,0 1118 addi_t0,t0,1 1119 st_t0,a0,0 1120 la_br &rd_loop 1121 b 1122 :rd_done 1123 la_a1 &rd_saw 1124 ld_t0,a1,0 1125 la_br &err_expected_decimal 1126 beqz_t0 1127 la_a1 &rd_val 1128 ld_a0,a1,0 1129 eret 1130 1131 ## --- Byte stream / single byte literal ------------------------------------- 1132 1133 ## parse_byte_stream(): consume free-flowing digits (intermixed with ws and 1134 ## #/; comments) and emit_byte them. Stops at first non-digit non-ws 1135 ## non-comment byte. 1136 :parse_byte_stream 1137 enter_0 1138 li_t0 %0 %0 1139 la_a0 &pbs_acc 1140 st_t0,a0,0 1141 la_a0 &pbs_have 1142 st_t0,a0,0 1143 :pbs_loop 1144 la_a0 &scan_pos 1145 ld_t0,a0,0 1146 la_a1 &scan_end 1147 ld_t1,a1,0 1148 la_br &pbs_done 1149 beq_t0,t1 1150 la_br &pbs_done 1151 blt_t1,t0 1152 lb_a0,t0,0 1153 la_br &is_space_any 1154 call 1155 la_br &pbs_consume_ws 1156 bnez_a0 1157 la_a0 &scan_pos 1158 ld_t0,a0,0 1159 lb_a0,t0,0 1160 li_t1 %35 %0 1161 la_br &pbs_consume_comment 1162 beq_a0,t1 1163 li_t1 %59 %0 1164 la_br &pbs_consume_comment 1165 beq_a0,t1 1166 la_br &is_byte_digit 1167 call 1168 la_br &pbs_done 1169 beqz_a0 1170 # consume one digit 1171 la_a0 &scan_pos 1172 ld_t0,a0,0 1173 lb_a0,t0,0 1174 addi_t0,t0,1 1175 la_a1 &scan_pos 1176 st_t0,a1,0 1177 la_a1 &pbs_c 1178 st_a0,a1,0 1179 # acc = (acc << shift) | digit 1180 la_a1 &byte_mode 1181 ld_t1,a1,0 1182 la_br &pbs_bin 1183 bnez_t1 1184 # HEX: shift 4 + digit_value 1185 la_a1 &pbs_acc 1186 ld_t0,a1,0 1187 shli_a3,t0,4 1188 la_a1 &pbs_c 1189 ld_a0,a1,0 1190 la_br &byte_digit_value 1191 call 1192 add_a3,a3,a0 1193 la_a1 &pbs_acc 1194 st_a3,a1,0 1195 la_br &pbs_bump 1196 b 1197 :pbs_bin 1198 la_a1 &pbs_acc 1199 ld_t0,a1,0 1200 shli_a3,t0,1 1201 la_a1 &pbs_c 1202 ld_a0,a1,0 1203 li_t1 %48 %0 1204 sub_a0,a0,t1 1205 add_a3,a3,a0 1206 la_a1 &pbs_acc 1207 st_a3,a1,0 1208 :pbs_bump 1209 la_a0 &pbs_have 1210 ld_t0,a0,0 1211 addi_t0,t0,1 1212 st_t0,a0,0 1213 la_br &byte_digit_count 1214 call 1215 la_a1 &pbs_have 1216 ld_t0,a1,0 1217 la_br &pbs_loop 1218 bne_t0,a0 1219 # full byte: emit 1220 la_a1 &pbs_acc 1221 ld_a0,a1,0 1222 andi_a0,a0,255 1223 la_br &emit_byte 1224 call 1225 li_t0 %0 %0 1226 la_a0 &pbs_acc 1227 st_t0,a0,0 1228 la_a0 &pbs_have 1229 st_t0,a0,0 1230 la_br &pbs_loop 1231 b 1232 :pbs_consume_ws 1233 la_a0 &scan_pos 1234 ld_t0,a0,0 1235 lb_a0,t0,0 1236 li_t1 %10 %0 1237 la_br &pbs_ws_advance 1238 bne_a0,t1 1239 la_a1 &cur_line 1240 ld_t2,a1,0 1241 addi_t2,t2,1 1242 st_t2,a1,0 1243 :pbs_ws_advance 1244 la_a0 &scan_pos 1245 ld_t0,a0,0 1246 addi_t0,t0,1 1247 st_t0,a0,0 1248 la_br &pbs_loop 1249 b 1250 :pbs_consume_comment 1251 :pbs_cc_loop 1252 la_a0 &scan_pos 1253 ld_t0,a0,0 1254 la_a1 &scan_end 1255 ld_t1,a1,0 1256 la_br &pbs_loop 1257 beq_t0,t1 1258 la_br &pbs_loop 1259 blt_t1,t0 1260 lb_a0,t0,0 1261 li_t1 %10 %0 1262 la_br &pbs_loop 1263 beq_a0,t1 1264 addi_t0,t0,1 1265 la_a1 &scan_pos 1266 st_t0,a1,0 1267 la_br &pbs_cc_loop 1268 b 1269 :pbs_done 1270 la_a0 &pbs_have 1271 ld_t0,a0,0 1272 la_br &err_byte_stream_short 1273 bnez_t0 1274 eret 1275 1276 ## parse_one_byte(a0=out_addr): read a single byte literal (exactly 1277 ## byte_digit_count contiguous digits, no internal whitespace). 1278 :parse_one_byte 1279 enter_0 1280 la_a1 &p1b_out 1281 st_a0,a1,0 1282 li_t0 %0 %0 1283 la_a1 &p1b_acc 1284 st_t0,a1,0 1285 la_a1 &p1b_have 1286 st_t0,a1,0 1287 :p1b_loop 1288 la_a0 &scan_pos 1289 ld_t0,a0,0 1290 la_a1 &scan_end 1291 ld_t1,a1,0 1292 la_br &p1b_done 1293 beq_t0,t1 1294 la_br &p1b_done 1295 blt_t1,t0 1296 lb_a0,t0,0 1297 la_br &is_byte_digit 1298 call 1299 la_br &p1b_done 1300 beqz_a0 1301 la_a0 &scan_pos 1302 ld_t0,a0,0 1303 lb_a0,t0,0 1304 addi_t0,t0,1 1305 la_a1 &scan_pos 1306 st_t0,a1,0 1307 la_a1 &p1b_c 1308 st_a0,a1,0 1309 la_a1 &byte_mode 1310 ld_t1,a1,0 1311 la_br &p1b_bin 1312 bnez_t1 1313 la_a1 &p1b_acc 1314 ld_t0,a1,0 1315 shli_a3,t0,4 1316 la_a1 &p1b_c 1317 ld_a0,a1,0 1318 la_br &byte_digit_value 1319 call 1320 add_a3,a3,a0 1321 la_a1 &p1b_acc 1322 st_a3,a1,0 1323 la_br &p1b_bump 1324 b 1325 :p1b_bin 1326 la_a1 &p1b_acc 1327 ld_t0,a1,0 1328 shli_a3,t0,1 1329 la_a1 &p1b_c 1330 ld_a0,a1,0 1331 li_t1 %48 %0 1332 sub_a0,a0,t1 1333 add_a3,a3,a0 1334 la_a1 &p1b_acc 1335 st_a3,a1,0 1336 :p1b_bump 1337 la_a0 &p1b_have 1338 ld_t0,a0,0 1339 addi_t0,t0,1 1340 st_t0,a0,0 1341 la_br &byte_digit_count 1342 call 1343 la_a1 &p1b_have 1344 ld_t0,a1,0 1345 la_br &p1b_loop 1346 bne_t0,a0 1347 # got full byte: write to *out_addr and return 1348 la_a1 &p1b_acc 1349 ld_a0,a1,0 1350 andi_a0,a0,255 1351 la_a1 &p1b_out 1352 ld_a1,a1,0 1353 sb_a0,a1,0 1354 eret 1355 :p1b_done 1356 la_a0 &p1b_have 1357 ld_t0,a0,0 1358 la_br &err_byte_lit_bad 1359 bnez_t0 1360 la_br &err_byte_lit_bad 1361 b 1362 1363 ## --- Label table ----------------------------------------------------------- 1364 1365 ## intern(a0=src, a1=len) -> a0=offset into text_buf. Copies bytes plus a 1366 ## NUL terminator. 1367 :intern 1368 enter_0 1369 la_a2 &intern_src 1370 st_a0,a2,0 1371 la_a2 &intern_len 1372 st_a1,a2,0 1373 la_a2 &text_used 1374 ld_a3,a2,0 1375 la_a2 &intern_orig 1376 st_a3,a2,0 1377 # if (text_used + len + 1 > TEXT_CAP) fatal 1378 add_a2,a3,a1 1379 addi_a2,a2,1 1380 li_t0 H2_TEXT_CAP 1381 la_br &err_text_overflow 1382 blt_t0,a2 1383 # dst = text_buf + text_used 1384 la_a0 &text_buf_ptr 1385 ld_a0,a0,0 1386 add_a0,a0,a3 1387 la_a2 &intern_dst 1388 st_a0,a2,0 1389 li_t0 %0 %0 1390 la_a1 &intern_i 1391 st_t0,a1,0 1392 :intern_copy_loop 1393 la_a0 &intern_i 1394 ld_t0,a0,0 1395 la_a1 &intern_len 1396 ld_t1,a1,0 1397 la_br &intern_copy_done 1398 beq_t0,t1 1399 la_a0 &intern_src 1400 ld_a0,a0,0 1401 add_a0,a0,t0 1402 lb_a0,a0,0 1403 la_a2 &intern_dst 1404 ld_a2,a2,0 1405 add_a2,a2,t0 1406 sb_a0,a2,0 1407 addi_t0,t0,1 1408 la_a1 &intern_i 1409 st_t0,a1,0 1410 la_br &intern_copy_loop 1411 b 1412 :intern_copy_done 1413 # NUL terminator 1414 la_a2 &intern_dst 1415 ld_a2,a2,0 1416 la_a1 &intern_len 1417 ld_t0,a1,0 1418 add_a2,a2,t0 1419 li_t1 %0 %0 1420 sb_t1,a2,0 1421 # text_used += len + 1 1422 la_a2 &text_used 1423 ld_a3,a2,0 1424 la_a1 &intern_len 1425 ld_a1,a1,0 1426 add_a3,a3,a1 1427 addi_a3,a3,1 1428 st_a3,a2,0 1429 la_a0 &intern_orig 1430 ld_a0,a0,0 1431 eret 1432 1433 ## label_addr(a0=index) -> a0 = &labels[index]. Each label is 32 B. 1434 :label_addr 1435 li_t0 %32 %0 1436 mul_a0,a0,t0 1437 la_a1 &labels_ptr 1438 ld_a1,a1,0 1439 add_a0,a0,a1 1440 ret 1441 1442 ## name_eq(a0=label_ptr, a1=src, a2=len) -> a0=0/1. 1443 :name_eq 1444 enter_0 1445 la_a3 &ne_label 1446 st_a0,a3,0 1447 la_a3 &ne_src 1448 st_a1,a3,0 1449 la_a3 &ne_len 1450 st_a2,a3,0 1451 # if (label->name_len != len) return 0 1452 ld_t0,a0,8 1453 la_br &ne_no 1454 bne_t0,a2 1455 # bytes equal? 1456 la_a0 &ne_label 1457 ld_a0,a0,0 1458 ld_a3,a0,0 1459 la_a0 &text_buf_ptr 1460 ld_a0,a0,0 1461 add_a0,a0,a3 1462 la_a1 &ne_src 1463 ld_a1,a1,0 1464 la_a2 &ne_len 1465 ld_a2,a2,0 1466 la_br &mem_eq 1467 call 1468 eret 1469 :ne_no 1470 li_a0 %0 %0 1471 eret 1472 1473 ## define_label(a0=src, a1=len, a2=scope_id). First definition wins. 1474 :define_label 1475 enter_0 1476 la_a3 &dl_src 1477 st_a0,a3,0 1478 la_a3 &dl_len 1479 st_a1,a3,0 1480 la_a3 &dl_scope 1481 st_a2,a3,0 1482 la_a0 &label_count 1483 ld_t0,a0,0 1484 li_t1 H2_LABEL_CAP 1485 la_br &err_too_many_labels 1486 beq_t0,t1 1487 la_br &err_too_many_labels 1488 blt_t1,t0 1489 # name_off = intern(src, len) 1490 la_a0 &dl_src 1491 ld_a0,a0,0 1492 la_a1 &dl_len 1493 ld_a1,a1,0 1494 la_br &intern 1495 call 1496 la_a3 &dl_name_off 1497 st_a0,a3,0 1498 # &labels[label_count] 1499 la_a0 &label_count 1500 ld_a0,a0,0 1501 la_br &label_addr 1502 call 1503 la_a3 &dl_label 1504 st_a0,a3,0 1505 # name_off 1506 la_a1 &dl_name_off 1507 ld_t0,a1,0 1508 st_t0,a0,0 1509 # name_len 1510 la_a1 &dl_len 1511 ld_t0,a1,0 1512 st_t0,a0,8 1513 # target_ip 1514 la_a1 &ip 1515 ld_t0,a1,0 1516 st_t0,a0,16 1517 # scope_id 1518 la_a1 &dl_scope 1519 ld_t0,a1,0 1520 st_t0,a0,24 1521 # label_count++ 1522 la_a0 &label_count 1523 ld_t0,a0,0 1524 addi_t0,t0,1 1525 st_t0,a0,0 1526 eret 1527 1528 ## lookup_label_in(a0=src, a1=len, a2=stack_ptr, a3=depth) -> a0=target_ip. 1529 :lookup_label_in 1530 enter_0 1531 la_t1 &ll_src 1532 st_a0,t1,0 1533 la_t1 &ll_len 1534 st_a1,t1,0 1535 la_t1 &ll_stack 1536 st_a2,t1,0 1537 la_t1 &ll_depth 1538 st_a3,t1,0 1539 # dotted? (first byte == '.' AND depth > 0) 1540 lb_t0,a0,0 1541 li_t1 %46 %0 1542 la_br &ll_undotted 1543 bne_t0,t1 1544 la_br &ll_undotted 1545 beqz_a3 1546 addi_t0,a3,neg1 1547 la_a1 &ll_d 1548 st_t0,a1,0 1549 :ll_dot_outer 1550 la_a0 &ll_d 1551 ld_t0,a0,0 1552 la_br &err_undefined_local 1553 bltz_t0 1554 la_a1 &ll_stack 1555 ld_a1,a1,0 1556 shli_t2,t0,3 1557 add_a1,a1,t2 1558 ld_t1,a1,0 1559 la_a0 &ll_sid 1560 st_t1,a0,0 1561 li_t0 %0 %0 1562 la_a0 &ll_i 1563 st_t0,a0,0 1564 :ll_dot_inner 1565 la_a0 &ll_i 1566 ld_t0,a0,0 1567 la_a1 &label_count 1568 ld_t1,a1,0 1569 la_br &ll_dot_next_d 1570 beq_t0,t1 1571 mov_a0,t0 1572 la_br &label_addr 1573 call 1574 la_a3 &ll_label 1575 st_a0,a3,0 1576 ld_t0,a0,24 1577 la_a1 &ll_sid 1578 ld_t1,a1,0 1579 la_br &ll_dot_inner_next 1580 bne_t0,t1 1581 la_a0 &ll_label 1582 ld_a0,a0,0 1583 la_a1 &ll_src 1584 ld_a1,a1,0 1585 la_a2 &ll_len 1586 ld_a2,a2,0 1587 la_br &name_eq 1588 call 1589 la_br &ll_dot_inner_next 1590 beqz_a0 1591 la_a0 &ll_label 1592 ld_a0,a0,0 1593 ld_a0,a0,16 1594 eret 1595 :ll_dot_inner_next 1596 la_a0 &ll_i 1597 ld_t0,a0,0 1598 addi_t0,t0,1 1599 st_t0,a0,0 1600 la_br &ll_dot_inner 1601 b 1602 :ll_dot_next_d 1603 la_a0 &ll_d 1604 ld_t0,a0,0 1605 addi_t0,t0,neg1 1606 st_t0,a0,0 1607 la_br &ll_dot_outer 1608 b 1609 1610 :ll_undotted 1611 li_t0 %0 %0 1612 la_a0 &ll_i 1613 st_t0,a0,0 1614 :ll_undotted_loop 1615 la_a0 &ll_i 1616 ld_t0,a0,0 1617 la_a1 &label_count 1618 ld_t1,a1,0 1619 la_br &err_undefined_label 1620 beq_t0,t1 1621 mov_a0,t0 1622 la_br &label_addr 1623 call 1624 la_a3 &ll_label 1625 st_a0,a3,0 1626 ld_t0,a0,24 1627 la_br &ll_undotted_next 1628 bnez_t0 1629 la_a0 &ll_label 1630 ld_a0,a0,0 1631 la_a1 &ll_src 1632 ld_a1,a1,0 1633 la_a2 &ll_len 1634 ld_a2,a2,0 1635 la_br &name_eq 1636 call 1637 la_br &ll_undotted_next 1638 beqz_a0 1639 la_a0 &ll_label 1640 ld_a0,a0,0 1641 ld_a0,a0,16 1642 eret 1643 :ll_undotted_next 1644 la_a0 &ll_i 1645 ld_t0,a0,0 1646 addi_t0,t0,1 1647 st_t0,a0,0 1648 la_br &ll_undotted_loop 1649 b 1650 1651 ## --- Reference processor --------------------------------------------------- 1652 ## process_reference(): cur_sigil already set; scan_pos already past sigil. 1653 ## Captures label name span (and optional -OTHER), reserves placeholder bytes, 1654 ## and appends a Fixup record. Resolution happens later in patch_fixups. 1655 :process_reference 1656 enter_0 1657 la_br &set_sigil_info 1658 call 1659 # require non-terminator (label name follows) 1660 la_a0 &scan_pos 1661 ld_t0,a0,0 1662 la_a1 &scan_end 1663 ld_t1,a1,0 1664 la_br &err_sigil_no_label 1665 beq_t0,t1 1666 la_br &err_sigil_no_label 1667 blt_t1,t0 1668 lb_a0,t0,0 1669 la_br &is_name_terminator 1670 call 1671 la_br &err_sigil_no_label 1672 bnez_a0 1673 # scan_name -> length in a0, pointer in sn_start (no copy). 1674 la_br &scan_name 1675 call 1676 la_a1 &pref_name_len 1677 st_a0,a1,0 1678 la_a0 &sn_start 1679 ld_t0,a0,0 1680 la_a1 &pref_name 1681 st_t0,a1,0 1682 # default: other = NULL, other_len = 0 1683 li_t0 %0 %0 1684 la_a1 &pref_other 1685 st_t0,a1,0 1686 la_a1 &pref_other_len 1687 st_t0,a1,0 1688 # optional '-' or '>' separator (tight, no whitespace) 1689 la_a0 &scan_pos 1690 ld_t0,a0,0 1691 la_a1 &scan_end 1692 ld_t1,a1,0 1693 la_br &pref_after_other 1694 beq_t0,t1 1695 la_br &pref_after_other 1696 blt_t1,t0 1697 lb_a0,t0,0 1698 li_t1 %45 %0 1699 la_br &pref_consume_sep 1700 beq_a0,t1 1701 li_t1 %62 %0 1702 la_br &pref_consume_sep 1703 beq_a0,t1 1704 la_br &pref_after_other 1705 b 1706 :pref_consume_sep 1707 la_a0 &scan_pos 1708 ld_t0,a0,0 1709 addi_t0,t0,1 1710 st_t0,a0,0 1711 la_a1 &scan_end 1712 ld_t1,a1,0 1713 la_br &err_minus_no_label 1714 beq_t0,t1 1715 la_br &err_minus_no_label 1716 blt_t1,t0 1717 lb_a0,t0,0 1718 la_br &is_name_terminator 1719 call 1720 la_br &err_minus_no_label 1721 bnez_a0 1722 la_br &scan_name 1723 call 1724 la_a1 &pref_other_len 1725 st_a0,a1,0 1726 la_a0 &sn_start 1727 ld_t0,a0,0 1728 la_a1 &pref_other 1729 st_t0,a1,0 1730 :pref_after_other 1731 # Reserve placeholder bytes; emit_zeros returns starting offset. 1732 la_a0 &pr_width 1733 ld_a0,a0,0 1734 la_br &emit_zeros 1735 call 1736 la_a1 &rf_out_off 1737 st_a0,a1,0 1738 # ip_after = ip (already advanced by emit_zeros). 1739 la_a0 &ip 1740 ld_t0,a0,0 1741 la_a1 &rf_ip_after 1742 st_t0,a1,0 1743 la_br &record_fixup 1744 call 1745 eret 1746 1747 ## record_fixup(): pref_name/pref_name_len/pref_other/pref_other_len already set 1748 ## by caller. rf_out_off and rf_ip_after also set. Snapshots cur_sigil/cur_path/ 1749 ## cur_line and the current scope stack (if depth > 0). 1750 :record_fixup 1751 enter_0 1752 la_a0 &fixup_count 1753 ld_t0,a0,0 1754 li_t1 H2_FIXUP_CAP 1755 la_br &err_too_many_fixups 1756 beq_t0,t1 1757 la_br &err_too_many_fixups 1758 blt_t1,t0 1759 # fp = fixups_ptr + count * 96 1760 li_t1 %96 %0 1761 mul_a1,t0,t1 1762 la_a2 &fixups_ptr 1763 ld_a2,a2,0 1764 add_a1,a1,a2 1765 la_a3 &rf_fp 1766 st_a1,a3,0 1767 # offset 0: out_off 1768 la_a0 &rf_out_off 1769 ld_t0,a0,0 1770 st_t0,a1,0 1771 # offset 8: ip_at_ref 1772 la_a0 &rf_ip_after 1773 ld_t0,a0,0 1774 st_t0,a1,8 1775 # offset 16: name 1776 la_a0 &pref_name 1777 ld_t0,a0,0 1778 st_t0,a1,16 1779 # offset 24: other (0 if none) 1780 la_a0 &pref_other 1781 ld_t0,a0,0 1782 st_t0,a1,24 1783 # offset 32: src_path = cur_path 1784 la_a0 &cur_path 1785 ld_t0,a0,0 1786 st_t0,a1,32 1787 # offset 40: name_len 1788 la_a0 &pref_name_len 1789 ld_t0,a0,0 1790 st_t0,a1,40 1791 # offset 48: other_len 1792 la_a0 &pref_other_len 1793 ld_t0,a0,0 1794 st_t0,a1,48 1795 # offset 56: scope_hist_off (filled below if depth > 0) 1796 li_t0 %0 %0 1797 st_t0,a1,56 1798 # offset 64: scope_depth (snapshot) 1799 la_a0 &scope_depth 1800 ld_t0,a0,0 1801 st_t0,a1,64 1802 # offset 72: src_line = cur_line (offset > 64: indirect via a3) 1803 la_a0 &cur_line 1804 ld_t0,a0,0 1805 li_t1 %72 %0 1806 add_a3,a1,t1 1807 st_t0,a3,0 1808 # offset 80: sigil 1809 la_a0 &cur_sigil 1810 ld_t0,a0,0 1811 li_t1 %80 %0 1812 add_a3,a1,t1 1813 st_t0,a3,0 1814 # If depth > 0, snapshot scope_stack into scope_history. 1815 la_a0 &scope_depth 1816 ld_t0,a0,0 1817 la_br &rf_no_scope 1818 beqz_t0 1819 la_a1 &scope_history_used 1820 ld_t1,a1,0 1821 add_t2,t1,t0 1822 li_a3 H2_SCOPE_HISTORY_CAP 1823 la_br &err_scope_history_overflow 1824 blt_a3,t2 1825 # Set scope_hist_off (offset 56) on the fixup. 1826 la_a0 &rf_fp 1827 ld_a0,a0,0 1828 st_t1,a0,56 1829 li_t2 %0 %0 1830 la_a0 &rf_i 1831 st_t2,a0,0 1832 :rf_copy_loop 1833 la_a0 &rf_i 1834 ld_t0,a0,0 1835 la_a1 &scope_depth 1836 ld_t1,a1,0 1837 la_br &rf_copy_done 1838 beq_t0,t1 1839 # src = scope_stack_ptr + i*8 1840 la_a1 &scope_stack_ptr 1841 ld_a1,a1,0 1842 shli_t2,t0,3 1843 add_a1,a1,t2 1844 ld_a3,a1,0 1845 # dst = scope_history_ptr + (scope_history_used + i)*8 1846 la_a2 &scope_history_used 1847 ld_a2,a2,0 1848 add_a2,a2,t0 1849 shli_a2,a2,3 1850 la_a1 &scope_history_ptr 1851 ld_a1,a1,0 1852 add_a1,a1,a2 1853 st_a3,a1,0 1854 addi_t0,t0,1 1855 la_a0 &rf_i 1856 st_t0,a0,0 1857 la_br &rf_copy_loop 1858 b 1859 :rf_copy_done 1860 la_a1 &scope_history_used 1861 ld_t0,a1,0 1862 la_a2 &scope_depth 1863 ld_t1,a2,0 1864 add_t0,t0,t1 1865 st_t0,a1,0 1866 :rf_no_scope 1867 la_a0 &fixup_count 1868 ld_t0,a0,0 1869 addi_t0,t0,1 1870 st_t0,a0,0 1871 eret 1872 1873 ## set_sigil_info(): reads cur_sigil; populates pr_width / pr_is_rel / 1874 ## pr_lo / pr_hi / pr_range_check. 1875 :set_sigil_info 1876 enter_0 1877 la_a0 &cur_sigil 1878 ld_a0,a0,0 1879 li_t0 %33 %0 1880 la_br &ssi_bang 1881 beq_a0,t0 1882 li_t0 %64 %0 1883 la_br &ssi_at 1884 beq_a0,t0 1885 li_t0 %36 %0 1886 la_br &ssi_dollar 1887 beq_a0,t0 1888 li_t0 %126 %0 1889 la_br &ssi_tilde 1890 beq_a0,t0 1891 li_t0 %37 %0 1892 la_br &ssi_pct 1893 beq_a0,t0 1894 li_t0 %38 %0 1895 la_br &ssi_amp 1896 beq_a0,t0 1897 la_br &err_bad_sigil 1898 b 1899 :ssi_bang 1900 li_t0 %1 %0 1901 la_a1 &pr_width 1902 st_t0,a1,0 1903 la_a1 &pr_is_rel 1904 st_t0,a1,0 1905 la_a1 &pr_range_check 1906 st_t0,a1,0 1907 li_t0 %128 %0 1908 li_t1 %0 %0 1909 sub_t0,t1,t0 1910 la_a1 &pr_lo 1911 st_t0,a1,0 1912 li_t0 %127 %0 1913 la_a1 &pr_hi 1914 st_t0,a1,0 1915 eret 1916 :ssi_at 1917 li_t0 %2 %0 1918 la_a1 &pr_width 1919 st_t0,a1,0 1920 li_t0 %1 %0 1921 la_a1 &pr_is_rel 1922 st_t0,a1,0 1923 la_a1 &pr_range_check 1924 st_t0,a1,0 1925 # 32768 = 256 * 128 1926 li_t0 %256 %0 1927 li_t1 %128 %0 1928 mul_t0,t0,t1 1929 li_t1 %0 %0 1930 sub_t1,t1,t0 1931 la_a1 &pr_lo 1932 st_t1,a1,0 1933 addi_t0,t0,neg1 1934 la_a1 &pr_hi 1935 st_t0,a1,0 1936 eret 1937 :ssi_dollar 1938 li_t0 %2 %0 1939 la_a1 &pr_width 1940 st_t0,a1,0 1941 li_t0 %0 %0 1942 la_a1 &pr_is_rel 1943 st_t0,a1,0 1944 li_t0 %1 %0 1945 la_a1 &pr_range_check 1946 st_t0,a1,0 1947 li_t0 %0 %0 1948 la_a1 &pr_lo 1949 st_t0,a1,0 1950 # 65536 = 256 * 256 1951 li_t0 %256 %0 1952 mov_t1,t0 1953 mul_t0,t0,t1 1954 addi_t0,t0,neg1 1955 la_a1 &pr_hi 1956 st_t0,a1,0 1957 eret 1958 :ssi_tilde 1959 li_t0 %3 %0 1960 la_a1 &pr_width 1961 st_t0,a1,0 1962 li_t0 %1 %0 1963 la_a1 &pr_is_rel 1964 st_t0,a1,0 1965 la_a1 &pr_range_check 1966 st_t0,a1,0 1967 # 8388608 = 256 * 256 * 128 1968 li_t0 %256 %0 1969 mov_t1,t0 1970 mul_t0,t0,t1 1971 li_t1 %128 %0 1972 mul_t0,t0,t1 1973 li_t1 %0 %0 1974 sub_t1,t1,t0 1975 la_a1 &pr_lo 1976 st_t1,a1,0 1977 addi_t0,t0,neg1 1978 la_a1 &pr_hi 1979 st_t0,a1,0 1980 eret 1981 :ssi_pct 1982 la_a0 &ptrsize 1983 ld_t0,a0,0 1984 la_a1 &pr_width 1985 st_t0,a1,0 1986 li_t0 %1 %0 1987 la_a1 &pr_is_rel 1988 st_t0,a1,0 1989 la_a1 &ptrsize_used 1990 st_t0,a1,0 1991 li_t0 %0 %0 1992 la_a1 &pr_range_check 1993 st_t0,a1,0 1994 la_a1 &pr_lo 1995 st_t0,a1,0 1996 la_a1 &pr_hi 1997 st_t0,a1,0 1998 eret 1999 :ssi_amp 2000 la_a0 &ptrsize 2001 ld_t0,a0,0 2002 la_a1 &pr_width 2003 st_t0,a1,0 2004 li_t0 %1 %0 2005 la_a1 &ptrsize_used 2006 st_t0,a1,0 2007 li_t0 %0 %0 2008 la_a1 &pr_is_rel 2009 st_t0,a1,0 2010 la_a1 &pr_range_check 2011 st_t0,a1,0 2012 la_a1 &pr_lo 2013 st_t0,a1,0 2014 la_a1 &pr_hi 2015 st_t0,a1,0 2016 eret 2017 2018 ## --- Directives ------------------------------------------------------------ 2019 2020 ## do_align(): .align N [PATTERN]. N positive power of two; optional pattern. 2021 :do_align 2022 enter_0 2023 la_br &skip_inline_ws 2024 call 2025 la_br &read_decimal 2026 call 2027 la_a1 &da_n 2028 st_a0,a1,0 2029 la_br &err_align_n 2030 beqz_a0 2031 la_br &err_align_n 2032 bltz_a0 2033 # power-of-two: N & (N-1) == 0 2034 la_a0 &da_n 2035 ld_a3,a0,0 2036 addi_a3,a3,neg1 2037 la_a0 &da_n 2038 ld_a2,a0,0 2039 and_a3,a3,a2 2040 la_br &err_align_n 2041 bnez_a3 2042 li_t0 %0 %0 2043 la_a0 &da_has_pat 2044 st_t0,a0,0 2045 la_a0 &da_patlen 2046 st_t0,a0,0 2047 la_br &skip_inline_ws 2048 call 2049 la_a0 &scan_pos 2050 ld_t0,a0,0 2051 la_a1 &scan_end 2052 ld_t1,a1,0 2053 la_br &da_compute 2054 beq_t0,t1 2055 la_br &da_compute 2056 blt_t1,t0 2057 lb_a0,t0,0 2058 la_br &is_byte_digit 2059 call 2060 la_br &da_compute 2061 beqz_a0 2062 li_t0 %1 %0 2063 la_a1 &da_has_pat 2064 st_t0,a1,0 2065 :da_pat_loop 2066 la_a0 &scan_pos 2067 ld_t0,a0,0 2068 la_a1 &scan_end 2069 ld_t1,a1,0 2070 la_br &da_compute 2071 beq_t0,t1 2072 la_br &da_compute 2073 blt_t1,t0 2074 lb_a0,t0,0 2075 la_br &is_byte_digit 2076 call 2077 la_br &da_compute 2078 beqz_a0 2079 la_a0 &da_patlen 2080 ld_t0,a0,0 2081 li_t1 H2_TOKEN_CAP 2082 la_br &err_pattern_too_large 2083 beq_t0,t1 2084 la_a0 &pat_buf_ptr 2085 ld_a0,a0,0 2086 add_a0,a0,t0 2087 la_br &parse_one_byte 2088 call 2089 la_a0 &da_patlen 2090 ld_t0,a0,0 2091 addi_t0,t0,1 2092 st_t0,a0,0 2093 la_br &da_pat_loop 2094 b 2095 :da_compute 2096 # pad = (N - (ip mod N)) mod N 2097 la_a0 &ip 2098 ld_a0,a0,0 2099 la_a1 &da_n 2100 ld_a1,a1,0 2101 rem_a2,a0,a1 2102 li_t0 %0 %0 2103 la_a3 &da_pad 2104 st_t0,a3,0 2105 la_br &da_emit 2106 beqz_a2 2107 sub_a3,a1,a2 2108 la_a1 &da_pad 2109 st_a3,a1,0 2110 :da_emit 2111 la_a0 &da_pad 2112 ld_t0,a0,0 2113 la_br &da_emit_done 2114 beqz_t0 2115 # No-pattern fast path: emit_zeros(pad). 2116 la_a1 &da_has_pat 2117 ld_t1,a1,0 2118 la_br &da_emit_pattern 2119 bnez_t1 2120 la_a0 &da_pad 2121 ld_a0,a0,0 2122 la_br &emit_zeros 2123 call 2124 la_br &da_emit_done 2125 b 2126 :da_emit_pattern 2127 li_t0 %0 %0 2128 la_a0 &da_i 2129 st_t0,a0,0 2130 :da_pattern_loop 2131 la_a0 &da_i 2132 ld_t0,a0,0 2133 la_a1 &da_pad 2134 ld_t1,a1,0 2135 la_br &da_emit_done 2136 beq_t0,t1 2137 # b = pat[i % patlen] 2138 la_a1 &da_patlen 2139 ld_a1,a1,0 2140 rem_a2,t0,a1 2141 la_a0 &pat_buf_ptr 2142 ld_a0,a0,0 2143 add_a0,a0,a2 2144 lb_a0,a0,0 2145 la_br &emit_byte 2146 call 2147 la_a0 &da_i 2148 ld_t0,a0,0 2149 addi_t0,t0,1 2150 st_t0,a0,0 2151 la_br &da_pattern_loop 2152 b 2153 :da_emit_done 2154 eret 2155 2156 ## do_fill(): .fill N B. 2157 :do_fill 2158 enter_0 2159 la_br &skip_inline_ws 2160 call 2161 la_br &read_decimal 2162 call 2163 la_a1 &df_n 2164 st_a0,a1,0 2165 la_br &err_fill_n 2166 bltz_a0 2167 la_br &skip_inline_ws 2168 call 2169 la_a0 &df_byte_ptr 2170 ld_a0,a0,0 2171 la_br &parse_one_byte 2172 call 2173 la_a0 &df_n 2174 ld_a0,a0,0 2175 la_br &df_done 2176 beqz_a0 2177 la_a1 &df_byte_ptr 2178 ld_a1,a1,0 2179 lb_a1,a1,0 2180 la_br &emit_fill 2181 call 2182 :df_done 2183 eret 2184 2185 ## do_scope_open(): scope_seq++; scope_stack[scope_depth++] = scope_seq. 2186 :do_scope_open 2187 enter_0 2188 la_a0 &scope_depth 2189 ld_t0,a0,0 2190 li_t1 H2_SCOPE_CAP 2191 la_br &err_scope_overflow 2192 beq_t0,t1 2193 la_br &err_scope_overflow 2194 blt_t1,t0 2195 la_a0 &scope_seq 2196 ld_t1,a0,0 2197 addi_t1,t1,1 2198 st_t1,a0,0 2199 la_a1 &scope_stack_ptr 2200 ld_a1,a1,0 2201 shli_t2,t0,3 2202 add_a1,a1,t2 2203 st_t1,a1,0 2204 addi_t0,t0,1 2205 la_a0 &scope_depth 2206 st_t0,a0,0 2207 eret 2208 2209 ## do_scope_close(): scope_depth--. 2210 :do_scope_close 2211 enter_0 2212 la_a0 &scope_depth 2213 ld_t0,a0,0 2214 la_br &err_scope_underflow 2215 beqz_t0 2216 addi_t0,t0,neg1 2217 st_t0,a0,0 2218 eret 2219 2220 ## do_ptrsize(): .ptrsize N -- N must be 4 or 8. 2221 :do_ptrsize 2222 enter_0 2223 la_br &skip_inline_ws 2224 call 2225 la_br &read_decimal 2226 call 2227 la_a1 &dp_n 2228 st_a0,a1,0 2229 li_t0 %4 %0 2230 la_br &dp_ok 2231 beq_a0,t0 2232 li_t0 %8 %0 2233 la_br &dp_ok 2234 beq_a0,t0 2235 la_br &err_ptrsize_bad 2236 b 2237 :dp_ok 2238 la_a0 &ptrsize_used 2239 ld_t0,a0,0 2240 la_br &dp_set 2241 beqz_t0 2242 la_a0 &ptrsize 2243 ld_t0,a0,0 2244 la_a1 &dp_n 2245 ld_t1,a1,0 2246 la_br &err_ptrsize_conflict 2247 bne_t0,t1 2248 eret 2249 :dp_set 2250 la_a0 &dp_n 2251 ld_t0,a0,0 2252 la_a1 &ptrsize 2253 st_t0,a1,0 2254 eret 2255 2256 ## --- Emit ------------------------------------------------------------------ 2257 2258 ## emit_byte(a0=byte): write one byte to output_buf and bump ip. 2259 :emit_byte 2260 la_a1 &output_used 2261 ld_t0,a1,0 2262 li_t1 H2_OUTPUT_CAP 2263 la_br &err_output_overflow 2264 beq_t0,t1 2265 la_br &err_output_overflow 2266 blt_t1,t0 2267 la_a2 &output_buf_ptr 2268 ld_a2,a2,0 2269 add_a2,a2,t0 2270 sb_a0,a2,0 2271 addi_t0,t0,1 2272 st_t0,a1,0 2273 la_a0 &ip 2274 ld_t0,a0,0 2275 addi_t0,t0,1 2276 st_t0,a0,0 2277 ret 2278 2279 ## emit_zeros(a0=n) -> a0 = starting offset (output_used before the call). 2280 ## Writes n zero bytes to output_buf and advances output_used + ip by n. 2281 :emit_zeros 2282 enter_0 2283 la_a3 &emz_n 2284 st_a0,a3,0 2285 # Capacity check: output_used + n must fit. 2286 la_a1 &output_used 2287 ld_t0,a1,0 2288 add_t1,t0,a0 2289 li_t2 H2_OUTPUT_CAP 2290 la_br &err_output_overflow 2291 blt_t2,t1 2292 la_a2 &emz_off 2293 st_t0,a2,0 2294 la_a2 &output_buf_ptr 2295 ld_a2,a2,0 2296 add_a2,a2,t0 2297 li_t1 %0 %0 2298 :emz_loop 2299 la_a3 &emz_n 2300 ld_t2,a3,0 2301 la_br &emz_done 2302 beq_t1,t2 2303 add_a3,a2,t1 2304 li_t0 %0 %0 2305 sb_t0,a3,0 2306 addi_t1,t1,1 2307 la_br &emz_loop 2308 b 2309 :emz_done 2310 la_a3 &emz_n 2311 ld_t0,a3,0 2312 la_a1 &output_used 2313 ld_t1,a1,0 2314 add_t1,t1,t0 2315 st_t1,a1,0 2316 la_a1 &ip 2317 ld_t1,a1,0 2318 add_t1,t1,t0 2319 st_t1,a1,0 2320 la_a0 &emz_off 2321 ld_a0,a0,0 2322 eret 2323 2324 ## emit_fill(a0=n, a1=byte): write n copies of byte; advances output_used + ip. 2325 :emit_fill 2326 enter_0 2327 la_a3 &emf_n 2328 st_a0,a3,0 2329 la_a3 &emf_b 2330 st_a1,a3,0 2331 la_a2 &output_used 2332 ld_t0,a2,0 2333 add_t1,t0,a0 2334 li_t2 H2_OUTPUT_CAP 2335 la_br &err_output_overflow 2336 blt_t2,t1 2337 la_a2 &output_buf_ptr 2338 ld_a2,a2,0 2339 add_a2,a2,t0 2340 li_t1 %0 %0 2341 :emf_loop 2342 la_a3 &emf_n 2343 ld_t2,a3,0 2344 la_br &emf_done 2345 beq_t1,t2 2346 la_a3 &emf_b 2347 ld_t0,a3,0 2348 add_a3,a2,t1 2349 sb_t0,a3,0 2350 addi_t1,t1,1 2351 la_br &emf_loop 2352 b 2353 :emf_done 2354 la_a3 &emf_n 2355 ld_t0,a3,0 2356 la_a1 &output_used 2357 ld_t1,a1,0 2358 add_t1,t1,t0 2359 st_t1,a1,0 2360 la_a1 &ip 2361 ld_t1,a1,0 2362 add_t1,t1,t0 2363 st_t1,a1,0 2364 eret 2365 2366 ## write_value(a0=out_off): patch a value into output_buf at out_off. 2367 ## Caller pre-populates ev_value/ev_width/ev_lo/ev_hi/ev_range_check. 2368 :write_value 2369 enter_0 2370 la_t1 &ev_out_off 2371 st_a0,t1,0 2372 2373 la_a0 &ev_range_check 2374 ld_t0,a0,0 2375 la_br &wv_no_range 2376 beqz_t0 2377 la_a0 &ev_value 2378 ld_a0,a0,0 2379 la_a1 &ev_lo 2380 ld_a1,a1,0 2381 la_br &err_ref_out_of_range 2382 blt_a0,a1 2383 la_a0 &ev_value 2384 ld_a0,a0,0 2385 la_a1 &ev_hi 2386 ld_a1,a1,0 2387 la_br &err_ref_out_of_range 2388 blt_a1,a0 2389 :wv_no_range 2390 la_a0 &ev_value 2391 ld_a0,a0,0 2392 la_a1 &ev_pack_v 2393 st_a0,a1,0 2394 li_t0 %0 %0 2395 la_a0 &ev_i 2396 st_t0,a0,0 2397 :wv_pack_loop 2398 la_a0 &ev_i 2399 ld_t0,a0,0 2400 la_a1 &ev_width 2401 ld_t1,a1,0 2402 la_br &wv_emit_dispatch 2403 beq_t0,t1 2404 la_a1 &ev_pack_v 2405 ld_a3,a1,0 2406 andi_a3,a3,255 2407 la_a2 &ev_bytes_ptr 2408 ld_a2,a2,0 2409 add_a2,a2,t0 2410 sb_a3,a2,0 2411 la_a1 &ev_pack_v 2412 ld_t2,a1,0 2413 shri_t2,t2,8 2414 st_t2,a1,0 2415 addi_t0,t0,1 2416 la_a0 &ev_i 2417 st_t0,a0,0 2418 la_br &wv_pack_loop 2419 b 2420 :wv_emit_dispatch 2421 la_a0 &big_endian 2422 ld_t0,a0,0 2423 la_br &wv_emit_be 2424 bnez_t0 2425 li_t0 %0 %0 2426 la_a0 &ev_i 2427 st_t0,a0,0 2428 :wv_emit_le_loop 2429 la_a0 &ev_i 2430 ld_t0,a0,0 2431 la_a1 &ev_width 2432 ld_t1,a1,0 2433 la_br &wv_done 2434 beq_t0,t1 2435 la_a2 &ev_bytes_ptr 2436 ld_a2,a2,0 2437 add_a2,a2,t0 2438 lb_a0,a2,0 2439 la_a3 &output_buf_ptr 2440 ld_a3,a3,0 2441 la_a2 &ev_out_off 2442 ld_a2,a2,0 2443 add_a3,a3,a2 2444 add_a3,a3,t0 2445 sb_a0,a3,0 2446 addi_t0,t0,1 2447 la_a0 &ev_i 2448 st_t0,a0,0 2449 la_br &wv_emit_le_loop 2450 b 2451 :wv_emit_be 2452 li_t0 %0 %0 2453 la_a0 &ev_i 2454 st_t0,a0,0 2455 :wv_emit_be_loop 2456 la_a0 &ev_i 2457 ld_t0,a0,0 2458 la_a1 &ev_width 2459 ld_t1,a1,0 2460 la_br &wv_done 2461 beq_t0,t1 2462 # src_idx = (width - 1) - i 2463 addi_t1,t1,neg1 2464 sub_t2,t1,t0 2465 la_a2 &ev_bytes_ptr 2466 ld_a2,a2,0 2467 add_a2,a2,t2 2468 lb_a0,a2,0 2469 la_a3 &output_buf_ptr 2470 ld_a3,a3,0 2471 la_a2 &ev_out_off 2472 ld_a2,a2,0 2473 add_a3,a3,a2 2474 add_a3,a3,t0 2475 sb_a0,a3,0 2476 addi_t0,t0,1 2477 la_a0 &ev_i 2478 st_t0,a0,0 2479 la_br &wv_emit_be_loop 2480 b 2481 :wv_done 2482 eret 2483 2484 ## --- Fixup resolution ------------------------------------------------------ 2485 ## patch_fixups(): walk fixups[0..fixup_count), resolve labels, write values 2486 ## into output_buf. Per-fixup error reports use the snapshotted src_path / 2487 ## src_line via the cur_path / cur_line globals. 2488 :patch_fixups 2489 enter_0 2490 li_t0 %0 %0 2491 la_a0 &pf_i 2492 st_t0,a0,0 2493 :pf_loop 2494 la_a0 &pf_i 2495 ld_t0,a0,0 2496 la_a1 &fixup_count 2497 ld_t1,a1,0 2498 la_br &pf_done 2499 beq_t0,t1 2500 # fp = fixups + i*96 2501 li_t1 %96 %0 2502 mul_a1,t0,t1 2503 la_a2 &fixups_ptr 2504 ld_a2,a2,0 2505 add_a1,a1,a2 2506 la_a3 &pf_fp 2507 st_a1,a3,0 2508 # cur_path = fp[32]; cur_line = fp[72]; cur_sigil = fp[80] 2509 ld_t0,a1,32 2510 la_a2 &cur_path 2511 st_t0,a2,0 2512 li_t1 %72 %0 2513 add_a3,a1,t1 2514 ld_t0,a3,0 2515 la_a2 &cur_line 2516 st_t0,a2,0 2517 li_t1 %80 %0 2518 add_a3,a1,t1 2519 ld_t0,a3,0 2520 la_a2 &cur_sigil 2521 st_t0,a2,0 2522 # pr_width / pr_is_rel / pr_lo / pr_hi / pr_range_check 2523 la_br &set_sigil_info 2524 call 2525 # Determine stack pointer for the lookup (NULL if depth == 0). 2526 la_a0 &pf_fp 2527 ld_a1,a0,0 2528 ld_t0,a1,64 2529 la_a2 &pf_depth 2530 st_t0,a2,0 2531 li_t1 %0 %0 2532 la_a2 &pf_stack 2533 st_t1,a2,0 2534 la_br &pf_lookup_label 2535 beqz_t0 2536 # stack = scope_history_ptr + scope_hist_off * 8 2537 ld_t1,a1,56 2538 shli_t1,t1,3 2539 la_a2 &scope_history_ptr 2540 ld_a2,a2,0 2541 add_a2,a2,t1 2542 la_a3 &pf_stack 2543 st_a2,a3,0 2544 :pf_lookup_label 2545 la_a0 &pf_fp 2546 ld_a1,a0,0 2547 ld_a0,a1,16 2548 ld_t0,a1,40 2549 mov_a1,t0 2550 la_a2 &pf_stack 2551 ld_a2,a2,0 2552 la_a3 &pf_depth 2553 ld_a3,a3,0 2554 la_br &lookup_label_in 2555 call 2556 la_a1 &pf_t_label 2557 st_a0,a1,0 2558 # If other != 0: value = t_label - t_other; emit. 2559 la_a0 &pf_fp 2560 ld_a1,a0,0 2561 ld_t0,a1,24 2562 la_br &pf_no_other 2563 beqz_t0 2564 mov_a0,t0 2565 ld_t0,a1,48 2566 mov_a1,t0 2567 la_a2 &pf_stack 2568 ld_a2,a2,0 2569 la_a3 &pf_depth 2570 ld_a3,a3,0 2571 la_br &lookup_label_in 2572 call 2573 la_a1 &pf_t_label 2574 ld_a1,a1,0 2575 sub_a0,a1,a0 2576 la_a1 &pf_value 2577 st_a0,a1,0 2578 la_br &pf_emit 2579 b 2580 :pf_no_other 2581 la_a0 &pr_is_rel 2582 ld_t0,a0,0 2583 la_br &pf_abs 2584 beqz_t0 2585 # rel: value = t_label - ip_at_ref 2586 la_a0 &pf_fp 2587 ld_a1,a0,0 2588 ld_t1,a1,8 2589 la_a0 &pf_t_label 2590 ld_a0,a0,0 2591 sub_a0,a0,t1 2592 la_a1 &pf_value 2593 st_a0,a1,0 2594 la_br &pf_emit 2595 b 2596 :pf_abs 2597 la_a0 &pf_t_label 2598 ld_a1,a0,0 2599 la_a0 &base_address 2600 ld_a0,a0,0 2601 add_a1,a1,a0 2602 la_a3 &pf_value 2603 st_a1,a3,0 2604 :pf_emit 2605 # Populate ev_* state, then write_value(out_off). 2606 la_a0 &pf_value 2607 ld_t0,a0,0 2608 la_a1 &ev_value 2609 st_t0,a1,0 2610 la_a0 &pr_width 2611 ld_t0,a0,0 2612 la_a1 &ev_width 2613 st_t0,a1,0 2614 la_a0 &pr_lo 2615 ld_t0,a0,0 2616 la_a1 &ev_lo 2617 st_t0,a1,0 2618 la_a0 &pr_hi 2619 ld_t0,a0,0 2620 la_a1 &ev_hi 2621 st_t0,a1,0 2622 la_a0 &pr_range_check 2623 ld_t0,a0,0 2624 la_a1 &ev_range_check 2625 st_t0,a1,0 2626 la_a0 &pf_fp 2627 ld_a1,a0,0 2628 ld_a0,a1,0 2629 la_br &write_value 2630 call 2631 # i++ 2632 la_a0 &pf_i 2633 ld_t0,a0,0 2634 addi_t0,t0,1 2635 st_t0,a0,0 2636 la_br &pf_loop 2637 b 2638 :pf_done 2639 eret 2640 2641 ## --- Output writer --------------------------------------------------------- 2642 :write_output 2643 enter_0 2644 la_a0 &output_path 2645 ld_a2,a0,0 2646 li_a0 sys_openat 2647 li_a1 H2_AT_FDCWD 2648 li_a3 H2_O_WRONLY_CREAT_TRUNC 2649 la_t1 &non_executable 2650 ld_t1,t1,0 2651 la_br &wo_mode_nonexec 2652 bnez_t1 2653 li_t0 H2_MODE_0750 2654 la_br &wo_after_mode 2655 b 2656 :wo_mode_nonexec 2657 li_t0 H2_MODE_0640 2658 :wo_after_mode 2659 syscall 2660 la_br &err_open_output 2661 bltz_a0 2662 la_a1 &output_fd 2663 st_a0,a1,0 2664 li_t0 %0 %0 2665 la_a1 &output_written 2666 st_t0,a1,0 2667 :wo_loop 2668 la_a0 &output_written 2669 ld_t0,a0,0 2670 la_a1 &output_used 2671 ld_t1,a1,0 2672 la_br &wo_done 2673 beq_t0,t1 2674 la_a0 &output_fd 2675 ld_a1,a0,0 2676 la_a2 &output_buf_ptr 2677 ld_a2,a2,0 2678 add_a2,a2,t0 2679 sub_a3,t1,t0 2680 li_a0 sys_write 2681 syscall 2682 la_br &err_write 2683 bltz_a0 2684 la_br &err_write 2685 beqz_a0 2686 la_a1 &output_written 2687 ld_t0,a1,0 2688 add_t0,t0,a0 2689 st_t0,a1,0 2690 la_br &wo_loop 2691 b 2692 :wo_done 2693 eret 2694 2695 ## --- Misc helpers ---------------------------------------------------------- 2696 2697 ## str_eq(a0=p, a1=q, a2=len) -> a0=0/1. len bytes equal AND p[len]==NUL. 2698 :str_eq 2699 enter_0 2700 la_t0 &se_p 2701 st_a0,t0,0 2702 la_t0 &se_q 2703 st_a1,t0,0 2704 la_t0 &se_len 2705 st_a2,t0,0 2706 li_t1 %0 %0 2707 :se_loop 2708 la_a0 &se_len 2709 ld_a1,a0,0 2710 la_br &se_check_terminal 2711 beq_t1,a1 2712 la_a0 &se_p 2713 ld_a0,a0,0 2714 add_a0,a0,t1 2715 lb_t0,a0,0 2716 la_a2 &se_q 2717 ld_a2,a2,0 2718 add_a2,a2,t1 2719 lb_t2,a2,0 2720 la_br &se_no 2721 bne_t0,t2 2722 addi_t1,t1,1 2723 la_br &se_loop 2724 b 2725 :se_check_terminal 2726 la_a0 &se_p 2727 ld_a0,a0,0 2728 add_a0,a0,t1 2729 lb_t0,a0,0 2730 la_br &se_no 2731 bnez_t0 2732 li_a0 %1 %0 2733 eret 2734 :se_no 2735 li_a0 %0 %0 2736 eret 2737 2738 ## mem_eq(a0=p, a1=q, a2=len) -> a0=0/1. 2739 :mem_eq 2740 enter_0 2741 la_t0 &me_p 2742 st_a0,t0,0 2743 la_t0 &me_q 2744 st_a1,t0,0 2745 la_t0 &me_len 2746 st_a2,t0,0 2747 li_t1 %0 %0 2748 :me_loop 2749 la_a0 &me_len 2750 ld_a1,a0,0 2751 la_br &me_yes 2752 beq_t1,a1 2753 la_a0 &me_p 2754 ld_a0,a0,0 2755 add_a0,a0,t1 2756 lb_t0,a0,0 2757 la_a2 &me_q 2758 ld_a2,a2,0 2759 add_a2,a2,t1 2760 lb_t2,a2,0 2761 la_br &me_no 2762 bne_t0,t2 2763 addi_t1,t1,1 2764 la_br &me_loop 2765 b 2766 :me_yes 2767 li_a0 %1 %0 2768 eret 2769 :me_no 2770 li_a0 %0 %0 2771 eret 2772 2773 ## parse_long(a0=cstr) -> a0=value. Decimal or 0x-prefixed hex i64. 2774 :parse_long 2775 enter_0 2776 la_t0 &pl_p 2777 st_a0,t0,0 2778 li_t0 %0 %0 2779 la_a1 &pl_val 2780 st_t0,a1,0 2781 la_a1 &pl_neg 2782 st_t0,a1,0 2783 # 0x / 0X prefix? 2784 la_a0 &pl_p 2785 ld_a0,a0,0 2786 lb_t0,a0,0 2787 li_t1 %48 %0 2788 la_br &pl_dec_init 2789 bne_t0,t1 2790 lb_t0,a0,1 2791 li_t1 %120 %0 2792 la_br &pl_hex_init 2793 beq_t0,t1 2794 li_t1 %88 %0 2795 la_br &pl_hex_init 2796 beq_t0,t1 2797 la_br &pl_dec_init 2798 b 2799 :pl_hex_init 2800 la_a0 &pl_p 2801 ld_t0,a0,0 2802 addi_t0,t0,2 2803 st_t0,a0,0 2804 :pl_hex_loop 2805 la_a0 &pl_p 2806 ld_t0,a0,0 2807 lb_t0,t0,0 2808 la_br &pl_finish 2809 beqz_t0 2810 # accept '0'..'9' / 'A'..'F' / 'a'..'f'; reject anything else 2811 li_t1 %48 %0 2812 la_br &err_bad_long 2813 blt_t0,t1 2814 li_t1 %57 %0 2815 la_br &pl_hex_acc 2816 blt_t0,t1 2817 la_br &pl_hex_acc 2818 beq_t0,t1 2819 li_t1 %65 %0 2820 la_br &err_bad_long 2821 blt_t0,t1 2822 li_t1 %70 %0 2823 la_br &pl_hex_acc 2824 blt_t0,t1 2825 la_br &pl_hex_acc 2826 beq_t0,t1 2827 li_t1 %97 %0 2828 la_br &err_bad_long 2829 blt_t0,t1 2830 li_t1 %102 %0 2831 la_br &pl_hex_acc 2832 blt_t0,t1 2833 la_br &pl_hex_acc 2834 beq_t0,t1 2835 la_br &err_bad_long 2836 b 2837 :pl_hex_acc 2838 mov_a0,t0 2839 la_br &byte_digit_value 2840 call 2841 la_a1 &pl_val 2842 ld_t0,a1,0 2843 shli_t0,t0,4 2844 add_t0,t0,a0 2845 st_t0,a1,0 2846 la_a0 &pl_p 2847 ld_t0,a0,0 2848 addi_t0,t0,1 2849 st_t0,a0,0 2850 la_br &pl_hex_loop 2851 b 2852 :pl_dec_init 2853 la_a0 &pl_p 2854 ld_a0,a0,0 2855 lb_t0,a0,0 2856 li_t1 %45 %0 2857 la_br &pl_dec_loop 2858 bne_t0,t1 2859 li_t0 %1 %0 2860 la_a1 &pl_neg 2861 st_t0,a1,0 2862 la_a0 &pl_p 2863 ld_t0,a0,0 2864 addi_t0,t0,1 2865 st_t0,a0,0 2866 :pl_dec_loop 2867 la_a0 &pl_p 2868 ld_t0,a0,0 2869 lb_t0,t0,0 2870 la_br &pl_finish 2871 beqz_t0 2872 li_t1 %48 %0 2873 la_br &err_bad_long 2874 blt_t0,t1 2875 li_t1 %57 %0 2876 la_br &err_bad_long 2877 blt_t1,t0 2878 li_t1 %48 %0 2879 sub_t0,t0,t1 2880 la_a1 &pl_val 2881 ld_a2,a1,0 2882 li_t1 %10 %0 2883 mul_a2,a2,t1 2884 add_a2,a2,t0 2885 st_a2,a1,0 2886 la_a0 &pl_p 2887 ld_t0,a0,0 2888 addi_t0,t0,1 2889 st_t0,a0,0 2890 la_br &pl_dec_loop 2891 b 2892 :pl_finish 2893 la_a1 &pl_neg 2894 ld_t0,a1,0 2895 la_br &pl_done 2896 beqz_t0 2897 la_a1 &pl_val 2898 ld_a3,a1,0 2899 li_t0 %0 %0 2900 sub_a3,t0,a3 2901 st_a3,a1,0 2902 :pl_done 2903 la_a1 &pl_val 2904 ld_a0,a1,0 2905 eret 2906 2907 ## --- Errors ---------------------------------------------------------------- 2908 2909 ## fatal(a0=msg_ptr): writes "<path>:<line>: hex2pp: <msg>\n" to stderr if 2910 ## cur_path is set, else "hex2pp: <msg>\n", then exits 1. 2911 :fatal 2912 la_a1 &fm_msg 2913 st_a0,a1,0 2914 la_a0 &cur_path 2915 ld_t0,a0,0 2916 la_br &fm_no_path 2917 beqz_t0 2918 # write path 2919 mov_a0,t0 2920 la_br &cstrlen 2921 call 2922 la_a3 &fm_tmp 2923 st_a0,a3,0 2924 la_a2 &cur_path 2925 ld_a2,a2,0 2926 la_a3 &fm_tmp 2927 ld_a3,a3,0 2928 li_a0 sys_write 2929 li_a1 %2 %0 2930 syscall 2931 # ":" 2932 li_a0 sys_write 2933 li_a1 %2 %0 2934 la_a2 &str_colon 2935 li_a3 %1 %0 2936 syscall 2937 # decimal cur_line 2938 la_a0 &cur_line 2939 ld_a0,a0,0 2940 la_br &write_decimal_stderr 2941 call 2942 # ": hex2pp: " 2943 li_a0 sys_write 2944 li_a1 %2 %0 2945 la_a2 &str_colon_prog 2946 li_a3 %10 %0 2947 syscall 2948 la_br &fm_emit_msg 2949 b 2950 :fm_no_path 2951 li_a0 sys_write 2952 li_a1 %2 %0 2953 la_a2 &str_prog 2954 li_a3 %8 %0 2955 syscall 2956 :fm_emit_msg 2957 la_a0 &fm_msg 2958 ld_a0,a0,0 2959 la_br &cstrlen 2960 call 2961 la_a3 &fm_tmp 2962 st_a0,a3,0 2963 la_a2 &fm_msg 2964 ld_a2,a2,0 2965 la_a3 &fm_tmp 2966 ld_a3,a3,0 2967 li_a0 sys_write 2968 li_a1 %2 %0 2969 syscall 2970 li_a0 sys_write 2971 li_a1 %2 %0 2972 la_a2 &str_newline 2973 li_a3 %1 %0 2974 syscall 2975 li_a0 sys_exit 2976 li_a1 %1 %0 2977 syscall 2978 2979 ## cstrlen(a0=p) -> a0=length. Walks until NUL. 2980 :cstrlen 2981 li_t0 %0 %0 2982 :cs_loop 2983 add_t1,a0,t0 2984 lb_t1,t1,0 2985 la_br &cs_done 2986 beqz_t1 2987 addi_t0,t0,1 2988 la_br &cs_loop 2989 b 2990 :cs_done 2991 mov_a0,t0 2992 ret 2993 2994 ## write_decimal_stderr(a0=value): write decimal of unsigned i64 to stderr. 2995 :write_decimal_stderr 2996 enter_0 2997 la_a1 &wd_v 2998 st_a0,a1,0 2999 la_br &wd_nonzero 3000 bnez_a0 3001 li_a0 sys_write 3002 li_a1 %2 %0 3003 la_a2 &str_zero 3004 li_a3 %1 %0 3005 syscall 3006 eret 3007 :wd_nonzero 3008 li_t0 %63 %0 3009 la_a1 &wd_pos 3010 st_t0,a1,0 3011 :wd_loop 3012 la_a0 &wd_v 3013 ld_a0,a0,0 3014 la_br &wd_emit 3015 beqz_a0 3016 li_t1 %10 %0 3017 rem_a2,a0,t1 3018 div_a0,a0,t1 3019 la_a3 &wd_v 3020 st_a0,a3,0 3021 li_t1 %48 %0 3022 add_a3,t1,a2 3023 la_a0 &wd_pos 3024 ld_t0,a0,0 3025 la_a1 &line_scratch_ptr 3026 ld_a1,a1,0 3027 add_a1,a1,t0 3028 sb_a3,a1,0 3029 addi_t0,t0,neg1 3030 la_a0 &wd_pos 3031 st_t0,a0,0 3032 la_br &wd_loop 3033 b 3034 :wd_emit 3035 la_a0 &wd_pos 3036 ld_t0,a0,0 3037 addi_t0,t0,1 3038 la_a1 &line_scratch_ptr 3039 ld_a1,a1,0 3040 add_a1,a1,t0 3041 mov_a2,a1 3042 li_t1 %64 %0 3043 sub_a3,t1,t0 3044 li_a0 sys_write 3045 li_a1 %2 %0 3046 syscall 3047 eret 3048 3049 ## --- Error stubs ----------------------------------------------------------- 3050 :err_unknown_arg 3051 la_a0 &msg_unknown_arg 3052 la_br &fatal 3053 b 3054 :err_extra_positional 3055 la_a0 &msg_extra_positional 3056 la_br &fatal 3057 b 3058 :err_missing_positional 3059 la_a0 &msg_missing_positional 3060 la_br &fatal 3061 b 3062 :err_missing_value 3063 la_a0 &msg_missing_value 3064 la_br &fatal 3065 b 3066 :err_open_input 3067 la_a0 &msg_open_input 3068 la_br &fatal 3069 b 3070 :err_read 3071 la_a0 &msg_read 3072 la_br &fatal 3073 b 3074 :err_input_too_big 3075 la_a0 &msg_input_too_big 3076 la_br &fatal 3077 b 3078 :err_open_output 3079 la_a0 &msg_open_output 3080 la_br &fatal 3081 b 3082 :err_write 3083 la_a0 &msg_write 3084 la_br &fatal 3085 b 3086 :err_text_overflow 3087 la_a0 &msg_text_overflow 3088 la_br &fatal 3089 b 3090 :err_too_many_labels 3091 la_a0 &msg_too_many_labels 3092 la_br &fatal 3093 b 3094 :err_duplicate_label 3095 la_a0 &msg_duplicate_label 3096 la_br &fatal 3097 b 3098 :err_undefined_label 3099 la_a0 &msg_undefined_label 3100 la_br &fatal 3101 b 3102 :err_undefined_local 3103 la_a0 &msg_undefined_local 3104 la_br &fatal 3105 b 3106 :err_unexpected_char 3107 la_a0 &msg_unexpected_char 3108 la_br &fatal 3109 b 3110 :err_unknown_directive 3111 la_a0 &msg_unknown_directive 3112 la_br &fatal 3113 b 3114 :err_scope_overflow 3115 la_a0 &msg_scope_overflow 3116 la_br &fatal 3117 b 3118 :err_scope_underflow 3119 la_a0 &msg_scope_underflow 3120 la_br &fatal 3121 b 3122 :err_scope_unclosed 3123 la_a0 &msg_scope_unclosed 3124 la_br &fatal 3125 b 3126 :err_align_n 3127 la_a0 &msg_align_n 3128 la_br &fatal 3129 b 3130 :err_fill_n 3131 la_a0 &msg_fill_n 3132 la_br &fatal 3133 b 3134 :err_pattern_too_large 3135 la_a0 &msg_pattern_too_large 3136 la_br &fatal 3137 b 3138 :err_byte_lit_bad 3139 la_a0 &msg_byte_lit_bad 3140 la_br &fatal 3141 b 3142 :err_byte_stream_short 3143 la_a0 &msg_byte_stream_short 3144 la_br &fatal 3145 b 3146 :err_sigil_no_label 3147 la_a0 &msg_sigil_no_label 3148 la_br &fatal 3149 b 3150 :err_minus_no_label 3151 la_a0 &msg_minus_no_label 3152 la_br &fatal 3153 b 3154 :err_bad_sigil 3155 la_a0 &msg_bad_sigil 3156 la_br &fatal 3157 b 3158 :err_ref_out_of_range 3159 la_a0 &msg_ref_out_of_range 3160 la_br &fatal 3161 b 3162 :err_name_too_long 3163 la_a0 &msg_name_too_long 3164 la_br &fatal 3165 b 3166 :err_empty_name 3167 la_a0 &msg_empty_name 3168 la_br &fatal 3169 b 3170 :err_empty_directive 3171 la_a0 &msg_empty_directive 3172 la_br &fatal 3173 b 3174 :err_expected_decimal 3175 la_a0 &msg_expected_decimal 3176 la_br &fatal 3177 b 3178 :err_output_overflow 3179 la_a0 &msg_output_overflow 3180 la_br &fatal 3181 b 3182 :err_bad_long 3183 la_a0 &msg_bad_long 3184 la_br &fatal 3185 b 3186 :err_too_many_fixups 3187 la_a0 &msg_too_many_fixups 3188 la_br &fatal 3189 b 3190 :err_scope_history_overflow 3191 la_a0 &msg_scope_history_overflow 3192 la_br &fatal 3193 b 3194 :err_ptrsize_bad 3195 la_a0 &msg_ptrsize_bad 3196 la_br &fatal 3197 b 3198 :err_ptrsize_conflict 3199 la_a0 &msg_ptrsize_conflict 3200 la_br &fatal 3201 b 3202 3203 ## Sentinel: end of executable text. 3204 :_text_end 3205 3206 ## --- Rodata ---------------------------------------------------------------- 3207 3208 :opt_B "-B" '00' 3209 :opt_E "-E" '00' 3210 :opt_e "-e" '00' 3211 :opt_b "-b" '00' 3212 :opt_N "-N" '00' 3213 3214 :kw_align "align" 3215 :kw_fill "fill" 3216 :kw_scope "scope" 3217 :kw_endscope "endscope" 3218 :kw_ptrsize "ptrsize" 3219 3220 :str_colon ":" 3221 :str_colon_prog ": hex2pp: " 3222 :str_prog "hex2pp: " 3223 :str_newline " 3224 " 3225 :str_zero "0" 3226 3227 :msg_unknown_arg "unknown argument" '00' 3228 :msg_extra_positional "extra positional argument" '00' 3229 :msg_missing_positional "missing IN or OUT positional argument" '00' 3230 :msg_missing_value "missing value for option" '00' 3231 :msg_open_input "failed to open input file" '00' 3232 :msg_read "failed to read input" '00' 3233 :msg_input_too_big "input too large" '00' 3234 :msg_open_output "failed to open output file" '00' 3235 :msg_write "failed to write output" '00' 3236 :msg_text_overflow "text pool overflow" '00' 3237 :msg_too_many_labels "too many labels" '00' 3238 :msg_duplicate_label "duplicate label" '00' 3239 :msg_undefined_label "undefined label" '00' 3240 :msg_undefined_local "undefined local label" '00' 3241 :msg_unexpected_char "unexpected character" '00' 3242 :msg_unknown_directive "unknown directive" '00' 3243 :msg_scope_overflow ".scope: depth overflow" '00' 3244 :msg_scope_underflow ".endscope: not in a scope" '00' 3245 :msg_scope_unclosed ".scope not closed at end of input" '00' 3246 :msg_align_n ".align: N must be a positive power of two" '00' 3247 :msg_fill_n ".fill: N must be non-negative" '00' 3248 :msg_pattern_too_large "pattern too large" '00' 3249 :msg_byte_lit_bad "byte literal: bad digit count" '00' 3250 :msg_byte_stream_short "byte stream: incomplete digits at end of run" '00' 3251 :msg_sigil_no_label "sigil not followed by label name" '00' 3252 :msg_minus_no_label "'-' must be followed by label name" '00' 3253 :msg_bad_sigil "internal: bad sigil" '00' 3254 :msg_ref_out_of_range "reference out of range" '00' 3255 :msg_name_too_long "name too long" '00' 3256 :msg_empty_name "expected label name" '00' 3257 :msg_empty_directive "expected directive name after '.'" '00' 3258 :msg_expected_decimal "expected decimal integer" '00' 3259 :msg_output_overflow "output overflow" '00' 3260 :msg_bad_long "invalid integer argument" '00' 3261 :msg_ptrsize_bad ".ptrsize: N must be 4 or 8" '00' 3262 :msg_ptrsize_conflict ".ptrsize conflicts with already-used width" '00' 3263 :msg_too_many_fixups "too many references" '00000000' 3264 :msg_scope_history_overflow "scope history overflow" '00' 3265 3266 ## BSS pointer-slot init table. 3267 :bss_init_tbl 3268 &scope_stack_ptr ZERO4 H2_OFF_scope_stack 3269 &name_buf_ptr ZERO4 H2_OFF_name_buf 3270 &label_buf_ptr ZERO4 H2_OFF_label_buf 3271 &other_buf_ptr ZERO4 H2_OFF_other_buf 3272 &pat_buf_ptr ZERO4 H2_OFF_pat_buf 3273 &line_scratch_ptr ZERO4 H2_OFF_line_scratch 3274 &ev_bytes_ptr ZERO4 H2_OFF_ev_bytes 3275 &df_byte_ptr ZERO4 H2_OFF_df_byte 3276 &input_buf_ptr ZERO4 H2_OFF_input_buf 3277 &output_buf_ptr ZERO4 H2_OFF_output_buf 3278 &text_buf_ptr ZERO4 H2_OFF_text_buf 3279 &labels_ptr ZERO4 H2_OFF_labels 3280 &fixups_ptr ZERO4 H2_OFF_fixups 3281 &scope_history_ptr ZERO4 H2_OFF_scope_history 3282 :bss_init_tbl_end 3283 3284 ## --- BSS scalars ---------------------------------------------------------- 3285 3286 :saved_argc 3287 ZERO8 3288 :saved_argv 3289 ZERO8 3290 :arg_idx 3291 ZERO8 3292 :arg_ptr 3293 ZERO8 3294 :input_path 3295 ZERO8 3296 :input_fd 3297 ZERO8 3298 :input_len 3299 ZERO8 3300 :output_path 3301 ZERO8 3302 :output_fd 3303 ZERO8 3304 :output_used 3305 ZERO8 3306 :output_written 3307 ZERO8 3308 :base_address 3309 ZERO8 3310 :byte_mode 3311 ZERO8 3312 :big_endian 3313 ZERO8 3314 :non_executable 3315 ZERO8 3316 :ptrsize 3317 ZERO8 3318 :ptrsize_used 3319 ZERO8 3320 3321 :pass 3322 ZERO8 3323 :ip 3324 ZERO8 3325 :cur_path 3326 ZERO8 3327 :cur_line 3328 ZERO8 3329 :scan_pos 3330 ZERO8 3331 :scan_end 3332 ZERO8 3333 :text_used 3334 ZERO8 3335 :label_count 3336 ZERO8 3337 :fixup_count 3338 ZERO8 3339 :scope_history_used 3340 ZERO8 3341 :scope_depth 3342 ZERO8 3343 :scope_seq 3344 ZERO8 3345 3346 ## name read 3347 :name_len 3348 ZERO8 3349 :name_scope 3350 ZERO8 3351 :nt_c 3352 ZERO8 3353 :rn_out 3354 ZERO8 3355 :rn_max 3356 ZERO8 3357 :rn_n 3358 ZERO8 3359 3360 ## scan_name (returns ptr+len; pointer goes here, length in a0). 3361 :sn_start 3362 ZERO8 3363 3364 ## record_fixup scratch 3365 :rf_name 3366 ZERO8 3367 :rf_name_len 3368 ZERO8 3369 :rf_other 3370 ZERO8 3371 :rf_other_len 3372 ZERO8 3373 :rf_out_off 3374 ZERO8 3375 :rf_ip_after 3376 ZERO8 3377 :rf_idx 3378 ZERO8 3379 :rf_fp 3380 ZERO8 3381 :rf_i 3382 ZERO8 3383 3384 ## patch_fixups scratch 3385 :pf_i 3386 ZERO8 3387 :pf_fp 3388 ZERO8 3389 :pf_t_label 3390 ZERO8 3391 :pf_value 3392 ZERO8 3393 :pf_stack 3394 ZERO8 3395 :pf_depth 3396 ZERO8 3397 3398 ## process_reference scratch (single-pass record path) 3399 :pref_name 3400 ZERO8 3401 :pref_name_len 3402 ZERO8 3403 :pref_other 3404 ZERO8 3405 :pref_other_len 3406 ZERO8 3407 3408 ## decimal read 3409 :rd_val 3410 ZERO8 3411 :rd_saw 3412 ZERO8 3413 3414 ## byte stream 3415 :pbs_acc 3416 ZERO8 3417 :pbs_have 3418 ZERO8 3419 :pbs_c 3420 ZERO8 3421 3422 ## one byte literal 3423 :p1b_out 3424 ZERO8 3425 :p1b_acc 3426 ZERO8 3427 :p1b_have 3428 ZERO8 3429 :p1b_c 3430 ZERO8 3431 3432 ## intern 3433 :intern_src 3434 ZERO8 3435 :intern_len 3436 ZERO8 3437 :intern_dst 3438 ZERO8 3439 :intern_orig 3440 ZERO8 3441 :intern_i 3442 ZERO8 3443 3444 ## name_eq 3445 :ne_label 3446 ZERO8 3447 :ne_src 3448 ZERO8 3449 :ne_len 3450 ZERO8 3451 3452 ## define_label 3453 :dl_src 3454 ZERO8 3455 :dl_len 3456 ZERO8 3457 :dl_scope 3458 ZERO8 3459 :dl_i 3460 ZERO8 3461 :dl_label 3462 ZERO8 3463 :dl_name_off 3464 ZERO8 3465 3466 ## lookup_label_in 3467 :ll_src 3468 ZERO8 3469 :ll_len 3470 ZERO8 3471 :ll_stack 3472 ZERO8 3473 :ll_depth 3474 ZERO8 3475 :ll_d 3476 ZERO8 3477 :ll_sid 3478 ZERO8 3479 :ll_i 3480 ZERO8 3481 :ll_label 3482 ZERO8 3483 3484 ## process_reference / set_sigil_info 3485 :cur_sigil 3486 ZERO8 3487 :pr_width 3488 ZERO8 3489 :pr_is_rel 3490 ZERO8 3491 :pr_lo 3492 ZERO8 3493 :pr_hi 3494 ZERO8 3495 :pr_range_check 3496 ZERO8 3497 :pr_llen 3498 ZERO8 3499 :pr_olen 3500 ZERO8 3501 :pr_has_other 3502 ZERO8 3503 :pr_t_label 3504 ZERO8 3505 :pr_value 3506 ZERO8 3507 3508 ## emit_value / write_value 3509 :ev_value 3510 ZERO8 3511 :ev_width 3512 ZERO8 3513 :ev_lo 3514 ZERO8 3515 :ev_hi 3516 ZERO8 3517 :ev_range_check 3518 ZERO8 3519 :ev_pack_v 3520 ZERO8 3521 :ev_i 3522 ZERO8 3523 :ev_out_off 3524 ZERO8 3525 3526 ## emit_zeros / emit_fill scratch 3527 :emz_n 3528 ZERO8 3529 :emz_off 3530 ZERO8 3531 :emf_n 3532 ZERO8 3533 :emf_b 3534 ZERO8 3535 3536 ## directive scratch 3537 :da_n 3538 ZERO8 3539 :da_has_pat 3540 ZERO8 3541 :da_patlen 3542 ZERO8 3543 :da_pad 3544 ZERO8 3545 :da_i 3546 ZERO8 3547 :df_n 3548 ZERO8 3549 :df_i 3550 ZERO8 3551 :dp_n 3552 ZERO8 3553 3554 ## str/mem 3555 :se_p 3556 ZERO8 3557 :se_q 3558 ZERO8 3559 :se_len 3560 ZERO8 3561 :me_p 3562 ZERO8 3563 :me_q 3564 ZERO8 3565 :me_len 3566 ZERO8 3567 3568 ## parse_long 3569 :pl_p 3570 ZERO8 3571 :pl_val 3572 ZERO8 3573 :pl_neg 3574 ZERO8 3575 3576 ## fatal 3577 :fm_msg 3578 ZERO8 3579 :fm_tmp 3580 ZERO8 3581 3582 ## write_decimal 3583 :wd_v 3584 ZERO8 3585 :wd_pos 3586 ZERO8 3587 3588 ## --- BSS pointer slots ---------------------------------------------------- 3589 :scope_stack_ptr 3590 ZERO8 3591 :name_buf_ptr 3592 ZERO8 3593 :label_buf_ptr 3594 ZERO8 3595 :other_buf_ptr 3596 ZERO8 3597 :pat_buf_ptr 3598 ZERO8 3599 :line_scratch_ptr 3600 ZERO8 3601 :ev_bytes_ptr 3602 ZERO8 3603 :df_byte_ptr 3604 ZERO8 3605 :input_buf_ptr 3606 ZERO8 3607 :output_buf_ptr 3608 ZERO8 3609 :text_buf_ptr 3610 ZERO8 3611 :labels_ptr 3612 ZERO8 3613 :fixups_ptr 3614 ZERO8 3615 :scope_history_ptr 3616 ZERO8 3617 3618 :ELF_end