From 2252e1fa757b77328810a5b35ab14da0f2d3d4ec Mon Sep 17 00:00:00 2001 From: Toni Date: Mon, 9 Mar 2026 16:23:45 +0100 Subject: [PATCH] we can now execute crt0 --- riscv64.cc | 163 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 49 deletions(-) diff --git a/riscv64.cc b/riscv64.cc index 5307852..e4a75fd 100644 --- a/riscv64.cc +++ b/riscv64.cc @@ -80,9 +80,9 @@ enum Op { C_OR, C_SD, C_SDSP, + C_SLLI, C_SRAI, C_SRLI, - C_SLLI, C_SUB, C_SUBW, C_SW, @@ -171,6 +171,7 @@ enum class Format { I_SHIFT, S, B, + CB, U, J, CI, @@ -199,9 +200,9 @@ static constexpr std::array OP_TABLE = {{ {"bne", Format::B}, {"c.add", Format::CR}, {"c.addi", Format::CI}, {"c.addiw", Format::CI}, {"c.addi16sp", Format::CI}, {"c.addi4spn", Format::CI}, - {"c.addw", Format::CI}, {"c.and", Format::CR}, - {"c.andi", Format::CI}, {"c.beqz", Format::B}, - {"c.bnez", Format::B}, {"c.ebreak", Format::CR}, + {"c.addw", Format::CR}, {"c.and", Format::CR}, + {"c.andi", Format::CI}, {"c.beqz", Format::CB}, + {"c.bnez", Format::CB}, {"c.ebreak", Format::NONE}, {"c.fldsp", Format::CSS}, {"c.j", Format::CJ}, {"c.jalr", Format::CR1}, {"c.jr", Format::CR1}, {"c.ld", Format::CL}, {"c.ldsp", Format::CL}, @@ -334,6 +335,9 @@ public: std::println("{} {}, {}, {}", def.mnemonic, REGS[ins.rs1], REGS[ins.rs2], ins.imm); break; + case Format::CB: + std::println("{} {}, {}", def.mnemonic, REGS[ins.rs1], ins.imm); + break; case Format::J: std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], ins.imm); break; @@ -452,8 +456,10 @@ public: } }; break; case Op::BGEU: { - std::println(stderr, "BGEU unimplemented"); - exit(1); + if ((u64)m_regs[i.rs1] >= (u64)m_regs[i.rs2]) { + m_pc += i.imm; + continue; + } }; break; case Op::BLT: { if (m_regs[i.rs1] < m_regs[i.rs2]) { @@ -473,6 +479,92 @@ public: continue; } }; 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: { if (m_regs[i.rs2] == 0) { m_regs[i.rd] = -1; @@ -480,10 +572,6 @@ public: m_regs[i.rd] = m_regs[i.rs1] / m_regs[i.rs2]; } }; break; - case Op::DIVU: { - std::println(stderr, "DIVU unimplemented"); - exit(1); - }; break; case Op::DIVUW: { if (m_regs[i.rs2] == 0) { m_regs[i.rd] = -1LL; @@ -540,10 +628,17 @@ public: std::cout.put(m_memory[i]); } }; break; - case 93: { // exit + case 93: // exit + case 94: { // exit_group std::println("Program exited with code {}.", m_regs[10]); return; }; 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 i64 tv_addr = m_regs[10]; i64 tz_addr = m_regs[11]; @@ -590,20 +685,12 @@ public: case Op::LH: { m_regs[i.rd] = *(i16 *)&m_memory[m_regs[i.rs1] + i.imm]; }; break; - case Op::LHU: { - std::println(stderr, "LHU unimplemented"); - exit(1); - }; break; case Op::LUI: { m_regs[i.rd] = (i64)(i32)(i.imm << 12); }; break; case Op::LW: { m_regs[i.rd] = *(i32 *)&m_memory[m_regs[i.rs1] + i.imm]; }; break; - case Op::LWU: { - std::println(stderr, "LWU unimplemented"); - exit(1); - }; break; case Op::MUL: { m_regs[i.rd] = m_regs[i.rs1] * m_regs[i.rs2]; }; break; @@ -640,10 +727,6 @@ public: case Op::OR: { m_regs[i.rd] = m_regs[i.rs1] | m_regs[i.rs2]; }; break; - case Op::ORI: { - std::println(stderr, "ORI unimplemented"); - exit(1); - }; break; case Op::REM: { if (m_regs[i.rs2] == 0) { 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]); } }; break; - case Op::REMW: { - std::println(stderr, "REMW unimplemented"); - exit(1); - }; break; case Op::SB: { u64 addr = m_regs[i.rs1] + i.imm; m_memory[addr] = m_regs[i.rs2]; }; break; - case Op::SD: { + case Op::SD: + case Op::C_SD: { u64 addr = m_regs[i.rs1] + i.imm; *(u64 *)(&m_memory[addr]) = m_regs[i.rs2]; }; break; @@ -681,10 +761,6 @@ public: u64 addr = m_regs[i.rs1] + i.imm; *(u16 *)(&m_memory[addr]) = m_regs[i.rs2]; }; break; - case Op::SLL: { - std::println(stderr, "SLL unimplemented"); - exit(1); - }; break; case Op::SLLI: { m_regs[i.rd] = m_regs[i.rs1] << i.shamt; }; break; @@ -698,20 +774,12 @@ public: case Op::SLT: { m_regs[i.rd] = (m_regs[i.rs1] < m_regs[i.rs2]) ? 1 : 0; }; break; - case Op::SLTI: { - std::println(stderr, "SLTI unimplemented"); - exit(1); - }; break; case Op::SLTIU: { m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)(i64)i.imm) ? 1 : 0; }; break; case Op::SLTU: { m_regs[i.rd] = ((u64)m_regs[i.rs1] < (u64)m_regs[i.rs2]) ? 1 : 0; }; break; - case Op::SRA: { - std::println(stderr, "SRA unimplemented"); - exit(1); - }; break; case Op::SRAI: { m_regs[i.rd] = (i64)m_regs[i.rs1] >> i.shamt; }; break; @@ -721,10 +789,6 @@ public: case Op::SRAW: { m_regs[i.rd] = ((i32)m_regs[i.rs1]) >> ((u32)m_regs[i.rs2] & 0b11111); }; break; - case Op::SRL: { - std::println(stderr, "SRL unimplemented"); - exit(1); - }; break; case Op::SRLI: { m_regs[i.rd] = (u64)m_regs[i.rs1] >> i.shamt; }; break; @@ -741,6 +805,7 @@ public: case Op::SUBW: { m_regs[i.rd] = (i32)(m_regs[i.rs1] - m_regs[i.rs2]); }; break; + case Op::C_SW: case Op::SW: { u64 addr = m_regs[i.rs1] + i.imm; *(u32 *)(&m_memory[addr]) = m_regs[i.rs2]; @@ -752,7 +817,7 @@ public: m_regs[i.rd] = m_regs[i.rs1] ^ i.imm; }; break; default: { - std::println(stderr, "Unrecognized Op: {}", (u64)i.op); + std::println(stderr, "{} not implemented", OP_TABLE[i.op].mnemonic); exit(1); }; break; } @@ -885,16 +950,17 @@ private: i.imm = (i.imm << 22) >> 22; i.op = Op::C_ADDI16SP; } else { - i.imm = (((raw >> 12) & 0b1) << 17) | (((raw >> 2) & 0b11111) << 12); - i.imm = (i.imm << 14) >> 14; + i.imm = (((raw >> 12) & 0b1) << 5) | ((raw >> 2) & 0b11111); + i.imm = (i.imm << 26) >> 26; i.op = Op::C_LUI; } - }; break; case 0b100: { u8 funct2 = (raw >> 10) & 0b11; if (funct2 == 0b11) { + i.rs1 = ((raw >> 7) & 0b111) + 8; + i.rd = i.rs1; bool bit12 = (raw >> 12) & 0b1; i.rs2 = ((raw >> 2) & 0b111) + 8; @@ -1522,7 +1588,6 @@ int main(int argc, char *argv[]) { exe_bytes.clear(); exe_bytes.shrink_to_fit(); - r.disassemble_all(); std::println("END DISASSEMBLY"); r.execute();