aarch64.om (19311B)
1 enum { 2 R_FP = 29, 3 R_LR = 30, 4 R_SP = 31, 5 } 6 7 enum { 8 COND_EQ = 0x0, 9 COND_NE = 0x1, 10 COND_GE = 0xa, 11 COND_LT = 0xb, 12 COND_GT = 0xc, 13 COND_LE = 0xd, 14 } 15 16 func aarch64_nop(c: *compiler) { 17 as_emit(c.s, 0x1f); 18 as_emit(c.s, 0x20); 19 as_emit(c.s, 0x03); 20 as_emit(c.s, 0xd5); 21 } 22 23 func aarch64_udf(c: *compiler) { 24 as_emit(c.s, 0x00); 25 as_emit(c.s, 0x00); 26 as_emit(c.s, 0x00); 27 as_emit(c.s, 0x00); 28 } 29 30 func aarch64_svc(c: *compiler) { 31 as_emit(c.s, 0x01); 32 as_emit(c.s, 0x00); 33 as_emit(c.s, 0x00); 34 as_emit(c.s, 0xd4); 35 } 36 37 func aarch64_ldr(c: *compiler, rd: int, rs: int, off: int) { 38 var x: int; 39 x = (0x1f2 << 23) + (1 << 22) + ((off & 0xfff) << 10) + (rs << 5) + rd; 40 as_emit(c.s, x); 41 as_emit(c.s, x >> 8); 42 as_emit(c.s, x >> 16); 43 as_emit(c.s, x >> 24); 44 } 45 46 func aarch64_str(c: *compiler, rd: int, rs: int, off: int) { 47 var x: int; 48 x = (0x1f2 << 23) + ((off & 0xfff) << 10) + (rs << 5) + rd; 49 as_emit(c.s, x); 50 as_emit(c.s, x >> 8); 51 as_emit(c.s, x >> 16); 52 as_emit(c.s, x >> 24); 53 } 54 55 func aarch64_mov(c: *compiler, rd: int, rs: int) { 56 var x: int; 57 if rd == R_SP || rs == R_SP { 58 x = (0x122 << 23) + (rs << 5) + rd; 59 } else { 60 x = (0x154 << 23) + (rs << 16) + (0x1f << 5) + rd; 61 } 62 as_emit(c.s, x); 63 as_emit(c.s, x >> 8); 64 as_emit(c.s, x >> 16); 65 as_emit(c.s, x >> 24); 66 } 67 68 func aarch64_movz(c: *compiler, rd: int, hw: int, x: int) { 69 x = (0x1a5 << 23) + ((hw & 3) << 21) + ((x & 0xffff) << 5) + rd; 70 as_emit(c.s, x); 71 as_emit(c.s, x >> 8); 72 as_emit(c.s, x >> 16); 73 as_emit(c.s, x >> 24); 74 } 75 76 func aarch64_movk(c: *compiler, rd: int, hw: int, x: int) { 77 x = (0x1e5 << 23) + ((hw & 3) << 21) + ((x & 0xffff) << 5) + rd; 78 as_emit(c.s, x); 79 as_emit(c.s, x >> 8); 80 as_emit(c.s, x >> 16); 81 as_emit(c.s, x >> 24); 82 } 83 84 func aarch64_addi(c: *compiler, rd: int, rs: int, imm: int) { 85 var x: int; 86 if imm >= 0 { 87 if imm < 0x1000 { 88 x = 0x91000000 + ((imm & 0xfff) << 10) + (rs << 5) + rd; 89 as_emit(c.s, x); 90 as_emit(c.s, x >> 8); 91 as_emit(c.s, x >> 16); 92 as_emit(c.s, x >> 24); 93 } else if imm < 0x1000000 { 94 x = 0x91000000 + ((imm & 0xfff) << 10) + (rs << 5) + rd; 95 as_emit(c.s, x); 96 as_emit(c.s, x >> 8); 97 as_emit(c.s, x >> 16); 98 as_emit(c.s, x >> 24); 99 x = 0x91400000 + (((imm >> 12) & 0xfff) << 10) + (rd << 5) + rd; 100 as_emit(c.s, x); 101 as_emit(c.s, x >> 8); 102 as_emit(c.s, x >> 16); 103 as_emit(c.s, x >> 24); 104 } else { 105 die("addi overflow"); 106 } 107 } else { 108 if imm > -0x1000 { 109 imm = -imm; 110 x = 0xd1000000 + ((imm & 0xfff) << 10) + (rs << 5) + rd; 111 as_emit(c.s, x); 112 as_emit(c.s, x >> 8); 113 as_emit(c.s, x >> 16); 114 as_emit(c.s, x >> 24); 115 } else if imm > -0x1000000 { 116 imm = -imm; 117 x = 0xd1000000 + ((imm & 0xfff) << 10) + (rs << 5) + rd; 118 as_emit(c.s, x); 119 as_emit(c.s, x >> 8); 120 as_emit(c.s, x >> 16); 121 as_emit(c.s, x >> 24); 122 x = 0xd1400000 + (((imm >> 12) & 0xfff) << 10) + (rd << 5) + rd; 123 as_emit(c.s, x); 124 as_emit(c.s, x >> 8); 125 as_emit(c.s, x >> 16); 126 as_emit(c.s, x >> 24); 127 } else { 128 die("subi overflow"); 129 } 130 } 131 } 132 133 func aarch64_addr(c: *compiler, rd: int, rn: int, rm: int, imm6: int) { 134 var x: int; 135 x = (0x116 << 23) + (rm << 16) + (imm6 << 10) + (rn << 5) + rd; 136 as_emit(c.s, x); 137 as_emit(c.s, x >> 8); 138 as_emit(c.s, x >> 16); 139 as_emit(c.s, x >> 24); 140 } 141 142 func aarch64_ldrb(c: *compiler, rt: int, rn: int) { 143 var x: int; 144 x = 0x39400000 + (rn << 5) + rt; 145 as_emit(c.s, x); 146 as_emit(c.s, x >> 8); 147 as_emit(c.s, x >> 16); 148 as_emit(c.s, x >> 24); 149 } 150 151 func aarch64_strb(c: *compiler, rt: int, rn: int) { 152 var x: int; 153 x = 0x39000000 + (rn << 5) + rt; 154 as_emit(c.s, x); 155 as_emit(c.s, x >> 8); 156 as_emit(c.s, x >> 16); 157 as_emit(c.s, x >> 24); 158 } 159 160 func aarch64_not(c: *compiler, rd: int, rm: int) { 161 var x: int; 162 x = 0xaa2003e0 + (rm << 16) + rd; 163 as_emit(c.s, x); 164 as_emit(c.s, x >> 8); 165 as_emit(c.s, x >> 16); 166 as_emit(c.s, x >> 24); 167 } 168 169 func aarch64_neg(c: *compiler, rd: int, rm: int) { 170 var x: int; 171 x = 0xcb0003e0 + (rm << 16) + rd; 172 as_emit(c.s, x); 173 as_emit(c.s, x >> 8); 174 as_emit(c.s, x >> 16); 175 as_emit(c.s, x >> 24); 176 } 177 178 func aarch64_sub(c: *compiler, rd: int, rn: int, rm: int) { 179 var x: int; 180 x = 0xcb000000 + (rm << 16) + (rn << 5) + rd; 181 as_emit(c.s, x); 182 as_emit(c.s, x >> 8); 183 as_emit(c.s, x >> 16); 184 as_emit(c.s, x >> 24); 185 } 186 187 func aarch64_or(c: *compiler, rd: int, rn: int, rm: int) { 188 var x: int; 189 x = 0xaa000000 + (rm << 16) + (rn << 5) + rd; 190 as_emit(c.s, x); 191 as_emit(c.s, x >> 8); 192 as_emit(c.s, x >> 16); 193 as_emit(c.s, x >> 24); 194 } 195 196 func aarch64_and(c: *compiler, rd: int, rn: int, rm: int) { 197 var x: int; 198 x = 0x8a000000 + (rm << 16) + (rn << 5) + rd; 199 as_emit(c.s, x); 200 as_emit(c.s, x >> 8); 201 as_emit(c.s, x >> 16); 202 as_emit(c.s, x >> 24); 203 } 204 205 func aarch64_xor(c: *compiler, rd: int, rn: int, rm: int) { 206 var x: int; 207 x = 0xca000000 + (rm << 16) + (rn << 5) + rd; 208 as_emit(c.s, x); 209 as_emit(c.s, x >> 8); 210 as_emit(c.s, x >> 16); 211 as_emit(c.s, x >> 24); 212 } 213 214 func aarch64_lsh(c: *compiler, rd: int, rn: int, rm: int) { 215 var x: int; 216 x = 0x9ac02000 + (rm << 16) + (rn << 5) + rd; 217 as_emit(c.s, x); 218 as_emit(c.s, x >> 8); 219 as_emit(c.s, x >> 16); 220 as_emit(c.s, x >> 24); 221 } 222 223 func aarch64_rsh(c: *compiler, rd: int, rn: int, rm: int) { 224 var x: int; 225 x = 0x9ac02400 + (rm << 16) + (rn << 5) + rd; 226 as_emit(c.s, x); 227 as_emit(c.s, x >> 8); 228 as_emit(c.s, x >> 16); 229 as_emit(c.s, x >> 24); 230 } 231 232 func aarch64_mul(c: *compiler, rd: int, rn: int, rm: int) { 233 var x: int; 234 x = 0x9b007c00 + (rm << 16) + (rn << 5) + rd; 235 as_emit(c.s, x); 236 as_emit(c.s, x >> 8); 237 as_emit(c.s, x >> 16); 238 as_emit(c.s, x >> 24); 239 } 240 241 func aarch64_sdiv(c: *compiler, rd: int, rn: int, rm: int) { 242 var x: int; 243 x = 0x9ac00c00 + (rm << 16) + (rn << 5) + rd; 244 as_emit(c.s, x); 245 as_emit(c.s, x >> 8); 246 as_emit(c.s, x >> 16); 247 as_emit(c.s, x >> 24); 248 } 249 250 func aarch64_msub(c: *compiler, rd: int, rn: int, rm: int, ra: int) { 251 var x: int; 252 x = 0x9b008000 + (rm << 16) + (ra << 10) + (rn << 5) + rd; 253 as_emit(c.s, x); 254 as_emit(c.s, x >> 8); 255 as_emit(c.s, x >> 16); 256 as_emit(c.s, x >> 24); 257 } 258 259 func aarch64_cmpi(c: *compiler, rn: int, imm12: int) { 260 var x: int; 261 x = 0xf100001f + ((imm12 & 0xfff) << 10) + (rn << 5); 262 as_emit(c.s, x); 263 as_emit(c.s, x >> 8); 264 as_emit(c.s, x >> 16); 265 as_emit(c.s, x >> 24); 266 } 267 268 func aarch64_cmp(c: *compiler, rn: int, rm: int) { 269 var x: int; 270 x = 0xeb00001f + (rm << 16) + (rn << 5); 271 as_emit(c.s, x); 272 as_emit(c.s, x >> 8); 273 as_emit(c.s, x >> 16); 274 as_emit(c.s, x >> 24); 275 } 276 277 func aarch64_cset(c: *compiler, rd: int, icond: int) { 278 var x: int; 279 x = 0x9a9f07e0 + (icond << 12) + rd; 280 as_emit(c.s, x); 281 as_emit(c.s, x >> 8); 282 as_emit(c.s, x >> 16); 283 as_emit(c.s, x >> 24); 284 } 285 286 func aarch64_bicond(c: *compiler, icond: int, target: *label) { 287 var x: int; 288 x = (0x54 << 24) + (2 << 5) + icond; 289 as_emit(c.s, x); 290 as_emit(c.s, x >> 8); 291 as_emit(c.s, x >> 16); 292 as_emit(c.s, x >> 24); 293 aarch64_udf(c); 294 addfixup(c.s, target, FIXUP_ARM_B); 295 } 296 297 func aarch64_push(c: *compiler, rs: int) { 298 aarch64_addi(c, R_SP, R_SP, -16); 299 aarch64_str(c, rs, R_SP, 0); 300 } 301 302 func aarch64_pop(c: *compiler, rd: int) { 303 aarch64_ldr(c, rd, R_SP, 0); 304 aarch64_addi(c, R_SP, R_SP, 16); 305 } 306 307 func aarch64_ret(c: *compiler) { 308 var x: int; 309 x = 0xd65f03c0; 310 as_emit(c.s, x); 311 as_emit(c.s, x >> 8); 312 as_emit(c.s, x >> 16); 313 as_emit(c.s, x >> 24); 314 } 315 316 func aarch64_jmp(c: *compiler, target: *label) { 317 reserve(c.s, 16); 318 aarch64_udf(c); 319 addfixup(c.s, target, FIXUP_ARM_B); 320 } 321 322 func aarch64_blr(c: *compiler, rs: int) { 323 var x: int; 324 x = 0xd63f0000 + (rs << 5); 325 as_emit(c.s, x); 326 as_emit(c.s, x >> 8); 327 as_emit(c.s, x >> 16); 328 as_emit(c.s, x >> 24); 329 } 330 331 func aarch64_adr(c: *compiler, target: *label) { 332 reserve(c.s, 16); 333 aarch64_udf(c); 334 aarch64_nop(c); 335 addfixup(c.s, target, FIXUP_ARM_ADR); 336 } 337 338 func aarch64_builtin(c: *compiler) { 339 var d: *decl; 340 341 d = find(c, "syscall", nil, 1); 342 if (d.func_defined && !d.func_label.fixed) { 343 fixup_label(c.s, d.func_label); 344 add_symbol(c.s, d.name, d.func_label); 345 aarch64_mov(c, 8, 0); 346 aarch64_mov(c, 0, 1); 347 aarch64_mov(c, 1, 2); 348 aarch64_mov(c, 2, 3); 349 aarch64_mov(c, 3, 4); 350 aarch64_mov(c, 4, 5); 351 aarch64_mov(c, 5, 6); 352 aarch64_svc(c); 353 aarch64_ret(c); 354 } 355 356 d = find(c, "_restorer", nil, 1); 357 if (d.func_defined && !d.func_label.fixed) { 358 fixup_label(c.s, d.func_label); 359 add_symbol(c.s, d.name, d.func_label); 360 aarch64_movz(c, 8, 0, 139); 361 aarch64_svc(c); 362 } 363 } 364 365 func aarch64_output_ir(c: *compiler, d: *decl) { 366 var ic: *irfunc; 367 368 ic = d.func_ir; 369 370 ic.c.filename = ic.filename; 371 ic.c.lineno = ic.lineno; 372 ic.c.colno = ic.colno; 373 ic.s.filename = ic.filename; 374 ic.s.lineno = ic.lineno; 375 376 fixup_label(c.s, d.func_label); 377 add_symbol(c.s, d.name, d.func_label); 378 379 if strcmp(d.name, "_start") == 0 { 380 aarch64_ldr(c, 0, 31, 0); 381 aarch64_addi(c, 1, 31, 8); 382 aarch64_addr(c, 2, 1, 0, 3); 383 aarch64_addi(c, 2, 2, 8); 384 } else if strcmp(d.name, "_kstart") == 0 { 385 die("unimplemented kstart on arm"); 386 } 387 388 // Allocate local variables 389 aarch64_output_irvars(c, ic); 390 391 // Output all blocks 392 aarch64_output_irblock(c, ic, ic.blocks[0]); 393 394 // Clear the marks 395 irreset(ic.blocks[0]); 396 } 397 398 func aarch64_output_irvars(c: *compiler, ic: *irfunc) { 399 var offset: int; 400 var total: int; 401 var size: int; 402 var i: int; 403 var j: int; 404 var v: *irvar; 405 406 // Allocate local variables 407 offset = 16; 408 i = 0; 409 loop { 410 if i == ic.vars_len { 411 break; 412 } 413 414 v = ic.vars[i]; 415 416 if v.dead { 417 i = i + 1; 418 continue; 419 } 420 421 if v.t && v.t.kind != TY_VOID { 422 size = type_sizeof(ic.c, v.t); 423 } else { 424 size = sizeof(i); 425 } 426 427 size = (size + 7) & -8; 428 429 v.offset = offset; 430 431 offset = offset + size; 432 i = i + 1; 433 } 434 435 offset = (offset + 15) & -16; 436 total = offset; 437 ic.frame_size = total; 438 439 // Setup the frame 440 aarch64_addi(c, R_SP, R_SP, -total); 441 aarch64_str(c, R_FP, R_SP, 0); 442 aarch64_str(c, R_LR, R_SP, 1); 443 aarch64_mov(c, R_FP, R_SP); 444 445 // Zero initialize local variables 446 aarch64_movz(c, 16, 0, 0); 447 offset = 16; 448 i = 0; 449 loop { 450 if i == ic.vars_len { 451 break; 452 } 453 454 v = ic.vars[i]; 455 456 if v.dead { 457 i = i + 1; 458 continue; 459 } 460 461 if v.t && v.t.kind != TY_VOID { 462 size = type_sizeof(ic.c, v.t); 463 } else { 464 size = sizeof(i); 465 } 466 467 size = (size + 7) & -8; 468 469 if i < ic.arg_count && i < 8 { 470 aarch64_str(c, i, R_FP, offset >> 3); 471 } else if i < ic.arg_count { 472 aarch64_ldr(c, 17, 29, (total >> 3) + (i - 8)); 473 aarch64_str(c, 17, 31, offset >> 3); 474 } else { 475 j = 0; 476 loop { 477 if j >= size { 478 break; 479 } 480 aarch64_str(c, 16, R_FP, (offset + j) >> 3); 481 j = j + 8; 482 } 483 } 484 485 offset = offset + size; 486 i = i + 1; 487 } 488 489 } 490 491 func aarch64_output_irblock(c: *compiler, ic: *irfunc, b: *irblock) { 492 var op: *irop; 493 var i: int; 494 495 b.mark = 1; 496 497 if !b.done { 498 cdie(ic.c, "no return in function"); 499 } 500 501 fixup_label(ic.s, b.label); 502 503 i = 0; 504 loop { 505 if i == b.ops_len { 506 break; 507 } 508 509 op = b.ops[i]; 510 511 aarch64_output_irstmt(c, ic, b, op); 512 513 i = i + 1; 514 } 515 } 516 517 func aarch64_output_irstmt(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 518 var kind: int; 519 520 ic.c.filename = o.filename; 521 ic.c.lineno = o.lineno; 522 ic.c.colno = o.colno; 523 ic.s.filename = o.filename; 524 ic.s.lineno = o.lineno; 525 526 kind = o.kind; 527 if kind == IOP_STORE { 528 // Evaluate the address 529 if o.a.kind == IOP_LOAD { 530 aarch64_output_irexpr(c, ic, b, o.a.a); 531 } else if o.a.kind == IOP_VAR { 532 aarch64_addi(c, 16, R_FP, ic.vars[o.a.n].offset); 533 } else { 534 die("invalid store"); 535 } 536 537 aarch64_push(c, 16); 538 539 // Evaluate the value 540 aarch64_output_irexpr(c, ic, b, o.b); 541 542 aarch64_pop(c, 17); 543 544 // Execute the store 545 if o.t.kind == TY_BYTE { 546 aarch64_strb(c, 16, 17); 547 } else if type_isprim(o.t) { 548 aarch64_str(c, 16, 17, 0); 549 } else { 550 cdie(ic.c, "invalid store"); 551 } 552 } else if kind == IOP_RETVAL { 553 // Do nothing 554 } else if kind == IOP_ARG { 555 // Do nothing 556 } else if kind == IOP_CALL { 557 // Allocate some space for the arguments 558 if o.n > 8 { 559 aarch64_addi(c, R_SP, R_SP, -((o.n + 1) & -2) * sizeof(kind)); 560 } 561 562 // Setup arguments 563 aarch64_output_irargs(c, ic, b, o); 564 565 // Call the function 566 aarch64_output_ircall(c, ic, b, o.a); 567 568 // Release space reserved for the arguments 569 if o.n > 8 { 570 aarch64_addi(c, R_SP, R_SP, ((o.n + 1) & -2) * sizeof(kind)); 571 } 572 573 // Save the return value 574 aarch64_output_irretval(c, ic, b, o); 575 576 if b.out.mark { 577 aarch64_jmp(c, b.out.label); 578 } else { 579 aarch64_output_irblock(c, ic, b.out); 580 } 581 return; 582 } else if kind == IOP_JUMP { 583 if b.out.mark { 584 // Jump to an already output block 585 aarch64_jmp(c, b.out.label); 586 } else { 587 // Output a new block 588 aarch64_output_irblock(c, ic, b.out); 589 } 590 return; 591 } else if kind == IOP_BRANCH { 592 // Evaluate the condition and branch if zero 593 aarch64_output_irexpr(c, ic, b, o.a); 594 595 aarch64_cmpi(c, 16, 0); 596 aarch64_bicond(c, COND_NE, b.alt.label); 597 598 // Then jump to the output 599 if b.out.mark { 600 aarch64_jmp(c, b.out.label); 601 } else { 602 aarch64_output_irblock(c, ic, b.out); 603 } 604 605 // And if we haven't already, output the alt branch 606 if !b.alt.mark { 607 aarch64_output_irblock(c, ic, b.alt); 608 } 609 610 return; 611 } else if kind == IOP_RETURN { 612 // Evaluate the return expression and return 613 if o.a { 614 aarch64_output_irexpr(c, ic, b, o.a); 615 } 616 617 aarch64_mov(c, 0, 16); 618 aarch64_ldr(c, R_LR, R_FP, 1); 619 aarch64_ldr(c, R_FP, R_FP, 0); 620 aarch64_addi(c, R_SP, R_SP, ic.frame_size); 621 aarch64_ret(c); 622 } else { 623 // Evaluate and discard the result 624 aarch64_output_irexpr(c, ic, b, o); 625 } 626 } 627 628 func aarch64_output_irargs(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 629 var i: int; 630 var op: *irop; 631 632 i = 0; 633 loop { 634 if i == b.ops_len { 635 return; 636 } 637 638 op = b.ops[i]; 639 if op.kind == IOP_ARG { 640 // Compute the value 641 aarch64_output_irexpr(c, ic, b, op.a); 642 643 if op.n < 8 { 644 aarch64_mov(c, op.n, 16); 645 } else { 646 // Stack argument 647 aarch64_str(c, 16, R_SP, op.n - 8); 648 } 649 } 650 651 i = i + 1; 652 } 653 } 654 655 func aarch64_output_irretval(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 656 var i: int; 657 var op: *irop; 658 659 // Find the retval place 660 op = nil; 661 i = 0; 662 loop { 663 if i == b.ops_len { 664 return; 665 } 666 667 op = b.ops[i]; 668 if op.kind == IOP_RETVAL { 669 break; 670 } 671 672 i = i + 1; 673 } 674 675 // Do nothing if there was no return value 676 if op.t.kind == TY_VOID { 677 return; 678 } 679 680 // Compute the address 681 if op.a.kind == IOP_LOAD { 682 aarch64_output_irexpr(c, ic, b, op.a.a); 683 } else if op.a.kind == IOP_VAR { 684 aarch64_addi(c, 16, R_FP, ic.vars[op.a.n].offset); 685 } else { 686 die("invalid store"); 687 } 688 689 // Execute the store 690 if op.t.kind == TY_BYTE { 691 aarch64_strb(c, 0, 16); 692 } else if type_isprim(op.t) { 693 aarch64_str(c, 0, 16, 0); 694 } else { 695 cdie(ic.c, "invalid store"); 696 } 697 } 698 699 func aarch64_output_irstr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 700 var s: *label; 701 s = as_blob(ic.s, o.s, o.slen + 1); 702 aarch64_adr(c, s); 703 } 704 705 func aarch64_output_irfuncptr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 706 var d: *decl; 707 d = find(ic.c, o.s, nil, 0); 708 if !d || !d.func_defined { 709 cdie(ic.c, "no such function"); 710 } 711 aarch64_adr(c, d.func_label); 712 } 713 714 func aarch64_output_ircall(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 715 aarch64_output_irexpr(c, ic, b, o); 716 aarch64_blr(c, 16); 717 } 718 719 func aarch64_output_irexpr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 720 var kind: int; 721 722 if !o { 723 cdie(ic.c, "no expr"); 724 } 725 726 kind = o.kind; 727 if kind == IOP_VAR { 728 aarch64_ldr(c, 16, R_FP, ic.vars[o.n].offset >> 3); 729 } else if kind == IOP_VARREF { 730 aarch64_addi(c, 16, R_FP, ic.vars[o.n].offset); 731 } else if kind == IOP_FUNC { 732 aarch64_output_irfuncptr(c, ic, b, o); 733 } else if kind == IOP_CONST { 734 aarch64_movz(c, 16, 0, o.n); 735 if o.n < 0 || o.n >= (1 << 16) { 736 aarch64_movk(c, 16, 1, o.n >> 16); 737 } 738 if o.n < 0 || o.n >= (1 << 32) { 739 aarch64_movk(c, 16, 2, o.n >> 32); 740 } 741 if o.n < 0 || o.n >= (1 << 48) { 742 aarch64_movk(c, 16, 3, o.n >> 48); 743 } 744 } else if kind == IOP_STR { 745 aarch64_output_irstr(c, ic, b, o); 746 } else if kind == IOP_LOAD { 747 aarch64_output_irexpr(c, ic, b, o.a); 748 if o.t.kind == TY_BYTE { 749 aarch64_ldrb(c, 16, 16); 750 } else if type_isprim(o.t) { 751 aarch64_ldr(c, 16, 16, 0); 752 } else { 753 cdie(ic.c, "invalid load"); 754 } 755 } else if kind == IOP_NEG { 756 aarch64_output_irexpr(c, ic, b, o.a); 757 aarch64_neg(c, 16, 16); 758 } else if kind == IOP_NOT { 759 aarch64_output_irexpr(c, ic, b, o.a); 760 aarch64_not(c, 16, 16); 761 } else if kind == IOP_ADD { 762 aarch64_output_irexpr(c, ic, b, o.b); 763 aarch64_push(c, 16); 764 aarch64_output_irexpr(c, ic, b, o.a); 765 aarch64_pop(c, 17); 766 aarch64_addr(c, 16, 17, 16, 0); 767 } else if kind == IOP_AND { 768 aarch64_output_irexpr(c, ic, b, o.b); 769 aarch64_push(c, 16); 770 aarch64_output_irexpr(c, ic, b, o.a); 771 aarch64_pop(c, 17); 772 aarch64_and(c, 16, 17, 16); 773 } else if kind == IOP_OR { 774 aarch64_output_irexpr(c, ic, b, o.b); 775 aarch64_push(c, 16); 776 aarch64_output_irexpr(c, ic, b, o.a); 777 aarch64_pop(c, 17); 778 aarch64_or(c, 16, 17, 16); 779 } else if kind == IOP_XOR { 780 aarch64_output_irexpr(c, ic, b, o.b); 781 aarch64_push(c, 16); 782 aarch64_output_irexpr(c, ic, b, o.a); 783 aarch64_pop(c, 17); 784 aarch64_xor(c, 16, 17, 16); 785 } else if kind == IOP_DIV { 786 aarch64_output_irexpr(c, ic, b, o.b); 787 aarch64_push(c, 16); 788 aarch64_output_irexpr(c, ic, b, o.a); 789 aarch64_pop(c, 17); 790 aarch64_sdiv(c, 16, 16, 17); 791 } else if kind == IOP_MOD { 792 aarch64_output_irexpr(c, ic, b, o.b); 793 aarch64_push(c, 16); 794 aarch64_output_irexpr(c, ic, b, o.a); 795 aarch64_pop(c, 17); 796 aarch64_sdiv(c, 9, 16, 17); 797 aarch64_msub(c, 16, 9, 17, 16); 798 } else if kind == IOP_LSH { 799 aarch64_output_irexpr(c, ic, b, o.b); 800 aarch64_push(c, 16); 801 aarch64_output_irexpr(c, ic, b, o.a); 802 aarch64_pop(c, 17); 803 aarch64_lsh(c, 16, 16, 17); 804 } else if kind == IOP_RSH { 805 aarch64_output_irexpr(c, ic, b, o.b); 806 aarch64_push(c, 16); 807 aarch64_output_irexpr(c, ic, b, o.a); 808 aarch64_pop(c, 17); 809 aarch64_rsh(c, 16, 16, 17); 810 } else if kind == IOP_MUL { 811 aarch64_output_irexpr(c, ic, b, o.b); 812 aarch64_push(c, 16); 813 aarch64_output_irexpr(c, ic, b, o.a); 814 aarch64_pop(c, 17); 815 aarch64_mul(c, 16, 17, 16); 816 } else if kind == IOP_SUB { 817 aarch64_output_irexpr(c, ic, b, o.b); 818 aarch64_push(c, 16); 819 aarch64_output_irexpr(c, ic, b, o.a); 820 aarch64_pop(c, 17); 821 aarch64_sub(c, 16, 16, 17); 822 } else if kind == IOP_EQ { 823 aarch64_output_irexpr(c, ic, b, o.b); 824 aarch64_push(c, 16); 825 aarch64_output_irexpr(c, ic, b, o.a); 826 aarch64_pop(c, 17); 827 aarch64_cmp(c, 16, 17); 828 aarch64_cset(c, 16, COND_NE); 829 } else if kind == IOP_NE { 830 aarch64_output_irexpr(c, ic, b, o.b); 831 aarch64_push(c, 16); 832 aarch64_output_irexpr(c, ic, b, o.a); 833 aarch64_pop(c, 17); 834 aarch64_cmp(c, 16, 17); 835 aarch64_cset(c, 16, COND_EQ); 836 } else if kind == IOP_GT { 837 aarch64_output_irexpr(c, ic, b, o.b); 838 aarch64_push(c, 16); 839 aarch64_output_irexpr(c, ic, b, o.a); 840 aarch64_pop(c, 17); 841 aarch64_cmp(c, 16, 17); 842 aarch64_cset(c, 16, COND_LE); 843 } else if kind == IOP_GE { 844 aarch64_output_irexpr(c, ic, b, o.b); 845 aarch64_push(c, 16); 846 aarch64_output_irexpr(c, ic, b, o.a); 847 aarch64_pop(c, 17); 848 aarch64_cmp(c, 16, 17); 849 aarch64_cset(c, 16, COND_LT); 850 } else if kind == IOP_LT { 851 aarch64_output_irexpr(c, ic, b, o.b); 852 aarch64_push(c, 16); 853 aarch64_output_irexpr(c, ic, b, o.a); 854 aarch64_pop(c, 17); 855 aarch64_cmp(c, 16, 17); 856 aarch64_cset(c, 16, COND_GE); 857 } else if kind == IOP_LE { 858 aarch64_output_irexpr(c, ic, b, o.b); 859 aarch64_push(c, 16); 860 aarch64_output_irexpr(c, ic, b, o.a); 861 aarch64_pop(c, 17); 862 aarch64_cmp(c, 16, 17); 863 aarch64_cset(c, 16, COND_GT); 864 } else { 865 cdie(ic.c, "invalid op"); 866 } 867 }