Skip to content

Commit e3987ed

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

File tree

9 files changed

+1454
-39
lines changed

9 files changed

+1454
-39
lines changed

runtime/platform/assert.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
// implemented for all the primitive types we can replace the usage of
1919
// sstream by Utils::toString()
2020
#if defined(DEBUG) || defined(TESTING)
21+
#include <string.h>
22+
2123
#include <sstream>
2224
#include <string>
2325
#endif
@@ -63,6 +65,9 @@ class Expect : public DynamicAssertionHelper {
6365
template <typename E, typename A>
6466
void NotEquals(const E& not_expected, const A& actual);
6567

68+
template <typename E, typename A>
69+
void BitEquals(const E& expected, const A& actual);
70+
6671
template <typename E, typename A, typename T>
6772
void FloatEquals(const E& expected, const A& actual, const T& tol);
6873

@@ -126,6 +131,17 @@ void Expect::NotEquals(const E& not_expected, const A& actual) {
126131
Fail("did not expect: <%s>", nes.c_str());
127132
}
128133

134+
template <typename E, typename A>
135+
void Expect::BitEquals(const E& expected, const A& actual) {
136+
static_assert(sizeof(E) == sizeof(A));
137+
if (memcmp(&expected, &actual, sizeof(E)) == 0) return;
138+
std::ostringstream ess, ass;
139+
ess << expected;
140+
ass << actual;
141+
std::string es = ess.str(), as = ass.str();
142+
Fail("expected: <%s> but was: <%s>", es.c_str(), as.c_str());
143+
}
144+
129145
template <typename E, typename A, typename T>
130146
void Expect::FloatEquals(const E& expected, const A& actual, const T& tol) {
131147
if (((expected - tol) <= actual) && (actual <= (expected + tol))) {
@@ -356,6 +372,9 @@ void Expect::Null(const T p) {
356372
#define EXPECT_NE(not_expected, actual) \
357373
dart::Expect(__FILE__, __LINE__).NotEquals((not_expected), (actual))
358374

375+
#define EXPECT_BITEQ(expected, actual) \
376+
dart::Expect(__FILE__, __LINE__).BitEquals((expected), (actual))
377+
359378
#define EXPECT_FLOAT_EQ(expected, actual, tol) \
360379
dart::Expect(__FILE__, __LINE__).FloatEquals((expected), (actual), (tol))
361380

runtime/vm/compiler/assembler/assembler_riscv.cc

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,14 +1175,14 @@ void MicroAssembler::fcvtwus(Register rd,
11751175

11761176
void MicroAssembler::fcvtsw(FRegister rd, Register rs1, RoundingMode rounding) {
11771177
ASSERT(Supports(RV_F));
1178-
EmitRType(FCVTSint, FRegister(W), rs1, rounding, rd, OPFP);
1178+
EmitRType(FCVTSint, Register(W), rs1, rounding, rd, OPFP);
11791179
}
11801180

11811181
void MicroAssembler::fcvtswu(FRegister rd,
11821182
Register rs1,
11831183
RoundingMode rounding) {
11841184
ASSERT(Supports(RV_F));
1185-
EmitRType(FCVTSint, FRegister(WU), rs1, rounding, rd, OPFP);
1185+
EmitRType(FCVTSint, Register(WU), rs1, rounding, rd, OPFP);
11861186
}
11871187

11881188
void MicroAssembler::fmvxw(Register rd, FRegister rs1) {
@@ -1192,7 +1192,7 @@ void MicroAssembler::fmvxw(Register rd, FRegister rs1) {
11921192

11931193
void MicroAssembler::fmvwx(FRegister rd, Register rs1) {
11941194
ASSERT(Supports(RV_F));
1195-
EmitRType(FMVWX, FRegister(0), rs1, F3_0, rd, OPFP);
1195+
EmitRType(FMVWX, Register(0), rs1, F3_0, rd, OPFP);
11961196
}
11971197

11981198
#if XLEN >= 64
@@ -1210,14 +1210,14 @@ void MicroAssembler::fcvtlus(Register rd,
12101210

12111211
void MicroAssembler::fcvtsl(FRegister rd, Register rs1, RoundingMode rounding) {
12121212
ASSERT(Supports(RV_F));
1213-
EmitRType(FCVTSint, FRegister(L), rs1, rounding, rd, OPFP);
1213+
EmitRType(FCVTSint, Register(L), rs1, rounding, rd, OPFP);
12141214
}
12151215

12161216
void MicroAssembler::fcvtslu(FRegister rd,
12171217
Register rs1,
12181218
RoundingMode rounding) {
12191219
ASSERT(Supports(RV_F));
1220-
EmitRType(FCVTSint, FRegister(LU), rs1, rounding, rd, OPFP);
1220+
EmitRType(FCVTSint, Register(LU), rs1, rounding, rd, OPFP);
12211221
}
12221222
#endif // XLEN >= 64
12231223

@@ -1399,14 +1399,14 @@ void MicroAssembler::fcvtwud(Register rd,
13991399

14001400
void MicroAssembler::fcvtdw(FRegister rd, Register rs1, RoundingMode rounding) {
14011401
ASSERT(Supports(RV_D));
1402-
EmitRType(FCVTDint, FRegister(W), rs1, rounding, rd, OPFP);
1402+
EmitRType(FCVTDint, Register(W), rs1, rounding, rd, OPFP);
14031403
}
14041404

14051405
void MicroAssembler::fcvtdwu(FRegister rd,
14061406
Register rs1,
14071407
RoundingMode rounding) {
14081408
ASSERT(Supports(RV_D));
1409-
EmitRType(FCVTDint, FRegister(WU), rs1, rounding, rd, OPFP);
1409+
EmitRType(FCVTDint, Register(WU), rs1, rounding, rd, OPFP);
14101410
}
14111411

14121412
#if XLEN >= 64
@@ -1429,19 +1429,19 @@ void MicroAssembler::fmvxd(Register rd, FRegister rs1) {
14291429

14301430
void MicroAssembler::fcvtdl(FRegister rd, Register rs1, RoundingMode rounding) {
14311431
ASSERT(Supports(RV_D));
1432-
EmitRType(FCVTDint, FRegister(L), rs1, rounding, rd, OPFP);
1432+
EmitRType(FCVTDint, Register(L), rs1, rounding, rd, OPFP);
14331433
}
14341434

14351435
void MicroAssembler::fcvtdlu(FRegister rd,
14361436
Register rs1,
14371437
RoundingMode rounding) {
14381438
ASSERT(Supports(RV_D));
1439-
EmitRType(FCVTDint, FRegister(LU), rs1, rounding, rd, OPFP);
1439+
EmitRType(FCVTDint, Register(LU), rs1, rounding, rd, OPFP);
14401440
}
14411441

14421442
void MicroAssembler::fmvdx(FRegister rd, Register rs1) {
14431443
ASSERT(Supports(RV_D));
1444-
EmitRType(FMVDX, FRegister(0), rs1, F3_0, rd, OPFP);
1444+
EmitRType(FMVDX, Register(0), rs1, F3_0, rd, OPFP);
14451445
}
14461446
#endif // XLEN >= 64
14471447

@@ -1873,6 +1873,102 @@ void MicroAssembler::amomaxuh(Register rd,
18731873
EmitRType(AMOMAXU, order, rs2, addr.base(), WIDTH16, rd, AMO);
18741874
}
18751875

1876+
void MicroAssembler::flis(FRegister rd, intptr_t index) {
1877+
ASSERT((index >= 0) && (index < 32));
1878+
ASSERT(Supports(RV_Zfa));
1879+
EmitRType(FMVWX, FRegister(1), FRegister(index), F3_0, rd, OPFP);
1880+
}
1881+
1882+
void MicroAssembler::flid(FRegister rd, intptr_t index) {
1883+
ASSERT((index >= 0) && (index < 32));
1884+
ASSERT(Supports(RV_Zfa));
1885+
EmitRType(FMVDX, FRegister(1), FRegister(index), F3_0, rd, OPFP);
1886+
}
1887+
1888+
void MicroAssembler::fminms(FRegister rd, FRegister rs1, FRegister rs2) {
1889+
ASSERT(Supports(RV_Zfa));
1890+
EmitRType(FMINMAXS, rs2, rs1, FMINM, rd, OPFP);
1891+
}
1892+
void MicroAssembler::fmaxms(FRegister rd, FRegister rs1, FRegister rs2) {
1893+
ASSERT(Supports(RV_Zfa));
1894+
EmitRType(FMINMAXS, rs2, rs1, FMAXM, rd, OPFP);
1895+
}
1896+
1897+
void MicroAssembler::fminmd(FRegister rd, FRegister rs1, FRegister rs2) {
1898+
ASSERT(Supports(RV_Zfa));
1899+
EmitRType(FMINMAXD, rs2, rs1, FMINM, rd, OPFP);
1900+
}
1901+
1902+
void MicroAssembler::fmaxmd(FRegister rd, FRegister rs1, FRegister rs2) {
1903+
ASSERT(Supports(RV_Zfa));
1904+
EmitRType(FMINMAXD, rs2, rs1, FMAXM, rd, OPFP);
1905+
}
1906+
1907+
void MicroAssembler::frounds(FRegister rd,
1908+
FRegister rs1,
1909+
RoundingMode rounding) {
1910+
ASSERT(Supports(RV_Zfa));
1911+
EmitRType(FCVTS, FRegister(4), rs1, rounding, rd, OPFP);
1912+
}
1913+
1914+
void MicroAssembler::froundnxs(FRegister rd,
1915+
FRegister rs1,
1916+
RoundingMode rounding) {
1917+
ASSERT(Supports(RV_Zfa));
1918+
EmitRType(FCVTS, FRegister(5), rs1, rounding, rd, OPFP);
1919+
}
1920+
1921+
void MicroAssembler::froundd(FRegister rd,
1922+
FRegister rs1,
1923+
RoundingMode rounding) {
1924+
ASSERT(Supports(RV_Zfa));
1925+
EmitRType(FCVTD, FRegister(4), rs1, rounding, rd, OPFP);
1926+
}
1927+
1928+
void MicroAssembler::froundnxd(FRegister rd,
1929+
FRegister rs1,
1930+
RoundingMode rounding) {
1931+
ASSERT(Supports(RV_Zfa));
1932+
EmitRType(FCVTD, FRegister(5), rs1, rounding, rd, OPFP);
1933+
}
1934+
1935+
void MicroAssembler::fcvtmodwd(Register rd, FRegister rs1) {
1936+
ASSERT(Supports(RV_Zfa));
1937+
EmitRType(FCVTintD, FRegister(8), rs1, RTZ, rd, OPFP);
1938+
}
1939+
1940+
#if XLEN == 32
1941+
void MicroAssembler::fmvhxd(Register rd, FRegister rs1) {
1942+
ASSERT(Supports(RV_Zfa));
1943+
EmitRType(FMVHXD, FRegister(1), rs1, F3_0, rd, OPFP);
1944+
}
1945+
1946+
void MicroAssembler::fmvpdx(FRegister rd, Register rs1, Register rs2) {
1947+
ASSERT(Supports(RV_Zfa));
1948+
EmitRType(FMVPDX, rs2, rs1, F3_0, rd, OPFP);
1949+
}
1950+
#endif // XLEN == 32
1951+
1952+
void MicroAssembler::fltqs(Register rd, FRegister rs1, FRegister rs2) {
1953+
ASSERT(Supports(RV_Zfa));
1954+
EmitRType(FCMPS, rs2, rs1, FLTQ, rd, OPFP);
1955+
}
1956+
1957+
void MicroAssembler::fleqs(Register rd, FRegister rs1, FRegister rs2) {
1958+
ASSERT(Supports(RV_Zfa));
1959+
EmitRType(FCMPS, rs2, rs1, FLEQ, rd, OPFP);
1960+
}
1961+
1962+
void MicroAssembler::fltqd(Register rd, FRegister rs1, FRegister rs2) {
1963+
ASSERT(Supports(RV_Zfa));
1964+
EmitRType(FCMPD, rs2, rs1, FLTQ, rd, OPFP);
1965+
}
1966+
1967+
void MicroAssembler::fleqd(Register rd, FRegister rs1, FRegister rs2) {
1968+
ASSERT(Supports(RV_Zfa));
1969+
EmitRType(FCMPD, rs2, rs1, FLEQ, rd, OPFP);
1970+
}
1971+
18761972
void MicroAssembler::lb(Register rd, Address addr, std::memory_order order) {
18771973
ASSERT(addr.offset() == 0);
18781974
ASSERT((order == std::memory_order_acquire) ||
@@ -2554,14 +2650,14 @@ void MicroAssembler::EmitRType(Funct7 funct7,
25542650
}
25552651

25562652
void MicroAssembler::EmitRType(Funct7 funct7,
2557-
FRegister rs2,
2653+
Register rs2,
25582654
Register rs1,
25592655
RoundingMode round,
25602656
FRegister rd,
25612657
Opcode opcode) {
25622658
uint32_t e = 0;
25632659
e |= EncodeFunct7(funct7);
2564-
e |= EncodeFRs2(rs2);
2660+
e |= EncodeRs2(rs2);
25652661
e |= EncodeRs1(rs1);
25662662
e |= EncodeRoundingMode(round);
25672663
e |= EncodeFRd(rd);
@@ -2570,14 +2666,14 @@ void MicroAssembler::EmitRType(Funct7 funct7,
25702666
}
25712667

25722668
void MicroAssembler::EmitRType(Funct7 funct7,
2573-
FRegister rs2,
2669+
Register rs2,
25742670
Register rs1,
25752671
Funct3 funct3,
25762672
FRegister rd,
25772673
Opcode opcode) {
25782674
uint32_t e = 0;
25792675
e |= EncodeFunct7(funct7);
2580-
e |= EncodeFRs2(rs2);
2676+
e |= EncodeRs2(rs2);
25812677
e |= EncodeRs1(rs1);
25822678
e |= EncodeFunct3(funct3);
25832679
e |= EncodeFRd(rd);
@@ -4074,10 +4170,19 @@ void Assembler::LoadImmediate(Register reg, intx_t imm) {
40744170
}
40754171

40764172
void Assembler::LoadSImmediate(FRegister reg, float imms) {
4077-
int32_t imm = bit_cast<int32_t, float>(imms);
4173+
uint32_t imm = bit_cast<uint32_t, float>(imms);
40784174
if (imm == 0) {
40794175
fmvwx(reg, ZR); // bit_cast uint32_t -> float
40804176
} else {
4177+
if (Supports(RV_Zfa)) {
4178+
for (intptr_t i = 0; i < 32; i++) {
4179+
if (kFlisConstants[i] == imm) {
4180+
flis(reg, i);
4181+
return;
4182+
}
4183+
}
4184+
}
4185+
40814186
ASSERT(constant_pool_allowed());
40824187
intptr_t index = object_pool_builder().FindImmediate(imm);
40834188
intptr_t offset = target::ObjectPool::element_offset(index);
@@ -4086,14 +4191,23 @@ void Assembler::LoadSImmediate(FRegister reg, float imms) {
40864191
}
40874192

40884193
void Assembler::LoadDImmediate(FRegister reg, double immd) {
4089-
int64_t imm = bit_cast<int64_t, double>(immd);
4194+
uint64_t imm = bit_cast<uint64_t, double>(immd);
40904195
if (imm == 0) {
40914196
#if XLEN >= 64
40924197
fmvdx(reg, ZR); // bit_cast uint64_t -> double
40934198
#else
40944199
fcvtdwu(reg, ZR); // static_cast uint32_t -> double
40954200
#endif
40964201
} else {
4202+
if (Supports(RV_Zfa)) {
4203+
for (intptr_t i = 0; i < 32; i++) {
4204+
if (kFlidConstants[i] == imm) {
4205+
flid(reg, i);
4206+
return;
4207+
}
4208+
}
4209+
}
4210+
40974211
ASSERT(constant_pool_allowed());
40984212
intptr_t index = object_pool_builder().FindImmediate64(imm);
40994213
intptr_t offset = target::ObjectPool::element_offset(index);

runtime/vm/compiler/assembler/assembler_riscv.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,27 @@ class MicroAssembler : public AssemblerBase {
687687
Address addr,
688688
std::memory_order order = std::memory_order_relaxed);
689689

690+
// ==== Zfa: Additional floating-point instructions ====
691+
void flis(FRegister rd, intptr_t index);
692+
void flid(FRegister rd, intptr_t index);
693+
void fminms(FRegister rd, FRegister rs1, FRegister rs2);
694+
void fmaxms(FRegister rd, FRegister rs1, FRegister rs2);
695+
void fminmd(FRegister rd, FRegister rs1, FRegister rs2);
696+
void fmaxmd(FRegister rd, FRegister rs1, FRegister rs2);
697+
void frounds(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
698+
void froundd(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
699+
void froundnxs(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
700+
void froundnxd(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
701+
void fcvtmodwd(Register rd, FRegister rs1);
702+
#if XLEN == 32
703+
void fmvhxd(Register rd, FRegister rs1);
704+
void fmvpdx(FRegister rd, Register rs1, Register rs2);
705+
#endif
706+
void fltqs(Register rd, FRegister rs1, FRegister rs2);
707+
void fleqs(Register rd, FRegister rs1, FRegister rs2);
708+
void fltqd(Register rd, FRegister rs1, FRegister rs2);
709+
void fleqd(Register rd, FRegister rs1, FRegister rs2);
710+
690711
// ==== Zalasr: Load-acquire, store-release ====
691712
void lb(Register rd, Address addr, std::memory_order order);
692713
void lh(Register rd, Address addr, std::memory_order order);
@@ -830,13 +851,13 @@ class MicroAssembler : public AssemblerBase {
830851
FRegister rd,
831852
Opcode opcode);
832853
void EmitRType(Funct7 funct7,
833-
FRegister rs2,
854+
Register rs2,
834855
Register rs1,
835856
RoundingMode round,
836857
FRegister rd,
837858
Opcode opcode);
838859
void EmitRType(Funct7 funct7,
839-
FRegister rs2,
860+
Register rs2,
840861
Register rs1,
841862
Funct3 funct3,
842863
FRegister rd,

0 commit comments

Comments
 (0)