riscv64.om (17588B)
1 //x1 = link register 2 //x2 = stack pointer 3 //x3 = global pointer 4 //x4 = thread pointer 5 //x8 = frame pointer 6 //x5-x7, x28-x31 = temporary 7 //x8-x9, x18-x27 = callee-saved 8 //x10-x17 = arguments 9 10 // Use x31 to build far jumps and large constants 11 12 //R = func7[31:25] rs2[24:20] rs1[19:15] func3[14:12] rd[11:7] op[6:0] 13 func riscv64_emitr(c: *compiler, op: int, fn: int, rd: int, rs1: int, rs2: int) { 14 var x: int; 15 x = ((fn >> 3) << 25) + (rs2 << 20) + (rs1 << 15) + ((fn & 7) << 12) + (rd << 7) + op; 16 as_emit(c.s, x); 17 as_emit(c.s, x >> 8); 18 as_emit(c.s, x >> 16); 19 as_emit(c.s, x >> 24); 20 } 21 22 //I = imm12[31:20] rs1[19:15] func3[14:12] rd[11:7] op[6:0] 23 func riscv64_emiti(c: *compiler, op: int, fn: int, rd: int, rs1: int, imm: int) { 24 var x: int; 25 26 if imm < -(1 << 11) || imm >= (1 << 11) { 27 die("riscv64_emiti: immediate overflow"); 28 } 29 30 x = (imm << 20) + (rs1 << 15) + (fn << 12) + (rd << 7) + op; 31 as_emit(c.s, x); 32 as_emit(c.s, x >> 8); 33 as_emit(c.s, x >> 16); 34 as_emit(c.s, x >> 24); 35 } 36 37 //S = imm7[31:25] rs2[24:20] rs1[19:15] func3[14:12] i5[11:7] op[6:0] 38 func riscv64_emits(c: *compiler, op: int, fn: int, rs1: int, rs2: int, imm: int) { 39 var x: int; 40 41 if imm < -(1 << 11) || imm >= (1 << 11) { 42 die("riscv64_emits immediate overflow"); 43 } 44 45 x = ((imm >> 5) << 25) + (rs2 << 20) + (rs1 << 15) + (fn << 12) + ((imm & 31) << 7) + op; 46 as_emit(c.s, x); 47 as_emit(c.s, x >> 8); 48 as_emit(c.s, x >> 16); 49 as_emit(c.s, x >> 24); 50 } 51 52 func riscv64_lui(c: *compiler, rd: int, imm: int) { 53 var x: int; 54 55 if imm < -0x80000 || imm >= 0x80000 { 56 die("riscv64_lui immediate overflow"); 57 } 58 59 x = (imm << 12) + (rd << 7) + 0b0110111; 60 as_emit(c.s, x); 61 as_emit(c.s, x >> 8); 62 as_emit(c.s, x >> 16); 63 as_emit(c.s, x >> 24); 64 } 65 66 func riscv64_li(c: *compiler, rd: int, imm: int) { 67 var x0: int; 68 var x1: int; 69 var x2: int; 70 var x3: int; 71 if imm >= -2048 && imm < 2048 { 72 riscv64_addi(c, rd, 0, imm); 73 } else { 74 x0 = -(imm & 0x800) | (imm & 0xfff); 75 imm = (imm - x0) >> 12; 76 x1 = -(imm & 0x80000) | (imm & 0xfffff); 77 imm = (imm - x1) >> 20; 78 x2 = -(imm & 0x800) | (imm & 0xfff); 79 imm = (imm - x2) >> 12; 80 x3 = -(imm & 0x80000) | (imm & 0xfffff); 81 82 riscv64_lui(c, 31, x3); 83 riscv64_addi(c, 31, 31, x2); 84 riscv64_slli(c, rd, 31, 32); 85 riscv64_lui(c, 31, x1); 86 riscv64_addi(c, 31, 31, x0); 87 riscv64_add(c, rd, rd, 31); 88 } 89 } 90 91 func riscv64_addli(c: *compiler, rd: int, rs: int, imm: int) { 92 if rs == 0 { 93 riscv64_li(c, rd, imm); 94 } else { 95 riscv64_li(c, 31, imm); 96 riscv64_add(c, rd, rs, 31); 97 } 98 } 99 100 func riscv64_addi(c: *compiler, rd: int, rs: int, imm: int) { 101 riscv64_emiti(c, 0b0010011, 0b000, rd, rs, imm); 102 } 103 104 func riscv64_ld(c: *compiler, rd: int, rs: int, imm: int) { 105 riscv64_emiti(c, 0b0000011, 0b011, rd, rs, imm); 106 } 107 108 func riscv64_lbu(c: *compiler, rd: int, rs: int, imm: int) { 109 riscv64_emiti(c, 0b0000011, 0b100, rd, rs, imm); 110 } 111 112 func riscv64_sd(c: *compiler, rs: int, rd: int, imm: int) { 113 riscv64_emits(c, 0b0100011, 0b011, rd, rs, imm); 114 } 115 116 func riscv64_sb(c: *compiler, rs: int, rd: int, imm: int) { 117 riscv64_emits(c, 0b0100011, 0b000, rd, rs, imm); 118 } 119 120 func riscv64_nop(c: *compiler) { 121 riscv64_emiti(c, 0b0010011, 0b000, 0, 0, 0); 122 } 123 124 func riscv64_ecall(c: *compiler) { 125 riscv64_emiti(c, 0b1110011, 0b000, 0, 0, 0); 126 } 127 128 func riscv64_ebreak(c: *compiler) { 129 riscv64_emiti(c, 0b1110011, 0b000, 0, 0, 1); 130 } 131 132 func riscv64_unimp(c: *compiler) { 133 riscv64_emiti(c, 0b1110011, 0b001, 0, 0, 3072); 134 } 135 136 func riscv64_mv(c: *compiler, rd: int, rs: int) { 137 riscv64_emiti(c, 0b0010011, 0b000, rd, rs, 0); 138 } 139 140 func riscv64_jalr(c: *compiler, rd: int, rs: int) { 141 riscv64_emiti(c, 0b1100111, 0b000, rd, rs, 0); 142 } 143 144 func riscv64_ret(c: *compiler) { 145 riscv64_emiti(c, 0b1100111, 0b000, 0, 1, 0); 146 } 147 148 func riscv64_slli(c: *compiler, rd: int, rs: int, shift: int) { 149 riscv64_emiti(c, 0b0010011, 0b001, rd, rs, shift); 150 } 151 152 func riscv64_add(c: *compiler, rd: int, rs1: int, rs2: int) { 153 riscv64_emitr(c, 0b0110011, 0b000, rd, rs1, rs2); 154 } 155 156 func riscv64_sub(c: *compiler, rd: int, rs1: int, rs2: int) { 157 riscv64_emitr(c, 0b0110011, 0b0100000000, rd, rs1, rs2); 158 } 159 160 func riscv64_and(c: *compiler, rd: int, rs1: int, rs2: int) { 161 riscv64_emitr(c, 0b0110011, 0b0000000111, rd, rs1, rs2); 162 } 163 164 func riscv64_or(c: *compiler, rd: int, rs1: int, rs2: int) { 165 riscv64_emitr(c, 0b0110011, 0b0000000110, rd, rs1, rs2); 166 } 167 168 func riscv64_xor(c: *compiler, rd: int, rs1: int, rs2: int) { 169 riscv64_emitr(c, 0b0110011, 0b0000000100, rd, rs1, rs2); 170 } 171 172 func riscv64_not(c: *compiler, rd: int, rs1: int) { 173 riscv64_emiti(c, 0b0010011, 0b100, rd, rs1, -1); 174 } 175 176 func riscv64_xor1(c: *compiler, rd: int, rs1: int) { 177 riscv64_emiti(c, 0b0010011, 0b100, rd, rs1, 1); 178 } 179 180 func riscv64_sll(c: *compiler, rd: int, rs1: int, rs2: int) { 181 riscv64_emitr(c, 0b0110011, 0b0000000001, rd, rs1, rs2); 182 } 183 184 func riscv64_srl(c: *compiler, rd: int, rs1: int, rs2: int) { 185 riscv64_emitr(c, 0b0110011, 0b0000000101, rd, rs1, rs2); 186 } 187 188 func riscv64_slt(c: *compiler, rd: int, rs1: int, rs2: int) { 189 riscv64_emitr(c, 0b0110011, 0b0000000010, rd, rs1, rs2); 190 } 191 192 func riscv64_sltu(c: *compiler, rd: int, rs1: int, rs2: int) { 193 riscv64_emitr(c, 0b0110011, 0b0000000011, rd, rs1, rs2); 194 } 195 196 func riscv64_seqz(c: *compiler, rd: int, rs1: int) { 197 riscv64_emiti(c, 0b0010011, 0b0000000011, rd, rs1, 1); 198 } 199 200 func riscv64_div(c: *compiler, rd: int, rs1: int, rs2: int) { 201 riscv64_emitr(c, 0b0110011, 0b0000001100, rd, rs1, rs2); 202 } 203 204 func riscv64_rem(c: *compiler, rd: int, rs1: int, rs2: int) { 205 riscv64_emitr(c, 0b0110011, 0b0000001110, rd, rs1, rs2); 206 } 207 208 func riscv64_mul(c: *compiler, rd: int, rs1: int, rs2: int) { 209 riscv64_emitr(c, 0b0110011, 0b0000001000, rd, rs1, rs2); 210 } 211 212 func riscv64_j(c: *compiler, target: *label) { 213 reserve(c.s, 16); 214 riscv64_ebreak(c); 215 riscv64_nop(c); 216 addfixup(c.s, target, FIXUP_RISCV_J); 217 } 218 219 func riscv64_bz(c: *compiler, rs: int, target: *label) { 220 riscv64_emits(c, 0b1100011, 0b001, rs, 0, 12); 221 riscv64_j(c, target); 222 } 223 224 func riscv64_push(c: *compiler, rs: int) { 225 riscv64_addi(c, 2, 2, -8); 226 riscv64_sd(c, rs, 2, 0); 227 } 228 229 func riscv64_pop(c: *compiler, rd: int) { 230 riscv64_ld(c, rd, 2, 0); 231 riscv64_addi(c, 2, 2, 8); 232 } 233 234 func riscv64_pcrel(c: *compiler, rd: int, target: *label) { 235 reserve(c.s, 16); 236 riscv64_ebreak(c); 237 riscv64_addi(c, 5, 5, 0); 238 addfixup(c.s, target, FIXUP_RISCV_AUIPC); 239 } 240 241 func riscv64_builtin(c: *compiler) { 242 var d: *decl; 243 244 d = find(c, "syscall", nil, 1); 245 if (d.func_defined && !d.func_label.fixed) { 246 fixup_label(c.s, d.func_label); 247 add_symbol(c.s, d.name, d.func_label); 248 riscv64_mv(c, 17, 10); 249 riscv64_mv(c, 10, 11); 250 riscv64_mv(c, 11, 12); 251 riscv64_mv(c, 12, 13); 252 riscv64_mv(c, 13, 14); 253 riscv64_mv(c, 14, 15); 254 riscv64_mv(c, 15, 16); 255 riscv64_ecall(c); 256 riscv64_ret(c); 257 } 258 259 d = find(c, "_restorer", nil, 1); 260 if (d.func_defined && !d.func_label.fixed) { 261 fixup_label(c.s, d.func_label); 262 add_symbol(c.s, d.name, d.func_label); 263 riscv64_addi(c, 17, 0, 139); 264 riscv64_ecall(c); 265 } 266 } 267 268 func riscv64_output_ir(c: *compiler, d: *decl) { 269 var ic: *irfunc; 270 271 ic = d.func_ir; 272 273 ic.c.filename = ic.filename; 274 ic.c.lineno = ic.lineno; 275 ic.c.colno = ic.colno; 276 ic.s.filename = ic.filename; 277 ic.s.lineno = ic.lineno; 278 279 fixup_label(c.s, d.func_label); 280 add_symbol(c.s, d.name, d.func_label); 281 282 if strcmp(d.name, "_start") == 0 { 283 riscv64_ld(c, 10, 2, 0); 284 riscv64_addi(c, 11, 2, 8); 285 riscv64_slli(c, 12, 10, 3); 286 riscv64_addi(c, 12, 12, 8); 287 riscv64_add(c, 12, 11, 12); 288 } else if strcmp(d.name, "_kstart") == 0 { 289 die("unimplemented kstart on arm"); 290 } 291 292 // Allocate local variables 293 riscv64_output_irvars(c, ic); 294 295 // Output all blocks 296 riscv64_output_irblock(c, ic, ic.blocks[0]); 297 298 // Clear the marks 299 irreset(ic.blocks[0]); 300 } 301 302 func riscv64_output_irvars(c: *compiler, ic: *irfunc) { 303 var offset: int; 304 var total: int; 305 var size: int; 306 var i: int; 307 var j: int; 308 var v: *irvar; 309 310 // Allocate local variables 311 offset = 16; 312 i = 0; 313 loop { 314 if i == ic.vars_len { 315 break; 316 } 317 318 v = ic.vars[i]; 319 320 if v.dead { 321 i = i + 1; 322 continue; 323 } 324 325 if v.t && v.t.kind != TY_VOID { 326 size = type_sizeof(ic.c, v.t); 327 } else { 328 size = sizeof(i); 329 } 330 331 size = (size + 7) & -8; 332 333 v.offset = offset; 334 335 offset = offset + size; 336 i = i + 1; 337 } 338 339 offset = (offset + 15) & -16; 340 total = offset; 341 ic.frame_size = total; 342 343 // Setup the frame 344 riscv64_addli(c, 2, 2, -total); 345 riscv64_sd(c, 8, 2, 0); 346 riscv64_sd(c, 1, 2, 8); 347 riscv64_mv(c, 8, 2); 348 349 // Zero initialize local variables 350 offset = 16; 351 i = 0; 352 loop { 353 if i == ic.vars_len { 354 break; 355 } 356 357 v = ic.vars[i]; 358 359 if v.dead { 360 i = i + 1; 361 continue; 362 } 363 364 if v.t && v.t.kind != TY_VOID { 365 size = type_sizeof(ic.c, v.t); 366 } else { 367 size = sizeof(i); 368 } 369 370 size = (size + 7) & -8; 371 372 if i < ic.arg_count && i < 8 { 373 riscv64_addli(c, 6, 8, offset); 374 riscv64_sd(c, 10 + i, 6, 0); 375 } else if i < ic.arg_count { 376 riscv64_addli(c, 6, 8, total + (i - 8)); 377 riscv64_ld(c, 5, 6, 0); 378 riscv64_addli(c, 6, 8, offset); 379 riscv64_sd(c, 5, 6, 0); 380 } else { 381 j = 0; 382 loop { 383 if j >= size { 384 break; 385 } 386 riscv64_addli(c, 6, 8, offset + j); 387 riscv64_sd(c, 0, 6, 0); 388 j = j + 8; 389 } 390 } 391 392 offset = offset + size; 393 i = i + 1; 394 } 395 } 396 397 func riscv64_output_irblock(c: *compiler, ic: *irfunc, b: *irblock) { 398 var op: *irop; 399 var i: int; 400 401 b.mark = 1; 402 403 if !b.done { 404 cdie(ic.c, "no return in function"); 405 } 406 407 fixup_label(ic.s, b.label); 408 409 i = 0; 410 loop { 411 if i == b.ops_len { 412 break; 413 } 414 415 op = b.ops[i]; 416 417 riscv64_output_irstmt(c, ic, b, op); 418 419 i = i + 1; 420 } 421 } 422 423 func riscv64_output_irstmt(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 424 var kind: int; 425 426 ic.c.filename = o.filename; 427 ic.c.lineno = o.lineno; 428 ic.c.colno = o.colno; 429 ic.s.filename = o.filename; 430 ic.s.lineno = o.lineno; 431 432 kind = o.kind; 433 if kind == IOP_STORE { 434 // Evaluate the address 435 if o.a.kind == IOP_LOAD { 436 riscv64_output_irexpr(c, ic, b, o.a.a); 437 } else if o.a.kind == IOP_VAR { 438 riscv64_addli(c, 5, 8, ic.vars[o.a.n].offset); 439 } else { 440 die("invalid store"); 441 } 442 443 riscv64_push(c, 5); 444 445 // Evaluate the value 446 riscv64_output_irexpr(c, ic, b, o.b); 447 448 riscv64_pop(c, 6); 449 450 // Execute the store 451 if o.t.kind == TY_BYTE { 452 riscv64_sb(c, 5, 6, 0); 453 } else if type_isprim(o.t) { 454 riscv64_sd(c, 5, 6, 0); 455 } else { 456 cdie(ic.c, "invalid store"); 457 } 458 } else if kind == IOP_RETVAL { 459 // Do nothing 460 } else if kind == IOP_ARG { 461 // Do nothing 462 } else if kind == IOP_CALL { 463 // Allocate some space for the arguments 464 if o.n > 8 { 465 riscv64_addli(c, 2, 2, -((o.n + 1) & -2) * sizeof(kind)); 466 } 467 468 // Setup arguments 469 riscv64_output_irargs(c, ic, b, o); 470 471 // Call the function 472 riscv64_output_ircall(c, ic, b, o.a); 473 474 // Release space reserved for the arguments 475 if o.n > 8 { 476 riscv64_addli(c, 2, 2, ((o.n + 1) & -2) * sizeof(kind)); 477 } 478 479 // Save the return value 480 riscv64_output_irretval(c, ic, b, o); 481 482 if b.out.mark { 483 riscv64_j(c, b.out.label); 484 } else { 485 riscv64_output_irblock(c, ic, b.out); 486 } 487 return; 488 } else if kind == IOP_JUMP { 489 if b.out.mark { 490 // Jump to an already output block 491 riscv64_j(c, b.out.label); 492 } else { 493 // Output a new block 494 riscv64_output_irblock(c, ic, b.out); 495 } 496 return; 497 } else if kind == IOP_BRANCH { 498 // Evaluate the condition and branch if zero 499 riscv64_output_irexpr(c, ic, b, o.a); 500 501 riscv64_bz(c, 5, b.alt.label); 502 503 // Then jump to the output 504 if b.out.mark { 505 riscv64_j(c, b.out.label); 506 } else { 507 riscv64_output_irblock(c, ic, b.out); 508 } 509 510 // And if we haven't already, output the alt branch 511 if !b.alt.mark { 512 riscv64_output_irblock(c, ic, b.alt); 513 } 514 515 return; 516 } else if kind == IOP_RETURN { 517 // Evaluate the return expression and return 518 if o.a { 519 riscv64_output_irexpr(c, ic, b, o.a); 520 } 521 522 riscv64_mv(c, 10, 5); 523 riscv64_ld(c, 1, 8, 8); 524 riscv64_ld(c, 8, 8, 0); 525 riscv64_addli(c, 2, 2, ic.frame_size); 526 riscv64_ret(c); 527 } else { 528 // Evaluate and discard the result 529 riscv64_output_irexpr(c, ic, b, o); 530 } 531 } 532 533 func riscv64_output_irargs(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 534 var i: int; 535 var op: *irop; 536 537 i = 0; 538 loop { 539 if i == b.ops_len { 540 return; 541 } 542 543 op = b.ops[i]; 544 if op.kind == IOP_ARG { 545 // Compute the value 546 riscv64_output_irexpr(c, ic, b, op.a); 547 548 if op.n < 8 { 549 riscv64_mv(c, 10 + op.n, 5); 550 } else { 551 // Stack argument 552 riscv64_addli(c, 6, 2, (op.n - 8) * 8); 553 riscv64_sd(c, 5, 6, 0); 554 } 555 } 556 557 i = i + 1; 558 } 559 } 560 561 func riscv64_output_irretval(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 562 var i: int; 563 var op: *irop; 564 565 // Find the retval place 566 op = nil; 567 i = 0; 568 loop { 569 if i == b.ops_len { 570 return; 571 } 572 573 op = b.ops[i]; 574 if op.kind == IOP_RETVAL { 575 break; 576 } 577 578 i = i + 1; 579 } 580 581 // Do nothing if there was no return value 582 if op.t.kind == TY_VOID { 583 return; 584 } 585 586 // Compute the address 587 if op.a.kind == IOP_LOAD { 588 riscv64_output_irexpr(c, ic, b, op.a.a); 589 } else if op.a.kind == IOP_VAR { 590 riscv64_addli(c, 5, 8, ic.vars[op.a.n].offset); 591 } else { 592 die("invalid store"); 593 } 594 595 // Execute the store 596 if op.t.kind == TY_BYTE { 597 riscv64_sb(c, 10, 5, 0); 598 } else if type_isprim(op.t) { 599 riscv64_sd(c, 10, 5, 0); 600 } else { 601 cdie(ic.c, "invalid store"); 602 } 603 } 604 605 func riscv64_output_irstr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 606 var s: *label; 607 s = as_blob(ic.s, o.s, o.slen + 1); 608 riscv64_pcrel(c, 5, s); 609 } 610 611 func riscv64_output_irfuncptr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 612 var d: *decl; 613 d = find(ic.c, o.s, nil, 0); 614 if !d || !d.func_defined { 615 cdie(ic.c, "no such function"); 616 } 617 riscv64_pcrel(c, 5, d.func_label); 618 } 619 620 func riscv64_output_ircall(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 621 riscv64_output_irexpr(c, ic, b, o); 622 riscv64_jalr(c, 1, 5); 623 } 624 625 func riscv64_output_irexpr(c: *compiler, ic: *irfunc, b: *irblock, o: *irop) { 626 var kind: int; 627 628 if !o { 629 cdie(ic.c, "no expr"); 630 } 631 632 kind = o.kind; 633 if kind == IOP_VAR { 634 riscv64_addli(c, 6, 8, ic.vars[o.n].offset); 635 riscv64_ld(c, 5, 6, 0); 636 } else if kind == IOP_VARREF { 637 riscv64_addli(c, 5, 8, ic.vars[o.n].offset); 638 } else if kind == IOP_FUNC { 639 riscv64_output_irfuncptr(c, ic, b, o); 640 } else if kind == IOP_CONST { 641 riscv64_addli(c, 5, 0, o.n); 642 } else if kind == IOP_STR { 643 riscv64_output_irstr(c, ic, b, o); 644 } else if kind == IOP_LOAD { 645 riscv64_output_irexpr(c, ic, b, o.a); 646 if o.t.kind == TY_BYTE { 647 riscv64_lbu(c, 5, 5, 0); 648 } else if type_isprim(o.t) { 649 riscv64_ld(c, 5, 5, 0); 650 } else { 651 cdie(ic.c, "invalid load"); 652 } 653 } else if kind == IOP_NEG { 654 riscv64_output_irexpr(c, ic, b, o.a); 655 riscv64_sub(c, 5, 0, 5); 656 } else if kind == IOP_NOT { 657 riscv64_output_irexpr(c, ic, b, o.a); 658 riscv64_not(c, 5, 5); 659 } else if kind == IOP_ADD { 660 riscv64_output_irexpr(c, ic, b, o.b); 661 riscv64_push(c, 5); 662 riscv64_output_irexpr(c, ic, b, o.a); 663 riscv64_pop(c, 6); 664 riscv64_add(c, 5, 5, 6); 665 } else if kind == IOP_AND { 666 riscv64_output_irexpr(c, ic, b, o.b); 667 riscv64_push(c, 5); 668 riscv64_output_irexpr(c, ic, b, o.a); 669 riscv64_pop(c, 6); 670 riscv64_and(c, 5, 5, 6); 671 } else if kind == IOP_OR { 672 riscv64_output_irexpr(c, ic, b, o.b); 673 riscv64_push(c, 5); 674 riscv64_output_irexpr(c, ic, b, o.a); 675 riscv64_pop(c, 6); 676 riscv64_or(c, 5, 5, 6); 677 } else if kind == IOP_XOR { 678 riscv64_output_irexpr(c, ic, b, o.b); 679 riscv64_push(c, 5); 680 riscv64_output_irexpr(c, ic, b, o.a); 681 riscv64_pop(c, 6); 682 riscv64_xor(c, 5, 5, 6); 683 } else if kind == IOP_DIV { 684 riscv64_output_irexpr(c, ic, b, o.b); 685 riscv64_push(c, 5); 686 riscv64_output_irexpr(c, ic, b, o.a); 687 riscv64_pop(c, 6); 688 riscv64_div(c, 5, 5, 6); 689 } else if kind == IOP_MOD { 690 riscv64_output_irexpr(c, ic, b, o.b); 691 riscv64_push(c, 5); 692 riscv64_output_irexpr(c, ic, b, o.a); 693 riscv64_pop(c, 6); 694 riscv64_rem(c, 5, 5, 6); 695 } else if kind == IOP_LSH { 696 riscv64_output_irexpr(c, ic, b, o.b); 697 riscv64_push(c, 5); 698 riscv64_output_irexpr(c, ic, b, o.a); 699 riscv64_pop(c, 6); 700 riscv64_sll(c, 5, 5, 6); 701 } else if kind == IOP_RSH { 702 riscv64_output_irexpr(c, ic, b, o.b); 703 riscv64_push(c, 5); 704 riscv64_output_irexpr(c, ic, b, o.a); 705 riscv64_pop(c, 6); 706 riscv64_srl(c, 5, 5, 6); 707 } else if kind == IOP_MUL { 708 riscv64_output_irexpr(c, ic, b, o.b); 709 riscv64_push(c, 5); 710 riscv64_output_irexpr(c, ic, b, o.a); 711 riscv64_pop(c, 6); 712 riscv64_mul(c, 5, 5, 6); 713 } else if kind == IOP_SUB { 714 riscv64_output_irexpr(c, ic, b, o.b); 715 riscv64_push(c, 5); 716 riscv64_output_irexpr(c, ic, b, o.a); 717 riscv64_pop(c, 6); 718 riscv64_sub(c, 5, 5, 6); 719 } else if kind == IOP_EQ { 720 riscv64_output_irexpr(c, ic, b, o.b); 721 riscv64_push(c, 5); 722 riscv64_output_irexpr(c, ic, b, o.a); 723 riscv64_pop(c, 6); 724 riscv64_sub(c, 5, 5, 6); 725 riscv64_seqz(c, 5, 5); 726 } else if kind == IOP_NE { 727 riscv64_output_irexpr(c, ic, b, o.b); 728 riscv64_push(c, 5); 729 riscv64_output_irexpr(c, ic, b, o.a); 730 riscv64_pop(c, 6); 731 riscv64_sub(c, 5, 5, 6); 732 riscv64_sltu(c, 5, 0, 5); 733 } else if kind == IOP_GT { 734 riscv64_output_irexpr(c, ic, b, o.b); 735 riscv64_push(c, 5); 736 riscv64_output_irexpr(c, ic, b, o.a); 737 riscv64_pop(c, 6); 738 riscv64_slt(c, 5, 6, 5); 739 } else if kind == IOP_GE { 740 riscv64_output_irexpr(c, ic, b, o.b); 741 riscv64_push(c, 5); 742 riscv64_output_irexpr(c, ic, b, o.a); 743 riscv64_pop(c, 6); 744 riscv64_slt(c, 5, 5, 6); 745 riscv64_xor1(c, 5, 5); 746 } else if kind == IOP_LT { 747 riscv64_output_irexpr(c, ic, b, o.b); 748 riscv64_push(c, 5); 749 riscv64_output_irexpr(c, ic, b, o.a); 750 riscv64_pop(c, 6); 751 riscv64_slt(c, 5, 5, 6); 752 } else if kind == IOP_LE { 753 riscv64_output_irexpr(c, ic, b, o.b); 754 riscv64_push(c, 5); 755 riscv64_output_irexpr(c, ic, b, o.a); 756 riscv64_pop(c, 6); 757 riscv64_slt(c, 5, 6, 5); 758 riscv64_xor1(c, 5, 5); 759 } else { 760 cdie(ic.c, "invalid op"); 761 } 762 }