Skip to content

Commit 9b668be

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm] Add the RISC-V Zcb extension.
TEST=ci, local qemu Change-Id: Ic9d7a1019e389a25817390dbb2f2f41daab579a4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394621 Reviewed-by: Alexander Aprelev <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent e841793 commit 9b668be

File tree

6 files changed

+995
-349
lines changed

6 files changed

+995
-349
lines changed

runtime/vm/compiler/assembler/assembler_riscv.cc

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,11 @@ void MicroAssembler::lb(Register rd, Address addr) {
273273

274274
void MicroAssembler::lh(Register rd, Address addr) {
275275
ASSERT(Supports(RV_I));
276+
if (Supports(RV_Zcb) && IsCRdp(rd) && IsCRs1p(addr.base()) &&
277+
IsCMem2Imm(addr.offset())) {
278+
c_lh(rd, addr);
279+
return;
280+
}
276281
EmitIType(addr.offset(), addr.base(), LH, rd, LOAD);
277282
}
278283

@@ -293,21 +298,41 @@ void MicroAssembler::lw(Register rd, Address addr) {
293298

294299
void MicroAssembler::lbu(Register rd, Address addr) {
295300
ASSERT(Supports(RV_I));
301+
if (Supports(RV_Zcb) && IsCRdp(rd) && IsCRs1p(addr.base()) &&
302+
IsCMem1Imm(addr.offset())) {
303+
c_lbu(rd, addr);
304+
return;
305+
}
296306
EmitIType(addr.offset(), addr.base(), LBU, rd, LOAD);
297307
}
298308

299309
void MicroAssembler::lhu(Register rd, Address addr) {
300310
ASSERT(Supports(RV_I));
311+
if (Supports(RV_Zcb) && IsCRdp(rd) && IsCRs1p(addr.base()) &&
312+
IsCMem2Imm(addr.offset())) {
313+
c_lhu(rd, addr);
314+
return;
315+
}
301316
EmitIType(addr.offset(), addr.base(), LHU, rd, LOAD);
302317
}
303318

304319
void MicroAssembler::sb(Register rs2, Address addr) {
305320
ASSERT(Supports(RV_I));
321+
if (Supports(RV_Zcb) && IsCRs2p(rs2) && IsCRs1p(addr.base()) &&
322+
IsCMem1Imm(addr.offset())) {
323+
c_sb(rs2, addr);
324+
return;
325+
}
306326
EmitSType(addr.offset(), rs2, addr.base(), SB, STORE);
307327
}
308328

309329
void MicroAssembler::sh(Register rs2, Address addr) {
310330
ASSERT(Supports(RV_I));
331+
if (Supports(RV_Zcb) && IsCRs2p(rs2) && IsCRs1p(addr.base()) &&
332+
IsCMem2Imm(addr.offset())) {
333+
c_sh(rs2, addr);
334+
return;
335+
}
311336
EmitSType(addr.offset(), rs2, addr.base(), SH, STORE);
312337
}
313338

@@ -371,6 +396,12 @@ void MicroAssembler::sltiu(Register rd, Register rs1, intptr_t imm) {
371396

372397
void MicroAssembler::xori(Register rd, Register rs1, intptr_t imm) {
373398
ASSERT(Supports(RV_I));
399+
if (Supports(RV_Zcb)) {
400+
if ((rd == rs1) && IsCRs1p(rs1) && (imm == -1)) {
401+
c_not(rd, rs1);
402+
return;
403+
}
404+
}
374405
EmitIType(imm, rs1, XORI, rd, OPIMM);
375406
}
376407

@@ -386,6 +417,12 @@ void MicroAssembler::andi(Register rd, Register rs1, intptr_t imm) {
386417
c_andi(rd, rs1, imm);
387418
return;
388419
}
420+
if (Supports(RV_Zcb)) {
421+
if ((rd == rs1) && IsCRs1p(rs1) && (imm == 0xFF)) {
422+
c_zextb(rd, rs1);
423+
return;
424+
}
425+
}
389426
}
390427
EmitIType(imm, rs1, ANDI, rd, OPIMM);
391428
}
@@ -702,6 +739,16 @@ void MicroAssembler::sraw(Register rd, Register rs1, Register rs2) {
702739

703740
void MicroAssembler::mul(Register rd, Register rs1, Register rs2) {
704741
ASSERT(Supports(RV_M));
742+
if (Supports(RV_Zcb)) {
743+
if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
744+
c_mul(rd, rs1, rs2);
745+
return;
746+
}
747+
if ((rd == rs2) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
748+
c_mul(rd, rs2, rs1);
749+
return;
750+
}
751+
}
705752
EmitRType(MULDIV, rs2, rs1, MUL, rd, OP);
706753
}
707754

@@ -1401,6 +1448,11 @@ void MicroAssembler::fmvdx(FRegister rd, Register rs1) {
14011448
#if XLEN >= 64
14021449
void MicroAssembler::adduw(Register rd, Register rs1, Register rs2) {
14031450
ASSERT(Supports(RV_Zba));
1451+
if (Supports(RV_Zcb)) {
1452+
if ((rd == rs1) && IsCRs1p(rs1) && (rs2 == ZR)) {
1453+
return c_zextw(rd, rs1);
1454+
}
1455+
}
14041456
EmitRType(ADDUW, rs2, rs1, F3_0, rd, OP32);
14051457
}
14061458
#endif
@@ -1514,16 +1566,31 @@ void MicroAssembler::minu(Register rd, Register rs1, Register rs2) {
15141566

15151567
void MicroAssembler::sextb(Register rd, Register rs1) {
15161568
ASSERT(Supports(RV_Zbb));
1569+
if (Supports(RV_Zcb)) {
1570+
if ((rd == rs1) && IsCRs1p(rs1)) {
1571+
return c_sextb(rd, rs1);
1572+
}
1573+
}
15171574
EmitRType((Funct7)0b0110000, 0b00100, rs1, SEXT, rd, OPIMM);
15181575
}
15191576

15201577
void MicroAssembler::sexth(Register rd, Register rs1) {
15211578
ASSERT(Supports(RV_Zbb));
1579+
if (Supports(RV_Zcb)) {
1580+
if ((rd == rs1) && IsCRs1p(rs1)) {
1581+
return c_sexth(rd, rs1);
1582+
}
1583+
}
15221584
EmitRType((Funct7)0b0110000, 0b00101, rs1, SEXT, rd, OPIMM);
15231585
}
15241586

15251587
void MicroAssembler::zexth(Register rd, Register rs1) {
15261588
ASSERT(Supports(RV_Zbb));
1589+
if (Supports(RV_Zcb)) {
1590+
if ((rd == rs1) && IsCRs1p(rs1)) {
1591+
return c_zexth(rd, rs1);
1592+
}
1593+
}
15271594
#if XLEN == 32
15281595
EmitRType((Funct7)0b0000100, 0b00000, rs1, ZEXT, rd, OP);
15291596
#elif XLEN == 64
@@ -1975,6 +2042,84 @@ void MicroAssembler::c_ebreak() {
19752042
Emit16(C_EBREAK);
19762043
}
19772044

2045+
void MicroAssembler::c_lbu(Register rd, Address addr) {
2046+
ASSERT(Supports(RV_Zcb));
2047+
Emit16(C_LBU | EncodeCRdp(rd) | EncodeCRs1p(addr.base()) |
2048+
EncodeCMem1Imm(addr.offset()));
2049+
}
2050+
2051+
void MicroAssembler::c_lhu(Register rd, Address addr) {
2052+
ASSERT(Supports(RV_Zcb));
2053+
Emit16(C_LHU | EncodeCRdp(rd) | EncodeCRs1p(addr.base()) |
2054+
EncodeCMem2Imm(addr.offset()));
2055+
}
2056+
2057+
void MicroAssembler::c_lh(Register rd, Address addr) {
2058+
ASSERT(Supports(RV_Zcb));
2059+
Emit16(C_LH | EncodeCRdp(rd) | EncodeCRs1p(addr.base()) |
2060+
EncodeCMem2Imm(addr.offset()));
2061+
}
2062+
2063+
void MicroAssembler::c_sb(Register rs2, Address addr) {
2064+
ASSERT(Supports(RV_Zcb));
2065+
Emit16(C_SB | EncodeCRs1p(addr.base()) | EncodeCRs2p(rs2) |
2066+
EncodeCMem1Imm(addr.offset()));
2067+
}
2068+
2069+
void MicroAssembler::c_sh(Register rs2, Address addr) {
2070+
ASSERT(Supports(RV_Zcb));
2071+
Emit16(C_SH | EncodeCRs1p(addr.base()) | EncodeCRs2p(rs2) |
2072+
EncodeCMem2Imm(addr.offset()));
2073+
}
2074+
2075+
void MicroAssembler::c_zextb(Register rd, Register rs1) {
2076+
ASSERT(Supports(RV_Zcb));
2077+
ASSERT(rd == rs1);
2078+
Emit16(C_ZEXTB | EncodeCRs1p(rs1));
2079+
}
2080+
2081+
void MicroAssembler::c_sextb(Register rd, Register rs1) {
2082+
ASSERT(Supports(RV_Zcb));
2083+
ASSERT(rd == rs1);
2084+
Emit16(C_SEXTB | EncodeCRs1p(rs1));
2085+
}
2086+
2087+
void MicroAssembler::c_zexth(Register rd, Register rs1) {
2088+
ASSERT(Supports(RV_Zcb));
2089+
ASSERT(Supports(RV_Zbb));
2090+
ASSERT(rd == rs1);
2091+
Emit16(C_ZEXTH | EncodeCRs1p(rs1));
2092+
}
2093+
2094+
void MicroAssembler::c_sexth(Register rd, Register rs1) {
2095+
ASSERT(Supports(RV_Zcb));
2096+
ASSERT(Supports(RV_Zbb));
2097+
ASSERT(rd == rs1);
2098+
Emit16(C_SEXTH | EncodeCRs1p(rs1));
2099+
}
2100+
2101+
#if XLEN >= 64
2102+
void MicroAssembler::c_zextw(Register rd, Register rs1) {
2103+
ASSERT(Supports(RV_Zcb));
2104+
ASSERT(Supports(RV_Zba));
2105+
ASSERT(rd == rs1);
2106+
Emit16(C_ZEXTW | EncodeCRs1p(rs1));
2107+
}
2108+
#endif
2109+
2110+
void MicroAssembler::c_mul(Register rd, Register rs1, Register rs2) {
2111+
ASSERT(Supports(RV_Zcb));
2112+
ASSERT(Supports(RV_M));
2113+
ASSERT(rd == rs1);
2114+
Emit16(C_MUL | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
2115+
}
2116+
2117+
void MicroAssembler::c_not(Register rd, Register rs1) {
2118+
ASSERT(Supports(RV_Zcb));
2119+
ASSERT(rd == rs1);
2120+
Emit16(C_NOT | EncodeCRs1p(rs1));
2121+
}
2122+
19782123
static Funct3 InvertFunct3(Funct3 func) {
19792124
switch (func) {
19802125
case BEQ:

runtime/vm/compiler/assembler/assembler_riscv.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class MicroAssembler : public AssemblerBase {
174174
void mv(Register rd, Register rs) { addi(rd, rs, 0); }
175175
void not_(Register rd, Register rs) { xori(rd, rs, -1); }
176176
void neg(Register rd, Register rs) { sub(rd, ZR, rs); }
177+
void zextb(Register rd, Register rs) { andi(rd, rs, 0xFF); }
177178

178179
void snez(Register rd, Register rs) { sltu(rd, ZR, rs); }
179180
void seqz(Register rd, Register rs) { sltiu(rd, rs, 1); }
@@ -696,6 +697,22 @@ class MicroAssembler : public AssemblerBase {
696697
void c_nop();
697698
void c_ebreak();
698699

700+
// ==== Zcb: Additional code-size saving instructions ====
701+
void c_lbu(Register rd, Address addr);
702+
void c_lh(Register rd, Address addr);
703+
void c_lhu(Register rd, Address addr);
704+
void c_sb(Register rs2, Address addr);
705+
void c_sh(Register rs2, Address addr);
706+
void c_zextb(Register rd, Register rs1);
707+
void c_sextb(Register rd, Register rs1);
708+
void c_zexth(Register rd, Register rs1);
709+
void c_sexth(Register rd, Register rs1);
710+
#if XLEN >= 64
711+
void c_zextw(Register rd, Register rs1);
712+
#endif
713+
void c_mul(Register rd, Register rs1, Register rs2);
714+
void c_not(Register rd, Register rs1);
715+
699716
protected:
700717
intptr_t UpdateCBOffset(intptr_t branch_position, intptr_t new_offset);
701718
intptr_t UpdateCJOffset(intptr_t branch_position, intptr_t new_offset);

0 commit comments

Comments
 (0)