P1-riscv64.M1pp (14933B)
1 # P1-riscv64.M1pp -- P1 riscv64 backend expressed in m1macro. 2 3 # Width hooks consumed by the portable P1pp support library. 4 %macro p1_word_bytes() 5 8 6 %endm 7 %macro p1_word_bits() 8 64 9 %endm 10 %macro p1_word_shift() 11 3 12 %endm 13 %macro p1_scheme_heap_bytes() 14 0x10000000 15 %endm 16 %macro p1_waitid_status_off() 17 24 18 %endm 19 # 20 # Mirrors p1/P1-aarch64.M1pp; same macro surface, different encodings. 21 # Native register picks follow docs/P1.md's 64-bit mapping table. 22 # 23 # Hidden backend regs: 24 # br = t6 (x31) -- dedicated branch-target mechanism 25 # scratch = t5 (x30) -- per-expansion scratch, never live across ops 26 # save0 = t4 (x29) -- transient across SYSCALL only 27 # save1 = t3 (x28) 28 # save2 = a6 (x16) 29 # saved_fp = fp (x8) -- used by ENTER/ERET to capture caller sp 30 # a7 = x17 -- Linux riscv64 syscall-number slot 31 # a4 = x14 -- syscall arg4 slot 32 # a5 = x15 -- syscall arg5 slot 33 34 # ---- Native register numbers -------------------------------------------- 35 36 %macro rv_reg_a0() 37 10 38 %endm 39 %macro rv_reg_a1() 40 11 41 %endm 42 %macro rv_reg_a2() 43 12 44 %endm 45 %macro rv_reg_a3() 46 13 47 %endm 48 %macro rv_reg_a4() 49 14 50 %endm 51 %macro rv_reg_a5() 52 15 53 %endm 54 %macro rv_reg_a6() 55 16 56 %endm 57 %macro rv_reg_a7() 58 17 59 %endm 60 %macro rv_reg_t0() 61 5 62 %endm 63 %macro rv_reg_t1() 64 6 65 %endm 66 %macro rv_reg_t2() 67 7 68 %endm 69 %macro rv_reg_s0() 70 9 71 %endm 72 %macro rv_reg_s1() 73 18 74 %endm 75 %macro rv_reg_s2() 76 19 77 %endm 78 %macro rv_reg_s3() 79 20 80 %endm 81 %macro rv_reg_sp() 82 2 83 %endm 84 %macro rv_reg_zero() 85 0 86 %endm 87 %macro rv_reg_ra() 88 1 89 %endm 90 %macro rv_reg_fp() 91 8 92 %endm 93 %macro rv_reg_br() 94 31 95 %endm 96 %macro rv_reg_scratch() 97 30 98 %endm 99 %macro rv_reg_save0() 100 29 101 %endm 102 %macro rv_reg_save1() 103 28 104 %endm 105 %macro rv_reg_save2() 106 16 107 %endm 108 109 %macro rv_reg(r) 110 %rv_reg_##r 111 %endm 112 113 %macro rv_is_sp_a0() 114 0 115 %endm 116 %macro rv_is_sp_a1() 117 0 118 %endm 119 %macro rv_is_sp_a2() 120 0 121 %endm 122 %macro rv_is_sp_a3() 123 0 124 %endm 125 %macro rv_is_sp_a4() 126 0 127 %endm 128 %macro rv_is_sp_a5() 129 0 130 %endm 131 %macro rv_is_sp_a6() 132 0 133 %endm 134 %macro rv_is_sp_a7() 135 0 136 %endm 137 %macro rv_is_sp_t0() 138 0 139 %endm 140 %macro rv_is_sp_t1() 141 0 142 %endm 143 %macro rv_is_sp_t2() 144 0 145 %endm 146 %macro rv_is_sp_s0() 147 0 148 %endm 149 %macro rv_is_sp_s1() 150 0 151 %endm 152 %macro rv_is_sp_s2() 153 0 154 %endm 155 %macro rv_is_sp_s3() 156 0 157 %endm 158 %macro rv_is_sp_sp() 159 1 160 %endm 161 %macro rv_is_sp_zero() 162 0 163 %endm 164 %macro rv_is_sp_ra() 165 0 166 %endm 167 %macro rv_is_sp_fp() 168 0 169 %endm 170 %macro rv_is_sp_br() 171 0 172 %endm 173 %macro rv_is_sp_scratch() 174 0 175 %endm 176 %macro rv_is_sp_save0() 177 0 178 %endm 179 %macro rv_is_sp_save1() 180 0 181 %endm 182 %macro rv_is_sp_save2() 183 0 184 %endm 185 186 %macro rv_is_sp(r) 187 %rv_is_sp_##r 188 %endm 189 190 # ---- Low-level instruction encoders -------------------------------------- 191 192 # R-type: funct7[31:25] rs2[24:20] rs1[19:15] funct3[14:12] rd[11:7] opcode[6:0] 193 %macro rv_r_type(base, rd, ra, rb) 194 %((| base (<< %rv_reg(rb) 20) (<< %rv_reg(ra) 15) (<< %rv_reg(rd) 7))) 195 %endm 196 197 # I-type: imm[31:20] rs1[19:15] funct3[14:12] rd[11:7] opcode[6:0] 198 %macro rv_i_type(base, rd, ra, imm12) 199 %((| base (<< (& imm12 0xFFF) 20) (<< %rv_reg(ra) 15) (<< %rv_reg(rd) 7))) 200 %endm 201 202 # S-type: imm[31:25] rs2[24:20] rs1[19:15] funct3[14:12] imm[11:7] opcode[6:0] 203 %macro rv_s_type(base, rs, ra, imm12) 204 %((| base (<< (& (>> imm12 5) 0x7F) 25) (<< %rv_reg(rs) 20) (<< %rv_reg(ra) 15) (<< (& imm12 0x1F) 7))) 205 %endm 206 207 # B-type: imm[12|10:5] rs2 rs1 funct3 imm[4:1|11] opcode. 12-bit signed, 208 # imm[0] always 0. For the hardcoded skip-over-jalr we only need a fixed 209 # positive offset (8 bytes = 2 insns), so inline the resulting bit pattern. 210 %macro rv_b_type_skip8(base, ra, rb) 211 # imm value 8 -> imm[11:0] = 0000_0000_0100. Bits of encoded imm: 212 # imm[12]=0, imm[10:5]=0, imm[4:1]=0100 (=4), imm[11]=0. 213 # encoded bits: [31:25]=0, [11:7]= (imm[4:1] << 1) | imm[11] = (4<<1)|0 = 8. 214 %((| base (<< %rv_reg(rb) 20) (<< %rv_reg(ra) 15) (<< 8 7))) 215 %endm 216 217 %macro rv_addi(rd, ra, imm12) 218 %rv_i_type(0x00000013, rd, ra, imm12) 219 %endm 220 221 # rv_addi with arbitrary 64-bit signed immediate. Falls back to a 222 # 64-bit literal load into `scratch` followed by an R-type ADD when the 223 # immediate doesn't fit in ADDI's 12-bit signed field. `scratch` (t5/x30) 224 # is per-expansion and never live across ops, so clobbering it is safe. 225 %macro rv_addi_any(rd, ra, imm) 226 %select((>= imm -2048), 227 %select((<= imm 2047), 228 %rv_addi(rd, ra, imm), 229 %rv_lit64_prefix(scratch) 230 $(imm) 231 %rv_r_type(0x00000033, rd, ra, scratch)), 232 %rv_lit64_prefix(scratch) 233 $(imm) 234 %rv_r_type(0x00000033, rd, ra, scratch)) 235 %endm 236 237 %macro rv_ld(rd, ra, imm12) 238 %rv_i_type(0x00003003, rd, ra, imm12) 239 %endm 240 241 %macro rv_sd(rs, ra, imm12) 242 %rv_s_type(0x00003023, rs, ra, imm12) 243 %endm 244 245 %macro rv_lbu(rd, ra, imm12) 246 %rv_i_type(0x00004003, rd, ra, imm12) 247 %endm 248 249 %macro rv_sb(rs, ra, imm12) 250 %rv_s_type(0x00000023, rs, ra, imm12) 251 %endm 252 253 %macro rv_lwu(rd, ra, imm12) 254 %rv_i_type(0x00006003, rd, ra, imm12) 255 %endm 256 257 # Load/store with arbitrary signed offset. The native I-type/S-type 258 # imm12 covers [-2048, 2047]; past that, materialize the offset in 259 # scratch (t5/x30), compute scratch = ra + scratch via R-type ADD, and 260 # issue the load/store with offset 0. Callers must not pass scratch as 261 # `ra` or `rs` — the materialize would clobber it before the address 262 # computation reads it. 263 %macro rv_ld_any(rd, ra, off) 264 %select((>= off -2048), 265 %select((<= off 2047), 266 %rv_ld(rd, ra, off), 267 %rv_lit64_prefix(scratch) 268 $(off) 269 %rv_r_type(0x00000033, scratch, ra, scratch) 270 %rv_ld(rd, scratch, 0)), 271 %rv_lit64_prefix(scratch) 272 $(off) 273 %rv_r_type(0x00000033, scratch, ra, scratch) 274 %rv_ld(rd, scratch, 0)) 275 %endm 276 277 %macro rv_sd_any(rs, ra, off) 278 %select((>= off -2048), 279 %select((<= off 2047), 280 %rv_sd(rs, ra, off), 281 %rv_lit64_prefix(scratch) 282 $(off) 283 %rv_r_type(0x00000033, scratch, ra, scratch) 284 %rv_sd(rs, scratch, 0)), 285 %rv_lit64_prefix(scratch) 286 $(off) 287 %rv_r_type(0x00000033, scratch, ra, scratch) 288 %rv_sd(rs, scratch, 0)) 289 %endm 290 291 %macro rv_lbu_any(rd, ra, off) 292 %select((>= off -2048), 293 %select((<= off 2047), 294 %rv_lbu(rd, ra, off), 295 %rv_lit64_prefix(scratch) 296 $(off) 297 %rv_r_type(0x00000033, scratch, ra, scratch) 298 %rv_lbu(rd, scratch, 0)), 299 %rv_lit64_prefix(scratch) 300 $(off) 301 %rv_r_type(0x00000033, scratch, ra, scratch) 302 %rv_lbu(rd, scratch, 0)) 303 %endm 304 305 %macro rv_sb_any(rs, ra, off) 306 %select((>= off -2048), 307 %select((<= off 2047), 308 %rv_sb(rs, ra, off), 309 %rv_lit64_prefix(scratch) 310 $(off) 311 %rv_r_type(0x00000033, scratch, ra, scratch) 312 %rv_sb(rs, scratch, 0)), 313 %rv_lit64_prefix(scratch) 314 $(off) 315 %rv_r_type(0x00000033, scratch, ra, scratch) 316 %rv_sb(rs, scratch, 0)) 317 %endm 318 319 %macro rv_mov_rr(dst, src) 320 %rv_addi(dst, src, 0) 321 %endm 322 323 %macro rv_slli(rd, ra, shamt) 324 %((| 0x00001013 (<< (& shamt 0x3F) 20) (<< %rv_reg(ra) 15) (<< %rv_reg(rd) 7))) 325 %endm 326 327 %macro rv_srli(rd, ra, shamt) 328 %((| 0x00005013 (<< (& shamt 0x3F) 20) (<< %rv_reg(ra) 15) (<< %rv_reg(rd) 7))) 329 %endm 330 331 %macro rv_srai(rd, ra, shamt) 332 %((| 0x40005013 (<< (& shamt 0x3F) 20) (<< %rv_reg(ra) 15) (<< %rv_reg(rd) 7))) 333 %endm 334 335 %macro rv_jalr(rd, rs, imm12) 336 %((| 0x00000067 (<< (& imm12 0xFFF) 20) (<< %rv_reg(rs) 15) (<< %rv_reg(rd) 7))) 337 %endm 338 339 %macro rv_ecall() 340 %(0x00000073) 341 %endm 342 343 # 64-bit literal-pool prefix for LI: 344 # auipc rd, 0 pc-relative base 345 # ld rd, 12(rd) load 8-byte literal from pc+12 346 # jal x0, 12 skip 12 bytes (literal + pad, =8 bytes of literal). 347 # The 8 bytes that follow in source become the literal. 348 %macro rv_lit64_prefix(rd) 349 %((| 0x00000017 (<< %rv_reg(rd) 7))) 350 %((| 0x00C03003 (<< %rv_reg(rd) 15) (<< %rv_reg(rd) 7))) 351 %(0x00C0006F) 352 %endm 353 354 # 32-bit literal-pool prefix for LA / LA_BR: 355 # auipc rd, 0 356 # lwu rd, 12(rd) zero-extend 4-byte literal from pc+12 357 # jal x0, 8 skip 8 bytes (=4 of insn slot? no, literal + align). 358 # lwu zero-extends into the full 64-bit register, so 4 bytes is enough for 359 # any address in the stage0 layout. Lets source use `&label` directly 360 # without padding to 8 bytes. 361 %macro rv_lit32_prefix(rd) 362 %((| 0x00000017 (<< %rv_reg(rd) 7))) 363 %((| 0x00C06003 (<< %rv_reg(rd) 15) (<< %rv_reg(rd) 7))) 364 %(0x0080006F) 365 %endm 366 367 # Memory op fallback: offset outside signed 12-bit range. Load the 368 # offset into `scratch` via LUI+ADDI dance? For stage0 programs the 369 # curated offsets stay inside -2048..2047, so fall back is unused; 370 # still emit a defensive failure to flag any future overflow. 371 # (In practice none of the LD/ST off values in p1_gen.py exceed the 372 # signed 12-bit range, so no fallback path is wired in here.) 373 374 # ---- P1 register-register op lowering ----------------------------------- 375 376 %macro rv_rrr_ADD(rd, ra, rb) 377 %rv_r_type(0x00000033, rd, ra, rb) 378 %endm 379 %macro rv_rrr_SUB(rd, ra, rb) 380 %rv_r_type(0x40000033, rd, ra, rb) 381 %endm 382 %macro rv_rrr_AND(rd, ra, rb) 383 %rv_r_type(0x00007033, rd, ra, rb) 384 %endm 385 %macro rv_rrr_OR(rd, ra, rb) 386 %rv_r_type(0x00006033, rd, ra, rb) 387 %endm 388 %macro rv_rrr_XOR(rd, ra, rb) 389 %rv_r_type(0x00004033, rd, ra, rb) 390 %endm 391 %macro rv_rrr_SHL(rd, ra, rb) 392 %rv_r_type(0x00001033, rd, ra, rb) 393 %endm 394 %macro rv_rrr_SHR(rd, ra, rb) 395 %rv_r_type(0x00005033, rd, ra, rb) 396 %endm 397 %macro rv_rrr_SAR(rd, ra, rb) 398 %rv_r_type(0x40005033, rd, ra, rb) 399 %endm 400 %macro rv_rrr_MUL(rd, ra, rb) 401 %rv_r_type(0x02000033, rd, ra, rb) 402 %endm 403 %macro rv_rrr_DIV(rd, ra, rb) 404 %rv_r_type(0x02004033, rd, ra, rb) 405 %endm 406 %macro rv_rrr_UDIV(rd, ra, rb) 407 %rv_r_type(0x02005033, rd, ra, rb) 408 %endm 409 %macro rv_rrr_REM(rd, ra, rb) 410 %rv_r_type(0x02006033, rd, ra, rb) 411 %endm 412 %macro rv_rrr_UREM(rd, ra, rb) 413 %rv_r_type(0x02007033, rd, ra, rb) 414 %endm 415 416 %macro rv_rrr_op(op, rd, ra, rb) 417 %rv_rrr_##op(rd, ra, rb) 418 %endm 419 420 # ---- P1 operation lowering ----------------------------------------------- 421 422 %macro p1_li(rd, imm) 423 %rv_lit64_prefix(rd) 424 $(imm) 425 %endm 426 427 %macro p1_la(rd) 428 %rv_lit32_prefix(rd) 429 %endm 430 431 %macro p1_labr() 432 %rv_lit32_prefix(br) 433 %endm 434 435 %macro p1_mov(rd, rs) 436 %select((= %rv_is_sp(rs) 1), 437 %rv_addi(rd, sp, 16), 438 %rv_mov_rr(rd, rs)) 439 %endm 440 441 %macro p1_rrr(op, rd, ra, rb) 442 %rv_rrr_op(op, rd, ra, rb) 443 %endm 444 445 %macro p1_addi(rd, ra, imm) 446 %rv_addi_any(rd, ra, imm) 447 %endm 448 449 # Logical-immediate fallback: when imm fits the I-type's 12-bit signed 450 # field, emit the native ANDI/ORI; otherwise materialize the immediate 451 # in scratch (t5/x30) and use the R-type AND/OR. funct3=7 (AND) or 6 452 # (OR) is shared between the I-type (opcode 0x13) and R-type 453 # (opcode 0x33) encodings. 454 %macro rv_logi_any(rd, ra, imm, base_i, base_r) 455 %select((>= imm -2048), 456 %select((<= imm 2047), 457 %rv_i_type(base_i, rd, ra, imm), 458 %rv_lit64_prefix(scratch) 459 $(imm) 460 %rv_r_type(base_r, rd, ra, scratch)), 461 %rv_lit64_prefix(scratch) 462 $(imm) 463 %rv_r_type(base_r, rd, ra, scratch)) 464 %endm 465 466 %macro p1_logi_ANDI(rd, ra, imm) 467 %rv_logi_any(rd, ra, imm, 0x00007013, 0x00007033) 468 %endm 469 %macro p1_logi_ORI(rd, ra, imm) 470 %rv_logi_any(rd, ra, imm, 0x00006013, 0x00006033) 471 %endm 472 %macro p1_logi(op, rd, ra, imm) 473 %p1_logi_##op(rd, ra, imm) 474 %endm 475 476 %macro p1_shifti_SHLI(rd, ra, imm) 477 %rv_slli(rd, ra, imm) 478 %endm 479 %macro p1_shifti_SHRI(rd, ra, imm) 480 %rv_srli(rd, ra, imm) 481 %endm 482 %macro p1_shifti_SARI(rd, ra, imm) 483 %rv_srai(rd, ra, imm) 484 %endm 485 %macro p1_shifti(op, rd, ra, imm) 486 %p1_shifti_##op(rd, ra, imm) 487 %endm 488 489 %macro p1_mem_LD(rt, rn, off) 490 %rv_ld_any(rt, rn, off) 491 %endm 492 %macro p1_mem_ST(rt, rn, off) 493 %rv_sd_any(rt, rn, off) 494 %endm 495 %macro p1_mem_LB(rt, rn, off) 496 %rv_lbu_any(rt, rn, off) 497 %endm 498 %macro p1_mem_SB(rt, rn, off) 499 %rv_sb_any(rt, rn, off) 500 %endm 501 %macro p1_mem(op, rt, rn, off) 502 %select((= %rv_is_sp(rn) 1), 503 %p1_mem_##op(rt, rn, (+ off 16)), 504 %p1_mem_##op(rt, rn, off)) 505 %endm 506 507 %macro p1_ldarg(rd, slot) 508 %rv_ld(rd, sp, 8) 509 %rv_ld_any(rd, rd, (+ 16 (* 8 slot))) 510 %endm 511 512 %macro p1_b() 513 %rv_jalr(zero, br, 0) 514 %endm 515 516 %macro p1_br(rs) 517 %rv_jalr(zero, rs, 0) 518 %endm 519 520 %macro p1_call() 521 %rv_jalr(ra, br, 0) 522 %endm 523 524 %macro p1_callr(rs) 525 %rv_jalr(ra, rs, 0) 526 %endm 527 528 %macro p1_ret() 529 %rv_jalr(zero, ra, 0) 530 %endm 531 532 %macro p1_eret() 533 %rv_ld(ra, sp, 0) 534 %rv_ld(fp, sp, 8) 535 %rv_mov_rr(sp, fp) 536 %rv_jalr(zero, ra, 0) 537 %endm 538 539 %macro p1_tail() 540 %rv_ld(ra, sp, 0) 541 %rv_ld(fp, sp, 8) 542 %rv_mov_rr(sp, fp) 543 %rv_jalr(zero, br, 0) 544 %endm 545 546 %macro p1_tailr(rs) 547 %rv_ld(ra, sp, 0) 548 %rv_ld(fp, sp, 8) 549 %rv_mov_rr(sp, fp) 550 %rv_jalr(zero, rs, 0) 551 %endm 552 553 # Conditional branch: emit a skip-taken native branch over the `%p1_b` 554 # fall-through, then the jalr(br) that takes the P1 branch. Each native 555 # B-type here uses the inverted condition with a +8 offset so the `jalr` 556 # two insns below is the taken target. 557 %macro p1_condb_BEQ(ra, rb) 558 %rv_b_type_skip8(0x00001063, ra, rb) 559 %p1_b 560 %endm 561 %macro p1_condb_BNE(ra, rb) 562 %rv_b_type_skip8(0x00000063, ra, rb) 563 %p1_b 564 %endm 565 %macro p1_condb_BLT(ra, rb) 566 %rv_b_type_skip8(0x00005063, ra, rb) 567 %p1_b 568 %endm 569 %macro p1_condb_BLTU(ra, rb) 570 %rv_b_type_skip8(0x00007063, ra, rb) 571 %p1_b 572 %endm 573 %macro p1_condb(op, ra, rb) 574 %p1_condb_##op(ra, rb) 575 %endm 576 577 %macro p1_condbz_BEQZ(ra) 578 %rv_b_type_skip8(0x00001063, ra, zero) 579 %p1_b 580 %endm 581 %macro p1_condbz_BNEZ(ra) 582 %rv_b_type_skip8(0x00000063, ra, zero) 583 %p1_b 584 %endm 585 %macro p1_condbz_BLTZ(ra) 586 %rv_b_type_skip8(0x00005063, ra, zero) 587 %p1_b 588 %endm 589 %macro p1_condbz(op, ra) 590 %p1_condbz_##op(ra) 591 %endm 592 593 %macro p1_enter(size) 594 %rv_addi_any(sp, sp, (- 0 (& (+ (+ 16 size) 15) -16))) 595 %rv_sd(ra, sp, 0) 596 %rv_addi_any(fp, sp, (& (+ (+ 16 size) 15) -16)) 597 %rv_sd(fp, sp, 8) 598 %endm 599 600 %macro p1_entry() 601 # :_start stub per the P1 program-entry model. Linux riscv64 puts argc 602 # at [sp] and argv starting at [sp+8], matching the generic SysV entry 603 # stack. Load argc into a0, compute &argv[0] into a1, call p1_main under 604 # the one-word direct-result convention, then issue sys_exit with the 605 # returned status. 606 :_start 607 %rv_ld(a0, sp, 0) 608 %rv_addi(a1, sp, 8) 609 %rv_lit32_prefix(br) 610 &p1_main 611 %rv_jalr(ra, br, 0) 612 %rv_addi(a7, zero, 93) 613 %rv_ecall 614 %endm 615 616 %macro p1_syscall() 617 # P1: a0=number, a1,a2,a3,t0,s0,s1 = args 0..5. 618 # Linux riscv64: a7=number, a0..a5 = args 0..5, return in a0. 619 # SYSCALL clobbers only P1 a0; restore a1/a2/a3 after ecall. 620 # Native a4/a5 (x14/x15) aren't P1-exposed; we use them as syscall arg 621 # slots and don't need to save them. 622 %rv_mov_rr(save0, a1) 623 %rv_mov_rr(save1, a2) 624 %rv_mov_rr(save2, a3) 625 %rv_mov_rr(a7, a0) 626 %rv_mov_rr(a0, save0) 627 %rv_mov_rr(a1, save1) 628 %rv_mov_rr(a2, save2) 629 %rv_mov_rr(a3, t0) 630 %rv_mov_rr(a4, s0) 631 %rv_mov_rr(a5, s1) 632 %rv_ecall 633 %rv_mov_rr(a1, save0) 634 %rv_mov_rr(a2, save1) 635 %rv_mov_rr(a3, save2) 636 %endm 637 638 # ---- Linux riscv64 syscall numbers --------------------------------------- 639 # Each macro returns the syscall number as an integer atom so callers can 640 # use it inside expressions (e.g. `%li(a0, %sys_write)`). 641 642 %macro p1_sys_read() 643 63 644 %endm 645 %macro p1_sys_write() 646 64 647 %endm 648 %macro p1_sys_close() 649 57 650 %endm 651 %macro p1_sys_openat() 652 56 653 %endm 654 %macro p1_sys_exit() 655 93 656 %endm 657 %macro p1_sys_clone() 658 220 659 %endm 660 %macro p1_sys_execve() 661 221 662 %endm 663 %macro p1_sys_spawn() 664 1024 665 %endm 666 %macro p1_sys_waitid() 667 95 668 %endm 669 %macro p1_sys_lseek() 670 62 671 %endm 672 %macro p1_sys_lseek_wrapper() 673 %mov(a3, a2) 674 %mov(a2, a1) 675 %mov(a1, a0) 676 %li(a0, %p1_sys_lseek) 677 %syscall 678 %ret 679 %endm 680 %macro p1_sys_brk() 681 214 682 %endm 683 %macro p1_sys_unlinkat() 684 35 685 %endm