From aa07ee638c97c4f9ca0b9350a97edb093d2588f8 Mon Sep 17 00:00:00 2001 From: shadow cat Date: Sun, 23 Mar 2025 14:47:05 -0400 Subject: [PATCH] refactor asm more --- data/test.lang | 25 +++-- src/compiler/arch/mod.rs | 2 +- src/compiler/arch/{riscv64 => riscv}/asm.rs | 34 +++---- .../arch/{riscv64 => riscv}/compile.rs | 23 ++--- .../arch/{riscv64 => riscv/instr}/base.rs | 51 ++++++---- src/compiler/arch/riscv/instr/mod.rs | 8 ++ src/compiler/arch/riscv/instr/rv32i.rs | 68 +++++++++++++ src/compiler/arch/riscv/instr/rv32m.rs | 16 +++ src/compiler/arch/riscv/instr/string.rs | 27 +++++ src/compiler/arch/{riscv64 => riscv}/mod.rs | 8 +- src/compiler/arch/{riscv64 => riscv}/reg.rs | 75 +++++++------- src/compiler/arch/riscv/single.rs | 39 ++++++++ src/compiler/arch/riscv64/funct.rs | 96 ------------------ src/compiler/arch/riscv64/opcode.rs | 10 -- src/compiler/arch/riscv64/single.rs | 57 ----------- src/compiler/mod.rs | 2 +- src/ir/arch/riscv64.rs | 34 +++---- src/ir/lower/func.rs | 2 +- src/ir/upper/func.rs | 2 +- src/parser/v3/lower/arch/riscv64.rs | 98 +++++++++---------- src/parser/v3/lower/asm.rs | 2 +- 21 files changed, 329 insertions(+), 350 deletions(-) rename src/compiler/arch/{riscv64 => riscv}/asm.rs (86%) rename src/compiler/arch/{riscv64 => riscv}/compile.rs (92%) rename src/compiler/arch/{riscv64 => riscv/instr}/base.rs (58%) create mode 100644 src/compiler/arch/riscv/instr/mod.rs create mode 100644 src/compiler/arch/riscv/instr/rv32i.rs create mode 100644 src/compiler/arch/riscv/instr/rv32m.rs create mode 100644 src/compiler/arch/riscv/instr/string.rs rename src/compiler/arch/{riscv64 => riscv}/mod.rs (63%) rename src/compiler/arch/{riscv64 => riscv}/reg.rs (99%) create mode 100644 src/compiler/arch/riscv/single.rs delete mode 100644 src/compiler/arch/riscv64/funct.rs delete mode 100644 src/compiler/arch/riscv64/opcode.rs delete mode 100644 src/compiler/arch/riscv64/single.rs diff --git a/data/test.lang b/data/test.lang index aff7dd0..4182d37 100644 --- a/data/test.lang +++ b/data/test.lang @@ -5,7 +5,7 @@ fn start() { println("what"); print(tester()); arger("a", "b", "c"); - exit(sub(add(35, 5), 1)); + exit(mul(sub(add(5, 9), 1), 3)); } fn thinger() { @@ -17,8 +17,8 @@ fn unused() { } fn println(msg: slice<8>) { - print(msg); - print("\n"); + print(msg); + print("\n"); } fn print(msg: slice<8>) { @@ -42,6 +42,17 @@ fn add(a: 64, b: 64) -> 64 { c } +fn mul(a: 64, b: 64) -> 64 { + let c: 64 = 0; + asm (t0 = a, t1 = b, a0 = c) { + ld t0, 0, t0 + ld t1, 0, t1 + mul t0, t0, t1 + sd t0, 0, a0 + }; + c +} + fn sub(a: 64, b: 64) -> 64 { let c: 64 = 0; asm (t0 = a, t1 = b, a0 = c) { @@ -54,9 +65,9 @@ fn sub(a: 64, b: 64) -> 64 { } fn arger(a: slice<8>, b: slice<8>, c: slice<8>) { - print(a); - print(b); - println(c); + print(a); + print(b); + println(c); } fn exit(status: 64) { @@ -68,5 +79,5 @@ fn exit(status: 64) { } fn tester() -> slice<8> { - "hola\n" + "hola\n" } diff --git a/src/compiler/arch/mod.rs b/src/compiler/arch/mod.rs index ceb8572..fb27202 100644 --- a/src/compiler/arch/mod.rs +++ b/src/compiler/arch/mod.rs @@ -1 +1 @@ -pub mod riscv64; +pub mod riscv; diff --git a/src/compiler/arch/riscv64/asm.rs b/src/compiler/arch/riscv/asm.rs similarity index 86% rename from src/compiler/arch/riscv64/asm.rs rename to src/compiler/arch/riscv/asm.rs index 525fd74..ecc8086 100644 --- a/src/compiler/arch/riscv64/asm.rs +++ b/src/compiler/arch/riscv/asm.rs @@ -8,39 +8,33 @@ use super::*; #[derive(Debug, Clone)] pub enum LinkerInstruction { Op { - op: Op, - dest: Reg, - src1: Reg, - src2: Reg, - }, - OpF7 { - op: Op, + op: Funct3, funct: Funct7, dest: Reg, src1: Reg, src2: Reg, }, OpImm { - op: Op, + op: Funct3, dest: Reg, src: Reg, imm: i32, }, OpImmF7 { - op: Op, + op: Funct3, funct: Funct7, dest: Reg, src: Reg, imm: i32, }, Store { - width: Width, + width: Funct3, src: Reg, offset: i32, base: Reg, }, Load { - width: Width, + width: Funct3, dest: Reg, offset: i32, base: Reg, @@ -67,8 +61,8 @@ pub enum LinkerInstruction { }, } -pub const fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction { - opi(Op::Add, dest, src, imm) +pub fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction { + opi(op32i::ADD, dest, src, imm) } impl Instr for LinkerInstruction { @@ -81,18 +75,12 @@ impl Instr for LinkerInstruction { ) -> Option { let last = match self { Self::Op { - op, - dest, - src1, - src2, - } => opr(*op, *dest, *src1, *src2), - Self::OpF7 { op, funct, dest, src1, src2, - } => oprf7(*op, *funct, *dest, *src1, *src2), + } => opr(*op, *funct, *dest, *src1, *src2), Self::OpImm { op, dest, src, imm } => opi(*op, *dest, *src, BitsI32::new(*imm)), Self::OpImmF7 { op, @@ -155,7 +143,7 @@ impl Instr for LinkerInstruction { impl LinkerInstruction { pub fn addi(dest: Reg, src: Reg, imm: i32) -> Self { Self::OpImm { - op: Op::Add, + op: op32i::ADD, dest, src, imm, @@ -163,7 +151,7 @@ impl LinkerInstruction { } pub fn sd(src: Reg, offset: i32, base: Reg) -> Self { Self::Store { - width: Width::D, + width: width::D, src, offset, base, @@ -171,7 +159,7 @@ impl LinkerInstruction { } pub fn ld(dest: Reg, offset: i32, base: Reg) -> Self { Self::Load { - width: Width::D, + width: width::D, dest, offset, base, diff --git a/src/compiler/arch/riscv64/compile.rs b/src/compiler/arch/riscv/compile.rs similarity index 92% rename from src/compiler/arch/riscv64/compile.rs rename to src/compiler/arch/riscv/compile.rs index 5201e0f..7c981eb 100644 --- a/src/compiler/arch/riscv64/compile.rs +++ b/src/compiler/arch/riscv/compile.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::{ - compiler::{arch::riscv64::Reg, create_program, Addr}, + compiler::{arch::riscv::Reg, create_program, Addr}, ir::{ arch::riscv64::{RV64Instruction as AI, RegRef}, IRLInstruction as IRI, IRLProgram, Len, Size, @@ -24,18 +24,18 @@ fn mov_mem( mut len: Len, ) { let mut off = 0; - for width in Width::MAIN.iter().rev() { - let wl = width.len(); + for width in width::MAIN.iter().rev().copied() { + let wl = width::len(width); while len >= wl { v.extend([ LI::Load { - width: *width, + width, dest: temp, offset: src_offset + off, base: src, }, LI::Store { - width: *width, + width, src: temp, offset: dest_offset + off, base: dest, @@ -164,23 +164,12 @@ pub fn compile(program: IRLProgram) -> (Vec, Option) { base: r(base), }), AI::Op { - op, - dest, - src1, - src2, - } => v.push(LI::Op { - op, - dest: r(dest), - src1: r(src1), - src2: r(src2), - }), - AI::OpF7 { op, funct, dest, src1, src2, - } => v.push(LI::OpF7 { + } => v.push(LI::Op { op, funct, dest: r(dest), diff --git a/src/compiler/arch/riscv64/base.rs b/src/compiler/arch/riscv/instr/base.rs similarity index 58% rename from src/compiler/arch/riscv64/base.rs rename to src/compiler/arch/riscv/instr/base.rs index 7f4b3d0..b748afb 100644 --- a/src/compiler/arch/riscv64/base.rs +++ b/src/compiler/arch/riscv/instr/base.rs @@ -1,6 +1,7 @@ -use crate::util::Bits32; - -use super::{Funct3, Reg}; +use crate::{ + compiler::arch::riscv::Reg, + util::{Bits32, BitsI32}, +}; pub struct RawInstruction(u32); @@ -15,6 +16,18 @@ impl RawInstruction { } } +pub const SYSTEM: u32 = 0b1110011; +pub const LOAD: u32 = 0b0000011; +pub const STORE: u32 = 0b0100011; +pub const AUIPC: u32 = 0b0010111; +pub const IMM_OP: u32 = 0b0010011; +pub const OP: u32 = 0b0110011; +pub const JAL: u32 = 0b1101111; +pub const JALR: u32 = 0b1100111; + +pub type Funct3 = Bits32<2, 0>; +pub type Funct7 = Bits32<6, 0>; + pub const fn r_type( funct7: Bits32<6, 0>, rs2: Reg, @@ -33,13 +46,7 @@ pub const fn r_type( pub const fn i_type(imm: Bits32<11, 0>, rs1: Reg, funct: Funct3, rd: Reg, opcode: u32) -> I { I((imm.val() << 20) + (rs1.val() << 15) + (funct.val() << 12) + (rd.val() << 7) + opcode) } -pub const fn s_type( - rs2: Reg, - rs1: Reg, - funct3: Funct3, - imm: Bits32<11, 0>, - opcode: u32, -) -> I { +pub const fn s_type(rs2: Reg, rs1: Reg, funct3: Funct3, imm: Bits32<11, 0>, opcode: u32) -> I { I((imm.bits(11, 5) << 25) + (rs2.val() << 20) + (rs1.val() << 15) @@ -47,13 +54,7 @@ pub const fn s_type( + (imm.bits(4, 0) << 7) + opcode) } -pub const fn b_type( - rs2: Reg, - rs1: Reg, - funct3: Funct3, - imm: Bits32<12, 1>, - opcode: u32, -) -> I { +pub const fn b_type(rs2: Reg, rs1: Reg, funct3: Funct3, imm: Bits32<12, 1>, opcode: u32) -> I { I((imm.bit(12) << 31) + (imm.bits(10, 5) << 25) + (rs2.val() << 20) @@ -74,3 +75,19 @@ pub const fn j_type(imm: Bits32<20, 1>, rd: Reg, opcode: u32) -> I { + (rd.val() << 7) + opcode) } + +pub fn opr(op: Funct3, funct: Funct7, dest: Reg, src1: Reg, src2: Reg) -> I { + r_type(funct, src2, src1, op.into(), dest, OP) +} +pub fn opi(op: Funct3, dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction { + i_type(imm.to_u(), src, op.into(), dest, IMM_OP) +} +pub fn opif7(op: Funct3, funct: Funct7, dest: Reg, src: Reg, imm: BitsI32<4, 0>) -> I { + i_type( + Bits32::new(imm.to_u().val() + (funct.val() << 5)), + src, + op.into(), + dest, + IMM_OP, + ) +} diff --git a/src/compiler/arch/riscv/instr/mod.rs b/src/compiler/arch/riscv/instr/mod.rs new file mode 100644 index 0000000..858e2c8 --- /dev/null +++ b/src/compiler/arch/riscv/instr/mod.rs @@ -0,0 +1,8 @@ +mod base; +mod rv32i; +mod rv32m; +mod string; +pub use base::*; +pub use rv32i::*; +pub use rv32m::*; +pub use string::*; diff --git a/src/compiler/arch/riscv/instr/rv32i.rs b/src/compiler/arch/riscv/instr/rv32i.rs new file mode 100644 index 0000000..968bd5e --- /dev/null +++ b/src/compiler/arch/riscv/instr/rv32i.rs @@ -0,0 +1,68 @@ +use crate::{compiler::arch::riscv::Reg, util::Bits32}; + +use super::{opr, Funct3, Funct7, RawInstruction}; + +pub mod op32i { + use super::*; + + pub const ADD: Funct3 = Funct3::new(0b000); + pub const SL: Funct3 = Funct3::new(0b001); + pub const SLT: Funct3 = Funct3::new(0b010); + pub const SLTU: Funct3 = Funct3::new(0b011); + pub const XOR: Funct3 = Funct3::new(0b100); + pub const SR: Funct3 = Funct3::new(0b101); + pub const OR: Funct3 = Funct3::new(0b110); + pub const AND: Funct3 = Funct3::new(0b111); + + pub const LOGICAL: Funct7 = Funct7::new(0b0000000); + pub const ARITHMETIC: Funct7 = Funct7::new(0b0100000); + pub const F7ADD: Funct7 = Funct7::new(0b0000000); + pub const F7SUB: Funct7 = Funct7::new(0b0100000); + + pub const FUNCT7: Funct7 = Funct7::new(0b0000000); +} + +pub mod width { + use crate::ir::Len; + + use super::*; + pub const MAIN: [Funct3; 4] = [B, H, W, D]; + + pub const B: Funct3 = Funct3::new(0b000); + pub const H: Funct3 = Funct3::new(0b001); + pub const W: Funct3 = Funct3::new(0b010); + pub const D: Funct3 = Funct3::new(0b011); + pub const BU: Funct3 = Funct3::new(0b100); + pub const HU: Funct3 = Funct3::new(0b101); + pub const WU: Funct3 = Funct3::new(0b110); + + pub const fn str(w: Funct3) -> &'static str { + match w { + B => "b", + H => "h", + W => "w", + D => "d", + BU => "bu", + HU => "hu", + WU => "wu", + _ => unreachable!(), + } + } + + pub const fn len(w: Funct3) -> Len { + match w { + B => 1, + H => 2, + W => 4, + D => 8, + BU => 1, + HU => 2, + WU => 4, + _ => unreachable!(), + } + } +} + +pub fn opr32i(op: Funct3, dest: Reg, src1: Reg, src2: Reg) -> RawInstruction { + opr(op, Bits32::new(0), dest, src1, src2) +} diff --git a/src/compiler/arch/riscv/instr/rv32m.rs b/src/compiler/arch/riscv/instr/rv32m.rs new file mode 100644 index 0000000..cebe3ba --- /dev/null +++ b/src/compiler/arch/riscv/instr/rv32m.rs @@ -0,0 +1,16 @@ +use super::{Funct3, Funct7}; + +pub mod op32m { + use super::*; + pub const MUL: Funct3 = Funct3::new(0b000); + pub const MULH: Funct3 = Funct3::new(0b001); + pub const MULHSU: Funct3 = Funct3::new(0b010); + pub const MULHU: Funct3 = Funct3::new(0b011); + pub const DIV: Funct3 = Funct3::new(0b100); + pub const DIVU: Funct3 = Funct3::new(0b101); + pub const REM: Funct3 = Funct3::new(0b110); + pub const REMU: Funct3 = Funct3::new(0b111); + + pub const FUNCT7: Funct7 = Funct7::new(0b0000001); +} + diff --git a/src/compiler/arch/riscv/instr/string.rs b/src/compiler/arch/riscv/instr/string.rs new file mode 100644 index 0000000..51495d8 --- /dev/null +++ b/src/compiler/arch/riscv/instr/string.rs @@ -0,0 +1,27 @@ +use super::*; + +pub fn opstr(op: Funct3, funct: Funct7) -> &'static str { + match (op, funct) { + (op32i::SLT, op32i::FUNCT7) => "slt", + (op32i::SLTU, op32i::FUNCT7) => "sltu", + (op32i::XOR, op32i::FUNCT7) => "xor", + (op32i::OR, op32i::FUNCT7) => "or", + (op32i::AND, op32i::FUNCT7) => "and", + + (op32i::ADD, op32i::F7ADD) => "add", + (op32i::ADD, op32i::F7SUB) => "sub", + (op32i::SL, op32i::LOGICAL) => "sll", + (op32i::SR, op32i::LOGICAL) => "srl", + (op32i::SR, op32i::ARITHMETIC) => "sra", + + (op32m::MUL, op32m::FUNCT7) => "mul", + (op32m::MULH, op32m::FUNCT7) => "mulh", + (op32m::MULHSU, op32m::FUNCT7) => "mulhsu", + (op32m::MULHU, op32m::FUNCT7) => "mulhu", + (op32m::DIV, op32m::FUNCT7) => "div", + (op32m::DIVU, op32m::FUNCT7) => "divu", + (op32m::REM, op32m::FUNCT7) => "rem", + (op32m::REMU, op32m::FUNCT7) => "remu", + _ => "unknown", + } +} diff --git a/src/compiler/arch/riscv64/mod.rs b/src/compiler/arch/riscv/mod.rs similarity index 63% rename from src/compiler/arch/riscv64/mod.rs rename to src/compiler/arch/riscv/mod.rs index 42c48e9..bf762e7 100644 --- a/src/compiler/arch/riscv64/mod.rs +++ b/src/compiler/arch/riscv/mod.rs @@ -1,17 +1,13 @@ mod asm; -mod base; mod compile; -mod funct; -mod opcode; mod reg; mod single; +mod instr; use crate::util::BitsI32; -use base::*; -use opcode::*; use single::*; pub use asm::*; pub use compile::*; pub use reg::*; -pub use funct::*; +pub use instr::*; diff --git a/src/compiler/arch/riscv64/reg.rs b/src/compiler/arch/riscv/reg.rs similarity index 99% rename from src/compiler/arch/riscv64/reg.rs rename to src/compiler/arch/riscv/reg.rs index 92cea14..d76367a 100644 --- a/src/compiler/arch/riscv64/reg.rs +++ b/src/compiler/arch/riscv/reg.rs @@ -47,43 +47,6 @@ pub const t4: Reg = Reg(29); pub const t5: Reg = Reg(30); pub const t6: Reg = Reg(31); -// pub const ft0: Reg = Reg(0); -// pub const ft1: Reg = Reg(1); -// pub const ft2: Reg = Reg(2); -// pub const ft3: Reg = Reg(3); -// pub const ft4: Reg = Reg(4); -// pub const ft5: Reg = Reg(5); -// pub const ft6: Reg = Reg(6); -// pub const ft7: Reg = Reg(7); -// -// pub const fs0: Reg = Reg(8); -// pub const fs1: Reg = Reg(9); -// -// pub const fa0: Reg = Reg(10); -// pub const fa1: Reg = Reg(11); -// pub const fa2: Reg = Reg(12); -// pub const fa3: Reg = Reg(13); -// pub const fa4: Reg = Reg(14); -// pub const fa5: Reg = Reg(15); -// pub const fa6: Reg = Reg(16); -// pub const fa7: Reg = Reg(17); -// -// pub const fs2: Reg = Reg(18); -// pub const fs3: Reg = Reg(19); -// pub const fs4: Reg = Reg(20); -// pub const fs5: Reg = Reg(21); -// pub const fs6: Reg = Reg(22); -// pub const fs7: Reg = Reg(23); -// pub const fs8: Reg = Reg(24); -// pub const fs9: Reg = Reg(25); -// pub const fs10: Reg = Reg(26); -// pub const fs11: Reg = Reg(27); -// -// pub const ft8: Reg = Reg(28); -// pub const ft9: Reg = Reg(29); -// pub const ft10: Reg = Reg(30); -// pub const ft11: Reg = Reg(31); - impl Reg { #[inline] pub const fn val(&self) -> u32 { @@ -177,3 +140,41 @@ impl std::fmt::Debug for Reg { ) } } + +// pub const ft0: Reg = Reg(0); +// pub const ft1: Reg = Reg(1); +// pub const ft2: Reg = Reg(2); +// pub const ft3: Reg = Reg(3); +// pub const ft4: Reg = Reg(4); +// pub const ft5: Reg = Reg(5); +// pub const ft6: Reg = Reg(6); +// pub const ft7: Reg = Reg(7); +// +// pub const fs0: Reg = Reg(8); +// pub const fs1: Reg = Reg(9); +// +// pub const fa0: Reg = Reg(10); +// pub const fa1: Reg = Reg(11); +// pub const fa2: Reg = Reg(12); +// pub const fa3: Reg = Reg(13); +// pub const fa4: Reg = Reg(14); +// pub const fa5: Reg = Reg(15); +// pub const fa6: Reg = Reg(16); +// pub const fa7: Reg = Reg(17); +// +// pub const fs2: Reg = Reg(18); +// pub const fs3: Reg = Reg(19); +// pub const fs4: Reg = Reg(20); +// pub const fs5: Reg = Reg(21); +// pub const fs6: Reg = Reg(22); +// pub const fs7: Reg = Reg(23); +// pub const fs8: Reg = Reg(24); +// pub const fs9: Reg = Reg(25); +// pub const fs10: Reg = Reg(26); +// pub const fs11: Reg = Reg(27); +// +// pub const ft8: Reg = Reg(28); +// pub const ft9: Reg = Reg(29); +// pub const ft10: Reg = Reg(30); +// pub const ft11: Reg = Reg(31); + diff --git a/src/compiler/arch/riscv/single.rs b/src/compiler/arch/riscv/single.rs new file mode 100644 index 0000000..0e89008 --- /dev/null +++ b/src/compiler/arch/riscv/single.rs @@ -0,0 +1,39 @@ +use crate::util::{Bits32, BitsI32}; + +use super::*; + +use RawInstruction as I; + +pub const fn ecall() -> I { + i_type(Bits32::new(0), zero, Bits32::new(0), zero, SYSTEM) +} +pub const fn ebreak() -> I { + i_type(Bits32::new(1), zero, Bits32::new(0), zero, SYSTEM) +} +pub const fn auipc(dest: Reg, imm: BitsI32<31, 12>) -> I { + u_type(imm.to_u(), dest, AUIPC) +} + +pub const fn load(width: Funct3, dest: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { + i_type(offset.to_u(), base, width, dest, LOAD) +} + +pub const fn store(width: Funct3, src: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { + s_type(src, base, width, offset.to_u(), STORE) +} + +pub const fn jal(dest: Reg, offset: BitsI32<20, 1>) -> I { + j_type(offset.to_u(), dest, JAL) +} +pub const fn jalr(dest: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { + i_type(offset.to_u(), base, Bits32::new(0), dest, JALR) +} + +// pseudoinstructions that map to a single instruction + +pub const fn j(offset: BitsI32<20, 1>) -> I { + jal(zero, offset) +} +pub const fn ret() -> I { + jalr(zero, BitsI32::new(0), ra) +} diff --git a/src/compiler/arch/riscv64/funct.rs b/src/compiler/arch/riscv64/funct.rs deleted file mode 100644 index f06c335..0000000 --- a/src/compiler/arch/riscv64/funct.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::{ir::Len, util::Bits32}; - -pub type Funct3 = Bits32<2, 0>; -pub type Funct7 = Bits32<6, 0>; - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum Op { - Add = 0b000, - Sl = 0b001, - Slt = 0b010, - Sltu = 0b011, - Xor = 0b100, - Sr = 0b101, - Or = 0b110, - And = 0b111, -} - -impl Op { - pub const fn code(&self) -> Funct3 { - Funct3::new(*self as u32) - } - pub const fn str(&self) -> &str { - match self { - Op::Add => "add", - Op::Sl => "sl", - Op::Slt => "slt", - Op::Sltu => "sltu", - Op::Xor => "xor", - Op::Sr => "sr", - Op::Or => "or", - Op::And => "and", - } - } - pub fn fstr(&self, funct: Funct7) -> String { - match (self, funct) { - (Op::Add, funct7::ADD) => "add", - (Op::Add, funct7::SUB) => "sub", - (Op::Sl, funct7::LOGICAL) => "sll", - (Op::Sr, funct7::LOGICAL) => "srl", - (Op::Sr, funct7::ARITHMETIC) => "sra", - other => return self.str().to_string() + "?" - }.to_string() - } -} - -pub mod funct7 { - use super::Funct7; - - pub const LOGICAL: Funct7 = Funct7::new(0b0000000); - pub const ARITHMETIC: Funct7 = Funct7::new(0b0100000); - pub const ADD: Funct7 = Funct7::new(0b0000000); - pub const SUB: Funct7 = Funct7::new(0b0100000); -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum Width { - B = 0b000, - H = 0b001, - W = 0b010, - D = 0b011, - BU = 0b100, - HU = 0b101, - WU = 0b110, -} - -impl Width { - pub const MAIN: [Self; 4] = [Self::B, Self::H, Self::W, Self::D]; - - pub const fn code(&self) -> Funct3 { - Funct3::new(*self as u32) - } - pub const fn len(&self) -> Len { - match self { - Width::B => 1, - Width::H => 2, - Width::W => 4, - Width::D => 8, - Width::BU => 1, - Width::HU => 2, - Width::WU => 4, - } - } - pub const fn str(&self) -> &str { - match self { - Width::B => "b", - Width::H => "h", - Width::W => "w", - Width::D => "d", - Width::BU => "bu", - Width::HU => "hu", - Width::WU => "wu", - } - } -} diff --git a/src/compiler/arch/riscv64/opcode.rs b/src/compiler/arch/riscv64/opcode.rs deleted file mode 100644 index 56ed50d..0000000 --- a/src/compiler/arch/riscv64/opcode.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub const OPCODE_MASK: u32 = 0b1111111; - -pub const SYSTEM: u32 = 0b1110011; -pub const LOAD : u32 = 0b0000011; -pub const STORE : u32 = 0b0100011; -pub const AUIPC : u32 = 0b0010111; -pub const IMM_OP: u32 = 0b0010011; -pub const OP : u32 = 0b0110011; -pub const JAL : u32 = 0b1101111; -pub const JALR : u32 = 0b1100111; diff --git a/src/compiler/arch/riscv64/single.rs b/src/compiler/arch/riscv64/single.rs deleted file mode 100644 index 6f3ddb5..0000000 --- a/src/compiler/arch/riscv64/single.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::util::{Bits32, BitsI32}; - -use super::*; - -use RawInstruction as I; - -pub const fn ecall() -> I { - i_type(Bits32::new(0), zero, Bits32::new(0), zero, SYSTEM) -} -pub const fn ebreak() -> I { - i_type(Bits32::new(1), zero, Bits32::new(0), zero, SYSTEM) -} -pub const fn auipc(dest: Reg, imm: BitsI32<31, 12>) -> I { - u_type(imm.to_u(), dest, AUIPC) -} - -pub const fn load(width: Width, dest: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { - i_type(offset.to_u(), base, width.code(), dest, LOAD) -} - -pub const fn store(width: Width, src: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { - s_type(src, base, width.code(), offset.to_u(), STORE) -} - -pub const fn opr(op: Op, dest: Reg, src1: Reg, src2: Reg) -> I { - r_type(Bits32::new(0), src2, src1, op.code(), dest, OP) -} -pub const fn oprf7(op: Op, funct: Funct7, dest: Reg, src1: Reg, src2: Reg) -> I { - r_type(funct, src2, src1, op.code(), dest, OP) -} -pub const fn opi(op: Op, dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> I { - i_type(imm.to_u(), src, op.code(), dest, IMM_OP) -} -pub const fn opif7(op: Op, funct: Funct7, dest: Reg, src: Reg, imm: BitsI32<4, 0>) -> I { - i_type( - Bits32::new(imm.to_u().val() + (funct.val() << 5)), - src, - op.code(), - dest, - IMM_OP, - ) -} -pub const fn jal(dest: Reg, offset: BitsI32<20, 1>) -> I { - j_type(offset.to_u(), dest, JAL) -} -pub const fn jalr(dest: Reg, offset: BitsI32<11, 0>, base: Reg) -> I { - i_type(offset.to_u(), base, Bits32::new(0), dest, JALR) -} - -// pseudoinstructions that map to a single instruction - -pub const fn j(offset: BitsI32<20, 1>) -> I { - jal(zero, offset) -} -pub const fn ret() -> I { - jalr(zero, BitsI32::new(0), ra) -} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 8d82a69..d7aab08 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -8,6 +8,6 @@ pub use program::*; use crate::ir::IRLProgram; pub fn compile(program: IRLProgram) -> Vec { - let (compiled, start) = arch::riscv64::compile(program); + let (compiled, start) = arch::riscv::compile(program); elf::create(compiled, start.expect("no start method found")) } diff --git a/src/ir/arch/riscv64.rs b/src/ir/arch/riscv64.rs index 3c56aa8..39ec2bf 100644 --- a/src/ir/arch/riscv64.rs +++ b/src/ir/arch/riscv64.rs @@ -1,4 +1,4 @@ -use crate::{compiler::arch::riscv64::*, ir::VarInst}; +use crate::{compiler::arch::riscv::*, ir::VarInst}; #[derive(Copy, Clone)] pub enum RV64Instruction { @@ -16,38 +16,32 @@ pub enum RV64Instruction { src: VarInst, }, Load { - width: Width, + width: Funct3, dest: RegRef, offset: i64, base: RegRef, }, Store { - width: Width, + width: Funct3, src: RegRef, offset: i64, base: RegRef, }, Op { - op: Op, - dest: RegRef, - src1: RegRef, - src2: RegRef, - }, - OpF7 { - op: Op, + op: Funct3, funct: Funct7, dest: RegRef, src1: RegRef, src2: RegRef, }, OpImm { - op: Op, + op: Funct3, dest: RegRef, src: RegRef, imm: i64, }, OpImmF7 { - op: Op, + op: Funct3, funct: Funct7, dest: RegRef, src: RegRef, @@ -82,28 +76,22 @@ impl std::fmt::Debug for RV64Instruction { dest, offset, base, - } => write!(f, "l{} {dest:?}, {offset}({base:?})", width.str()), + } => write!(f, "l{} {dest:?}, {offset}({base:?})", width::str(*width)), Self::Store { width, src, offset, base, - } => write!(f, "s{} {src:?}, {offset}({base:?})", width.str()), + } => write!(f, "s{} {src:?}, {offset}({base:?})", width::str(*width)), Self::Op { - op, - dest, - src1, - src2, - } => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", op.str()), - Self::OpF7 { op, funct, dest, src1, src2, - } => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", op.fstr(*funct)), + } => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", opstr(*op, *funct)), Self::OpImm { op, dest, src, imm } => { - write!(f, "{}i {dest:?}, {src:?}, {imm}", op.str()) + write!(f, "{}i {dest:?}, {src:?}, {imm}", opstr(*op, op32i::FUNCT7)) } Self::OpImmF7 { op, @@ -111,7 +99,7 @@ impl std::fmt::Debug for RV64Instruction { dest, src, imm, - } => write!(f, "{}i {dest:?}, {src:?}, {imm}", op.fstr(*funct)), + } => write!(f, "{}i {dest:?}, {src:?}, {imm}", opstr(*op, *funct)), } } } diff --git a/src/ir/lower/func.rs b/src/ir/lower/func.rs index 42ad338..3223c19 100644 --- a/src/ir/lower/func.rs +++ b/src/ir/lower/func.rs @@ -1,5 +1,5 @@ use super::*; -use crate::compiler::arch::riscv64::Reg; +use crate::compiler::arch::riscv::Reg; use arch::riscv64::RV64Instruction; use std::collections::HashMap; diff --git a/src/ir/upper/func.rs b/src/ir/upper/func.rs index 42d1a01..2e5af42 100644 --- a/src/ir/upper/func.rs +++ b/src/ir/upper/func.rs @@ -1,7 +1,7 @@ use std::fmt::Write; use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, Type, VarID}; -use crate::{common::FileSpan, compiler::arch::riscv64::Reg, util::Padder}; +use crate::{common::FileSpan, compiler::arch::riscv::Reg, util::Padder}; pub struct IRUFunction { pub name: String, diff --git a/src/parser/v3/lower/arch/riscv64.rs b/src/parser/v3/lower/arch/riscv64.rs index f9a4055..bbe18e6 100644 --- a/src/parser/v3/lower/arch/riscv64.rs +++ b/src/parser/v3/lower/arch/riscv64.rs @@ -1,6 +1,6 @@ use super::{FnLowerCtx, Node, PAsmArg, PIdent, PInstruction}; use crate::{ - compiler::arch::riscv64::*, + compiler::arch::riscv::*, ir::{ arch::riscv64::{RV64Instruction, RegRef}, VarInst, @@ -11,22 +11,7 @@ impl RV64Instruction { pub fn parse(inst: &PInstruction, ctx: &mut FnLowerCtx) -> Option { let args = &inst.args[..]; let opstr = &**inst.op.inner.as_ref()?; - let op = |ctx: &mut FnLowerCtx<'_, '_>, op: Op| -> Option { - let [dest, src1, src2] = args else { - ctx.err(format!("{opstr} requires 3 arguments")); - return None; - }; - let dest = RegRef::from_arg(dest, ctx)?; - let src1 = RegRef::from_arg(src1, ctx)?; - let src2 = RegRef::from_arg(src2, ctx)?; - Some(Self::Op { - op, - dest, - src1, - src2, - }) - }; - let opi = |ctx: &mut FnLowerCtx<'_, '_>, op: Op| -> Option { + let opi = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3| -> Option { let [dest, src, imm] = args else { ctx.err(format!("{opstr} requires 3 arguments")); return None; @@ -36,7 +21,7 @@ impl RV64Instruction { let imm = i64_from_arg(imm, ctx)?; Some(Self::OpImm { op, dest, src, imm }) }; - let opf7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Op, funct: Funct7| -> Option { + let op = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option { let [dest, src1, src2] = args else { ctx.err(format!("{opstr} requires 3 arguments")); return None; @@ -44,7 +29,7 @@ impl RV64Instruction { let dest = RegRef::from_arg(dest, ctx)?; let src1 = RegRef::from_arg(src1, ctx)?; let src2 = RegRef::from_arg(src2, ctx)?; - Some(Self::OpF7 { + Some(Self::Op { op, funct, dest, @@ -52,7 +37,7 @@ impl RV64Instruction { src2, }) }; - let opif7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Op, funct: Funct7| -> Option { + let opif7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option { let [dest, src, imm] = args else { ctx.err(format!("{opstr} requires 3 arguments")); return None; @@ -68,7 +53,7 @@ impl RV64Instruction { imm, }) }; - let store = |ctx: &mut FnLowerCtx<'_, '_>, width: Width| -> Option { + let store = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option { let [src, offset, base] = args else { ctx.err(format!("{opstr} requires 3 arguments")); return None; @@ -83,7 +68,7 @@ impl RV64Instruction { base, }) }; - let load = |ctx: &mut FnLowerCtx<'_, '_>, width: Width| -> Option { + let load = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option { let [dest, offset, base] = args else { ctx.err("ld requires 3 arguments".to_string()); return None; @@ -128,40 +113,49 @@ impl RV64Instruction { Self::Mv { dest, src } } - "lb" => load(ctx, Width::B)?, - "lh" => load(ctx, Width::H)?, - "lw" => load(ctx, Width::W)?, - "ld" => load(ctx, Width::D)?, - "lbu" => load(ctx, Width::BU)?, - "lhu" => load(ctx, Width::HU)?, - "lwu" => load(ctx, Width::WU)?, + "lb" => load(ctx, width::B)?, + "lh" => load(ctx, width::H)?, + "lw" => load(ctx, width::W)?, + "ld" => load(ctx, width::D)?, + "lbu" => load(ctx, width::BU)?, + "lhu" => load(ctx, width::HU)?, + "lwu" => load(ctx, width::WU)?, - "sb" => store(ctx, Width::B)?, - "sh" => store(ctx, Width::H)?, - "sw" => store(ctx, Width::W)?, - "sd" => store(ctx, Width::D)?, + "sb" => store(ctx, width::B)?, + "sh" => store(ctx, width::H)?, + "sw" => store(ctx, width::W)?, + "sd" => store(ctx, width::D)?, - "addi" => opi(ctx, Op::Add)?, - "slti" => opi(ctx, Op::Slt)?, - "sltiu" => opi(ctx, Op::Sltu)?, - "xori" => opi(ctx, Op::Xor)?, - "ori" => opi(ctx, Op::Or)?, - "andi" => opi(ctx, Op::And)?, + "addi" => opi(ctx, op32i::ADD)?, + "slti" => opi(ctx, op32i::SLT)?, + "sltiu" => opi(ctx, op32i::SLTU)?, + "xori" => opi(ctx, op32i::XOR)?, + "ori" => opi(ctx, op32i::OR)?, + "andi" => opi(ctx, op32i::AND)?, - "slli" => opif7(ctx, Op::Sl, funct7::LOGICAL)?, - "srli" => opif7(ctx, Op::Sr, funct7::LOGICAL)?, - "srla" => opif7(ctx, Op::Sr, funct7::ARITHMETIC)?, + "slli" => opif7(ctx, op32i::SL, op32i::LOGICAL)?, + "srli" => opif7(ctx, op32i::SR, op32i::LOGICAL)?, + "srla" => opif7(ctx, op32i::SR, op32i::ARITHMETIC)?, - "add" => opf7(ctx, Op::Add, funct7::ADD)?, - "sub" => opf7(ctx, Op::Add, funct7::SUB)?, - "sll" => op(ctx, Op::Sl)?, - "slt" => op(ctx, Op::Slt)?, - "sltu" => op(ctx, Op::Sltu)?, - "xor" => op(ctx, Op::Xor)?, - "srl" => opf7(ctx, Op::Sr, funct7::LOGICAL)?, - "sra" => opf7(ctx, Op::Sr, funct7::ARITHMETIC)?, - "or" => op(ctx, Op::Or)?, - "and" => op(ctx, Op::And)?, + "add" => op(ctx, op32i::ADD, op32i::F7ADD)?, + "sub" => op(ctx, op32i::ADD, op32i::F7SUB)?, + "sll" => op(ctx, op32i::SL, op32i::FUNCT7)?, + "slt" => op(ctx, op32i::SLT, op32i::FUNCT7)?, + "sltu" => op(ctx, op32i::SLTU, op32i::FUNCT7)?, + "xor" => op(ctx, op32i::XOR, op32i::FUNCT7)?, + "srl" => op(ctx, op32i::SR, op32i::LOGICAL)?, + "sra" => op(ctx, op32i::SR, op32i::ARITHMETIC)?, + "or" => op(ctx, op32i::OR, op32i::FUNCT7)?, + "and" => op(ctx, op32i::AND, op32i::FUNCT7)?, + + "mul" => op(ctx, op32m::MUL, op32m::FUNCT7)?, + "mulh" => op(ctx, op32m::MULH, op32m::FUNCT7)?, + "mulhsu" => op(ctx, op32m::MULHSU, op32m::FUNCT7)?, + "mulhu" => op(ctx, op32m::MULHU, op32m::FUNCT7)?, + "div" => op(ctx, op32m::DIV, op32m::FUNCT7)?, + "divu" => op(ctx, op32m::DIVU, op32m::FUNCT7)?, + "rem" => op(ctx, op32m::REM, op32m::FUNCT7)?, + "remu" => op(ctx, op32m::REMU, op32m::FUNCT7)?, w => { ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w)); diff --git a/src/parser/v3/lower/asm.rs b/src/parser/v3/lower/asm.rs index b65aeb8..232bbb6 100644 --- a/src/parser/v3/lower/asm.rs +++ b/src/parser/v3/lower/asm.rs @@ -1,5 +1,5 @@ use crate::{ - compiler::arch::riscv64::Reg, + compiler::arch::riscv::Reg, ir::{arch::riscv64::RV64Instruction, IRUInstruction, VarInst}, };