Skip to content

Commit acd7e82

Browse files
authored
Implement N32 floating-point regs (#78)
* Add --n32 flag to recomp.elf * Implement N32 floating-point regs
1 parent 5f4f92a commit acd7e82

File tree

2 files changed

+130
-60
lines changed

2 files changed

+130
-60
lines changed

header.h

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,37 @@
1818

1919
#define cvt_w_s(f) cvt_w_d((double)f)
2020

21-
static union FloatReg f0 = {{0, 0}}, f2 = {{0, 0}}, f4 = {{0, 0}}, f6 = {{0, 0}}, f8 = {{0, 0}},
22-
f10 = {{0, 0}}, f12 = {{0, 0}}, f14 = {{0, 0}}, f16 = {{0, 0}}, f18 = {{0, 0}}, f20 = {{0, 0}},
23-
f22 = {{0, 0}}, f24 = {{0, 0}}, f26 = {{0, 0}}, f28 = {{0, 0}}, f30 = {{0, 0}};
21+
static union FloatReg
22+
f0 = {{0, 0}},
23+
f1 = {{0, 0}},
24+
f2 = {{0, 0}},
25+
f3 = {{0, 0}},
26+
f4 = {{0, 0}},
27+
f5 = {{0, 0}},
28+
f6 = {{0, 0}},
29+
f7 = {{0, 0}},
30+
f8 = {{0, 0}},
31+
f9 = {{0, 0}},
32+
f10 = {{0, 0}},
33+
f11 = {{0, 0}},
34+
f12 = {{0, 0}},
35+
f13 = {{0, 0}},
36+
f14 = {{0, 0}},
37+
f15 = {{0, 0}},
38+
f16 = {{0, 0}},
39+
f17 = {{0, 0}},
40+
f18 = {{0, 0}},
41+
f19 = {{0, 0}},
42+
f20 = {{0, 0}},
43+
f21 = {{0, 0}},
44+
f22 = {{0, 0}},
45+
f23 = {{0, 0}},
46+
f24 = {{0, 0}},
47+
f25 = {{0, 0}},
48+
f26 = {{0, 0}},
49+
f27 = {{0, 0}},
50+
f28 = {{0, 0}},
51+
f29 = {{0, 0}},
52+
f30 = {{0, 0}},
53+
f31 = {{0, 0}};
2454
static uint32_t fcsr = 1;

recomp.cpp

Lines changed: 97 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ struct Function {
210210
};
211211

212212
bool conservative;
213+
bool n32;
213214

214215
const uint8_t* text_section;
215216
uint32_t text_section_len;
@@ -1967,26 +1968,38 @@ const char* r(uint32_t reg) {
19671968
const char* wr(uint32_t reg) {
19681969
// clang-format off
19691970
static const char *regs[] = {
1970-
"f0.w[0]", "f0.w[1]",
1971-
"f2.w[0]", "f2.w[1]",
1972-
"f4.w[0]", "f4.w[1]",
1973-
"f6.w[0]", "f6.w[1]",
1974-
"f8.w[0]", "f8.w[1]",
1975-
"f10.w[0]", "f10.w[1]",
1976-
"f12.w[0]", "f12.w[1]",
1977-
"f14.w[0]", "f14.w[1]",
1978-
"f16.w[0]", "f16.w[1]",
1979-
"f18.w[0]", "f18.w[1]",
1980-
"f20.w[0]", "f20.w[1]",
1981-
"f22.w[0]", "f22.w[1]",
1982-
"f24.w[0]", "f24.w[1]",
1983-
"f26.w[0]", "f26.w[1]",
1984-
"f28.w[0]", "f28.w[1]",
1985-
"f30.w[0]", "f30.w[1]"
1971+
"f0.w[0]", "f0.w[1]", "f1.w[0]", "f1.w[1]",
1972+
"f2.w[0]", "f2.w[1]", "f3.w[0]", "f3.w[1]",
1973+
"f4.w[0]", "f4.w[1]", "f5.w[0]", "f5.w[1]",
1974+
"f6.w[0]", "f6.w[1]", "f7.w[0]", "f7.w[1]",
1975+
"f8.w[0]", "f8.w[1]", "f9.w[0]", "f9.w[1]",
1976+
"f10.w[0]", "f10.w[1]", "f11.w[0]", "f11.w[1]",
1977+
"f12.w[0]", "f12.w[1]", "f13.w[0]", "f13.w[1]",
1978+
"f14.w[0]", "f14.w[1]", "f15.w[0]", "f15.w[1]",
1979+
"f16.w[0]", "f16.w[1]", "f17.w[0]", "f17.w[1]",
1980+
"f18.w[0]", "f18.w[1]", "f19.w[0]", "f19.w[1]",
1981+
"f20.w[0]", "f20.w[1]", "f21.w[0]", "f21.w[1]",
1982+
"f22.w[0]", "f22.w[1]", "f23.w[0]", "f23.w[1]",
1983+
"f24.w[0]", "f24.w[1]", "f25.w[0]", "f25.w[1]",
1984+
"f26.w[0]", "f26.w[1]", "f27.w[0]", "f27.w[1]",
1985+
"f28.w[0]", "f28.w[1]", "f29.w[0]", "f29.w[1]",
1986+
"f30.w[0]", "f30.w[1]", "f31.w[0]", "f31.w[1]",
19861987
};
19871988
// clang-format on
19881989

1989-
size_t index = reg - (int)rabbitizer::Registers::Cpu::Cop1O32::COP1_O32_fv0;
1990+
size_t index;
1991+
1992+
if (n32) {
1993+
// In N32, all registers access the lower half of the register
1994+
index = reg * 2;
1995+
} else {
1996+
// In O32, odd registers alias the upper half of the previous register
1997+
if (reg % 2 == 0) {
1998+
index = reg * 2;
1999+
} else {
2000+
index = (reg - 1) * 2 + 1;
2001+
}
2002+
}
19902003

19912004
assert(index < std::size(regs));
19922005
return regs[index];
@@ -1995,26 +2008,38 @@ const char* wr(uint32_t reg) {
19952008
const char* fr(uint32_t reg) {
19962009
// clang-format off
19972010
static const char *regs[] = {
1998-
"f0.f[0]", "f0.f[1]",
1999-
"f2.f[0]", "f2.f[1]",
2000-
"f4.f[0]", "f4.f[1]",
2001-
"f6.f[0]", "f6.f[1]",
2002-
"f8.f[0]", "f8.f[1]",
2003-
"f10.f[0]", "f10.f[1]",
2004-
"f12.f[0]", "f12.f[1]",
2005-
"f14.f[0]", "f14.f[1]",
2006-
"f16.f[0]", "f16.f[1]",
2007-
"f18.f[0]", "f18.f[1]",
2008-
"f20.f[0]", "f20.f[1]",
2009-
"f22.f[0]", "f22.f[1]",
2010-
"f24.f[0]", "f24.f[1]",
2011-
"f26.f[0]", "f26.f[1]",
2012-
"f28.f[0]", "f28.f[1]",
2013-
"f30.f[0]", "f30.f[1]",
2011+
"f0.f[0]", "f0.f[1]", "f1.f[0]", "f1.f[1]",
2012+
"f2.f[0]", "f2.f[1]", "f3.f[0]", "f3.f[1]",
2013+
"f4.f[0]", "f4.f[1]", "f5.f[0]", "f5.f[1]",
2014+
"f6.f[0]", "f6.f[1]", "f7.f[0]", "f7.f[1]",
2015+
"f8.f[0]", "f8.f[1]", "f9.f[0]", "f9.f[1]",
2016+
"f10.f[0]", "f10.f[1]", "f11.f[0]", "f11.f[1]",
2017+
"f12.f[0]", "f12.f[1]", "f13.f[0]", "f13.f[1]",
2018+
"f14.f[0]", "f14.f[1]", "f15.f[0]", "f15.f[1]",
2019+
"f16.f[0]", "f16.f[1]", "f17.f[0]", "f17.f[1]",
2020+
"f18.f[0]", "f18.f[1]", "f19.f[0]", "f19.f[1]",
2021+
"f20.f[0]", "f20.f[1]", "f21.f[0]", "f21.f[1]",
2022+
"f22.f[0]", "f22.f[1]", "f23.f[0]", "f23.f[1]",
2023+
"f24.f[0]", "f24.f[1]", "f25.f[0]", "f25.f[1]",
2024+
"f26.f[0]", "f26.f[1]", "f27.f[0]", "f27.f[1]",
2025+
"f28.f[0]", "f28.f[1]", "f29.f[0]", "f29.f[1]",
2026+
"f30.f[0]", "f30.f[1]", "f31.f[0]", "f31.f[1]",
20142027
};
20152028
// clang-format on
20162029

2017-
size_t index = reg - (int)rabbitizer::Registers::Cpu::Cop1O32::COP1_O32_fv0;
2030+
size_t index;
2031+
2032+
if (n32) {
2033+
// In N32, all registers access the lower half of the register
2034+
index = reg * 2;
2035+
} else {
2036+
// In O32, odd registers alias the upper half of the previous register
2037+
if (reg % 2 == 0) {
2038+
index = reg * 2;
2039+
} else {
2040+
index = (reg - 1) * 2 + 1;
2041+
}
2042+
}
20182043

20192044
assert(index < std::size(regs));
20202045
return regs[index];
@@ -2023,29 +2048,32 @@ const char* fr(uint32_t reg) {
20232048
const char* dr(uint32_t reg) {
20242049
// clang-format off
20252050
static const char *regs[] = {
2026-
"f0",
2027-
"f2",
2028-
"f4",
2029-
"f6",
2030-
"f8",
2031-
"f10",
2032-
"f12",
2033-
"f14",
2034-
"f16",
2035-
"f18",
2036-
"f20",
2037-
"f22",
2038-
"f24",
2039-
"f26",
2040-
"f28",
2041-
"f30"
2051+
"f0", "f1",
2052+
"f2", "f3",
2053+
"f4", "f5",
2054+
"f6", "f7",
2055+
"f8", "f9",
2056+
"f10", "f11",
2057+
"f12", "f13",
2058+
"f14", "f15",
2059+
"f16", "f17",
2060+
"f18", "f19",
2061+
"f20", "f21",
2062+
"f22", "f23",
2063+
"f24", "f25",
2064+
"f26", "f27",
2065+
"f28", "f29",
2066+
"f30", "f31",
20422067
};
20432068
// clang-format on
20442069

2045-
size_t index = reg - (int)rabbitizer::Registers::Cpu::Cop1O32::COP1_O32_fv0;
2070+
size_t index = reg;
2071+
2072+
if (!n32) {
2073+
// In O32, only even registers can be used as double registers
2074+
assert(reg % 2 == 0);
2075+
}
20462076

2047-
assert(index % 2 == 0);
2048-
index /= 2;
20492077
assert(index < std::size(regs));
20502078
return regs[index];
20512079
}
@@ -3946,13 +3974,25 @@ void crashHandler(int sig) {
39463974
#endif
39473975

39483976
int main(int argc, char* argv[]) {
3949-
const char* filename = argv[1];
3977+
int argi;
39503978

3951-
if ((argc > 2) && (strcmp(filename, "--conservative") == 0)) {
3952-
conservative = true;
3953-
filename = argv[2];
3979+
for (argi = 1; argi < argc; argi++) {
3980+
if (strcmp(argv[argi], "--conservative") == 0) {
3981+
conservative = true;
3982+
} else if (strcmp(argv[argi], "--n32") == 0) {
3983+
n32 = true;
3984+
} else {
3985+
break;
3986+
}
3987+
}
3988+
3989+
if (argi != argc - 1) {
3990+
fprintf(stderr, "Usage: %s [--conservative] [--n32] <elf_file>\n", argv[0]);
3991+
return 1;
39543992
}
39553993

3994+
const char* filename = argv[argi];
3995+
39563996
#ifdef UNIX_PLATFORM
39573997
signal(SIGSEGV, crashHandler);
39583998
signal(SIGABRT, crashHandler);

0 commit comments

Comments
 (0)