we can now execute crt0

This commit is contained in:
2026-03-09 16:23:45 +01:00
parent 20d8953220
commit 2252e1fa75

View File

@@ -80,9 +80,9 @@ enum Op {
C_OR, C_OR,
C_SD, C_SD,
C_SDSP, C_SDSP,
C_SLLI,
C_SRAI, C_SRAI,
C_SRLI, C_SRLI,
C_SLLI,
C_SUB, C_SUB,
C_SUBW, C_SUBW,
C_SW, C_SW,
@@ -171,6 +171,7 @@ enum class Format {
I_SHIFT, I_SHIFT,
S, S,
B, B,
CB,
U, U,
J, J,
CI, CI,
@@ -199,9 +200,9 @@ static constexpr std::array<OpDef, 101> OP_TABLE = {{
{"bne", Format::B}, {"c.add", Format::CR}, {"bne", Format::B}, {"c.add", Format::CR},
{"c.addi", Format::CI}, {"c.addiw", Format::CI}, {"c.addi", Format::CI}, {"c.addiw", Format::CI},
{"c.addi16sp", Format::CI}, {"c.addi4spn", Format::CI}, {"c.addi16sp", Format::CI}, {"c.addi4spn", Format::CI},
{"c.addw", Format::CI}, {"c.and", Format::CR}, {"c.addw", Format::CR}, {"c.and", Format::CR},
{"c.andi", Format::CI}, {"c.beqz", Format::B}, {"c.andi", Format::CI}, {"c.beqz", Format::CB},
{"c.bnez", Format::B}, {"c.ebreak", Format::CR}, {"c.bnez", Format::CB}, {"c.ebreak", Format::NONE},
{"c.fldsp", Format::CSS}, {"c.j", Format::CJ}, {"c.fldsp", Format::CSS}, {"c.j", Format::CJ},
{"c.jalr", Format::CR1}, {"c.jr", Format::CR1}, {"c.jalr", Format::CR1}, {"c.jr", Format::CR1},
{"c.ld", Format::CL}, {"c.ldsp", Format::CL}, {"c.ld", Format::CL}, {"c.ldsp", Format::CL},
@@ -334,6 +335,9 @@ public:
std::println("{} {}, {}, {}", def.mnemonic, REGS[ins.rs1], REGS[ins.rs2], std::println("{} {}, {}, {}", def.mnemonic, REGS[ins.rs1], REGS[ins.rs2],
ins.imm); ins.imm);
break; break;
case Format::CB:
std::println("{} {}, {}", def.mnemonic, REGS[ins.rs1], ins.imm);
break;
case Format::J: case Format::J:
std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], ins.imm); std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], ins.imm);
break; break;
@@ -452,8 +456,10 @@ public:
} }
}; break; }; break;
case Op::BGEU: { case Op::BGEU: {
std::println(stderr, "BGEU unimplemented"); if ((u64)m_regs[i.rs1] >= (u64)m_regs[i.rs2]) {
exit(1); m_pc += i.imm;
continue;
}
}; break; }; break;
case Op::BLT: { case Op::BLT: {
if (m_regs[i.rs1] < m_regs[i.rs2]) { if (m_regs[i.rs1] < m_regs[i.rs2]) {
@@ -473,6 +479,92 @@ public:
continue; continue;
} }
}; break; }; break;
case Op::C_ADD: {
m_regs[i.rd] += m_regs[i.rs2];
}; break;
case Op::C_ADDI: {
m_regs[i.rd] += i.imm;
}; break;
case Op::C_ADDIW: {
m_regs[i.rd] = (i64)(i32)m_regs[i.rd] + i.imm;
}; break;
case Op::C_ADDI16SP: {
sp += i.imm;
}; break;
case Op::C_ADDI4SPN: {
m_regs[i.rd] = sp + i.imm;
}; break;
case Op::C_ADDW: {
m_regs[i.rd] = (i64)((i32)m_regs[i.rd] + (i32)m_regs[i.rs2]);
}; break;
case Op::C_AND: {
m_regs[i.rd] &= m_regs[i.rs2];
}; break;
case Op::C_ANDI: {
m_regs[i.rd] = m_regs[i.rs1] & i.imm;
}; break;
case Op::C_BEQZ: {
if (m_regs[i.rs1] == 0) {
m_pc += i.imm;
continue;
}
}; break;
case Op::C_BNEZ: {
if (m_regs[i.rs1] != 0) {
m_pc += i.imm;
continue;
}
}; break;
case Op::C_J: {
m_pc += i.imm;
continue;
}; break;
case Op::C_JALR: {
m_regs[1] = m_pc + 2;
m_pc = m_regs[i.rs1];
continue;
}; break;
case Op::C_JR: {
m_pc = m_regs[i.rs1];
continue;
}; break;
case Op::C_LD: {
u64 addr = m_regs[i.rs1] + i.imm;
m_regs[i.rd] = *(u64 *)&m_memory[addr];
}; break;
case Op::C_LDSP: {
u64 addr = sp + i.imm;
m_regs[i.rd] = *(u64 *)(&m_memory[addr]);
}; break;
case Op::C_LI: {
m_regs[i.rd] = i.imm;
}; break;
case Op::C_LUI: {
m_regs[i.rd] = (int64_t)(uint64_t)((int64_t)i.imm) << 12;
}; break;
case Op::C_LW: {
u64 addr = m_regs[i.rs1] + i.imm;
m_regs[i.rd] = *(u32 *)&m_memory[addr];
}; break;
case Op::C_MV: {
m_regs[i.rd] = m_regs[i.rs2];
}; break;
case Op::C_SDSP: {
u64 addr = sp + i.imm;
*(u64 *)(&m_memory[addr]) = m_regs[i.rs2];
}; break;
case Op::C_SLLI: {
m_regs[i.rd] = (i64)((u64)m_regs[i.rd] << i.imm);
}; break;
case Op::C_SRAI: {
m_regs[i.rd] >>= i.imm;
}; break;
case Op::C_SRLI: {
m_regs[i.rd] = (i64)((u64)m_regs[i.rd] >> i.imm);
}; break;
case Op::C_SUB: {
m_regs[i.rd] -= m_regs[i.rs2];
}; break;
case Op::DIV: { case Op::DIV: {
if (m_regs[i.rs2] == 0) { if (m_regs[i.rs2] == 0) {
m_regs[i.rd] = -1; m_regs[i.rd] = -1;
@@ -480,10 +572,6 @@ public:
m_regs[i.rd] = m_regs[i.rs1] / m_regs[i.rs2]; m_regs[i.rd] = m_regs[i.rs1] / m_regs[i.rs2];
} }
}; break; }; break;
case Op::DIVU: {
std::println(stderr, "DIVU unimplemented");
exit(1);
}; break;
case Op::DIVUW: { case Op::DIVUW: {
if (m_regs[i.rs2] == 0) { if (m_regs[i.rs2] == 0) {
m_regs[i.rd] = -1LL; m_regs[i.rd] = -1LL;
@@ -540,10 +628,17 @@ public:
std::cout.put(m_memory[i]); std::cout.put(m_memory[i]);
} }
}; break; }; break;
case 93: { // exit case 93: // exit
case 94: { // exit_group
std::println("Program exited with code {}.", m_regs[10]); std::println("Program exited with code {}.", m_regs[10]);
return; return;
}; break; }; break;
case 96: { // set_tid_address
i64 tidptr = m_regs[10];
i32 tid = 123;
memcpy(&m_memory[tidptr], &tid, sizeof(tid));
m_regs[10] = tid;
}; break;
case 169: { // gettimeofday case 169: { // gettimeofday
i64 tv_addr = m_regs[10]; i64 tv_addr = m_regs[10];
i64 tz_addr = m_regs[11]; i64 tz_addr = m_regs[11];
@@ -590,20 +685,12 @@ public:
case Op::LH: { case Op::LH: {
m_regs[i.rd] = *(i16 *)&m_memory[m_regs[i.rs1] + i.imm]; m_regs[i.rd] = *(i16 *)&m_memory[m_regs[i.rs1] + i.imm];
}; break; }; break;
case Op::LHU: {
std::println(stderr, "LHU unimplemented");
exit(1);
}; break;
case Op::LUI: { case Op::LUI: {
m_regs[i.rd] = (i64)(i32)(i.imm << 12); m_regs[i.rd] = (i64)(i32)(i.imm << 12);
}; break; }; break;
case Op::LW: { case Op::LW: {
m_regs[i.rd] = *(i32 *)&m_memory[m_regs[i.rs1] + i.imm]; m_regs[i.rd] = *(i32 *)&m_memory[m_regs[i.rs1] + i.imm];
}; break; }; break;
case Op::LWU: {
std::println(stderr, "LWU unimplemented");
exit(1);
}; break;
case Op::MUL: { case Op::MUL: {
m_regs[i.rd] = m_regs[i.rs1] * m_regs[i.rs2]; m_regs[i.rd] = m_regs[i.rs1] * m_regs[i.rs2];
}; break; }; break;
@@ -640,10 +727,6 @@ public:
case Op::OR: { case Op::OR: {
m_regs[i.rd] = m_regs[i.rs1] | m_regs[i.rs2]; m_regs[i.rd] = m_regs[i.rs1] | m_regs[i.rs2];
}; break; }; break;
case Op::ORI: {
std::println(stderr, "ORI unimplemented");
exit(1);
}; break;
case Op::REM: { case Op::REM: {
if (m_regs[i.rs2] == 0) { if (m_regs[i.rs2] == 0) {
m_regs[i.rd] = m_regs[i.rs1]; m_regs[i.rd] = m_regs[i.rs1];
@@ -665,15 +748,12 @@ public:
m_regs[i.rd] = (i32)((u32)m_regs[i.rs1] % (u32)m_regs[i.rs2]); m_regs[i.rd] = (i32)((u32)m_regs[i.rs1] % (u32)m_regs[i.rs2]);
} }
}; break; }; break;
case Op::REMW: {
std::println(stderr, "REMW unimplemented");
exit(1);
}; break;
case Op::SB: { case Op::SB: {
u64 addr = m_regs[i.rs1] + i.imm; u64 addr = m_regs[i.rs1] + i.imm;
m_memory[addr] = m_regs[i.rs2]; m_memory[addr] = m_regs[i.rs2];
}; break; }; break;
case Op::SD: { case Op::SD:
case Op::C_SD: {
u64 addr = m_regs[i.rs1] + i.imm; u64 addr = m_regs[i.rs1] + i.imm;
*(u64 *)(&m_memory[addr]) = m_regs[i.rs2]; *(u64 *)(&m_memory[addr]) = m_regs[i.rs2];
}; break; }; break;
@@ -681,10 +761,6 @@ public:
u64 addr = m_regs[i.rs1] + i.imm; u64 addr = m_regs[i.rs1] + i.imm;
*(u16 *)(&m_memory[addr]) = m_regs[i.rs2]; *(u16 *)(&m_memory[addr]) = m_regs[i.rs2];
}; break; }; break;
case Op::SLL: {
std::println(stderr, "SLL unimplemented");
exit(1);
}; break;
case Op::SLLI: { case Op::SLLI: {
m_regs[i.rd] = m_regs[i.rs1] << i.shamt; m_regs[i.rd] = m_regs[i.rs1] << i.shamt;
}; break; }; break;
@@ -698,20 +774,12 @@ public:
case Op::SLT: { case Op::SLT: {
m_regs[i.rd] = (m_regs[i.rs1] < m_regs[i.rs2]) ? 1 : 0; m_regs[i.rd] = (m_regs[i.rs1] < m_regs[i.rs2]) ? 1 : 0;
}; break; }; break;
case Op::SLTI: {
std::println(stderr, "SLTI unimplemented");
exit(1);
}; break;
case Op::SLTIU: { case Op::SLTIU: {
m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)(i64)i.imm) ? 1 : 0; m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)(i64)i.imm) ? 1 : 0;
}; break; }; break;
case Op::SLTU: { case Op::SLTU: {
m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)m_regs[i.rs2]) ? 1 : 0; m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)m_regs[i.rs2]) ? 1 : 0;
}; break; }; break;
case Op::SRA: {
std::println(stderr, "SRA unimplemented");
exit(1);
}; break;
case Op::SRAI: { case Op::SRAI: {
m_regs[i.rd] = (i64)m_regs[i.rs1] >> i.shamt; m_regs[i.rd] = (i64)m_regs[i.rs1] >> i.shamt;
}; break; }; break;
@@ -721,10 +789,6 @@ public:
case Op::SRAW: { case Op::SRAW: {
m_regs[i.rd] = ((i32)m_regs[i.rs1]) >> ((u32)m_regs[i.rs2] & 0b11111); m_regs[i.rd] = ((i32)m_regs[i.rs1]) >> ((u32)m_regs[i.rs2] & 0b11111);
}; break; }; break;
case Op::SRL: {
std::println(stderr, "SRL unimplemented");
exit(1);
}; break;
case Op::SRLI: { case Op::SRLI: {
m_regs[i.rd] = (u64)m_regs[i.rs1] >> i.shamt; m_regs[i.rd] = (u64)m_regs[i.rs1] >> i.shamt;
}; break; }; break;
@@ -741,6 +805,7 @@ public:
case Op::SUBW: { case Op::SUBW: {
m_regs[i.rd] = (i32)(m_regs[i.rs1] - m_regs[i.rs2]); m_regs[i.rd] = (i32)(m_regs[i.rs1] - m_regs[i.rs2]);
}; break; }; break;
case Op::C_SW:
case Op::SW: { case Op::SW: {
u64 addr = m_regs[i.rs1] + i.imm; u64 addr = m_regs[i.rs1] + i.imm;
*(u32 *)(&m_memory[addr]) = m_regs[i.rs2]; *(u32 *)(&m_memory[addr]) = m_regs[i.rs2];
@@ -752,7 +817,7 @@ public:
m_regs[i.rd] = m_regs[i.rs1] ^ i.imm; m_regs[i.rd] = m_regs[i.rs1] ^ i.imm;
}; break; }; break;
default: { default: {
std::println(stderr, "Unrecognized Op: {}", (u64)i.op); std::println(stderr, "{} not implemented", OP_TABLE[i.op].mnemonic);
exit(1); exit(1);
}; break; }; break;
} }
@@ -885,16 +950,17 @@ private:
i.imm = (i.imm << 22) >> 22; i.imm = (i.imm << 22) >> 22;
i.op = Op::C_ADDI16SP; i.op = Op::C_ADDI16SP;
} else { } else {
i.imm = (((raw >> 12) & 0b1) << 17) | (((raw >> 2) & 0b11111) << 12); i.imm = (((raw >> 12) & 0b1) << 5) | ((raw >> 2) & 0b11111);
i.imm = (i.imm << 14) >> 14; i.imm = (i.imm << 26) >> 26;
i.op = Op::C_LUI; i.op = Op::C_LUI;
} }
}; break; }; break;
case 0b100: { case 0b100: {
u8 funct2 = (raw >> 10) & 0b11; u8 funct2 = (raw >> 10) & 0b11;
if (funct2 == 0b11) { if (funct2 == 0b11) {
i.rs1 = ((raw >> 7) & 0b111) + 8;
i.rd = i.rs1;
bool bit12 = (raw >> 12) & 0b1; bool bit12 = (raw >> 12) & 0b1;
i.rs2 = ((raw >> 2) & 0b111) + 8; i.rs2 = ((raw >> 2) & 0b111) + 8;
@@ -1522,7 +1588,6 @@ int main(int argc, char *argv[]) {
exe_bytes.clear(); exe_bytes.clear();
exe_bytes.shrink_to_fit(); exe_bytes.shrink_to_fit();
r.disassemble_all();
std::println("END DISASSEMBLY"); std::println("END DISASSEMBLY");
r.execute(); r.execute();