refactor asm more
This commit is contained in:
@@ -5,7 +5,7 @@ fn start() {
|
|||||||
println("what");
|
println("what");
|
||||||
print(tester());
|
print(tester());
|
||||||
arger("a", "b", "c");
|
arger("a", "b", "c");
|
||||||
exit(sub(add(35, 5), 1));
|
exit(mul(sub(add(5, 9), 1), 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thinger() {
|
fn thinger() {
|
||||||
@@ -42,6 +42,17 @@ fn add(a: 64, b: 64) -> 64 {
|
|||||||
c
|
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 {
|
fn sub(a: 64, b: 64) -> 64 {
|
||||||
let c: 64 = 0;
|
let c: 64 = 0;
|
||||||
asm (t0 = a, t1 = b, a0 = c) {
|
asm (t0 = a, t1 = b, a0 = c) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
pub mod riscv64;
|
pub mod riscv;
|
||||||
|
|||||||
@@ -8,39 +8,33 @@ use super::*;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum LinkerInstruction {
|
pub enum LinkerInstruction {
|
||||||
Op {
|
Op {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
dest: Reg,
|
|
||||||
src1: Reg,
|
|
||||||
src2: Reg,
|
|
||||||
},
|
|
||||||
OpF7 {
|
|
||||||
op: Op,
|
|
||||||
funct: Funct7,
|
funct: Funct7,
|
||||||
dest: Reg,
|
dest: Reg,
|
||||||
src1: Reg,
|
src1: Reg,
|
||||||
src2: Reg,
|
src2: Reg,
|
||||||
},
|
},
|
||||||
OpImm {
|
OpImm {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
dest: Reg,
|
dest: Reg,
|
||||||
src: Reg,
|
src: Reg,
|
||||||
imm: i32,
|
imm: i32,
|
||||||
},
|
},
|
||||||
OpImmF7 {
|
OpImmF7 {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
funct: Funct7,
|
funct: Funct7,
|
||||||
dest: Reg,
|
dest: Reg,
|
||||||
src: Reg,
|
src: Reg,
|
||||||
imm: i32,
|
imm: i32,
|
||||||
},
|
},
|
||||||
Store {
|
Store {
|
||||||
width: Width,
|
width: Funct3,
|
||||||
src: Reg,
|
src: Reg,
|
||||||
offset: i32,
|
offset: i32,
|
||||||
base: Reg,
|
base: Reg,
|
||||||
},
|
},
|
||||||
Load {
|
Load {
|
||||||
width: Width,
|
width: Funct3,
|
||||||
dest: Reg,
|
dest: Reg,
|
||||||
offset: i32,
|
offset: i32,
|
||||||
base: Reg,
|
base: Reg,
|
||||||
@@ -67,8 +61,8 @@ pub enum LinkerInstruction {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction {
|
pub fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> RawInstruction {
|
||||||
opi(Op::Add, dest, src, imm)
|
opi(op32i::ADD, dest, src, imm)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instr for LinkerInstruction {
|
impl Instr for LinkerInstruction {
|
||||||
@@ -81,18 +75,12 @@ impl Instr for LinkerInstruction {
|
|||||||
) -> Option<Symbol> {
|
) -> Option<Symbol> {
|
||||||
let last = match self {
|
let last = match self {
|
||||||
Self::Op {
|
Self::Op {
|
||||||
op,
|
|
||||||
dest,
|
|
||||||
src1,
|
|
||||||
src2,
|
|
||||||
} => opr(*op, *dest, *src1, *src2),
|
|
||||||
Self::OpF7 {
|
|
||||||
op,
|
op,
|
||||||
funct,
|
funct,
|
||||||
dest,
|
dest,
|
||||||
src1,
|
src1,
|
||||||
src2,
|
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::OpImm { op, dest, src, imm } => opi(*op, *dest, *src, BitsI32::new(*imm)),
|
||||||
Self::OpImmF7 {
|
Self::OpImmF7 {
|
||||||
op,
|
op,
|
||||||
@@ -155,7 +143,7 @@ impl Instr for LinkerInstruction {
|
|||||||
impl LinkerInstruction {
|
impl LinkerInstruction {
|
||||||
pub fn addi(dest: Reg, src: Reg, imm: i32) -> Self {
|
pub fn addi(dest: Reg, src: Reg, imm: i32) -> Self {
|
||||||
Self::OpImm {
|
Self::OpImm {
|
||||||
op: Op::Add,
|
op: op32i::ADD,
|
||||||
dest,
|
dest,
|
||||||
src,
|
src,
|
||||||
imm,
|
imm,
|
||||||
@@ -163,7 +151,7 @@ impl LinkerInstruction {
|
|||||||
}
|
}
|
||||||
pub fn sd(src: Reg, offset: i32, base: Reg) -> Self {
|
pub fn sd(src: Reg, offset: i32, base: Reg) -> Self {
|
||||||
Self::Store {
|
Self::Store {
|
||||||
width: Width::D,
|
width: width::D,
|
||||||
src,
|
src,
|
||||||
offset,
|
offset,
|
||||||
base,
|
base,
|
||||||
@@ -171,7 +159,7 @@ impl LinkerInstruction {
|
|||||||
}
|
}
|
||||||
pub fn ld(dest: Reg, offset: i32, base: Reg) -> Self {
|
pub fn ld(dest: Reg, offset: i32, base: Reg) -> Self {
|
||||||
Self::Load {
|
Self::Load {
|
||||||
width: Width::D,
|
width: width::D,
|
||||||
dest,
|
dest,
|
||||||
offset,
|
offset,
|
||||||
base,
|
base,
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
compiler::{arch::riscv64::Reg, create_program, Addr},
|
compiler::{arch::riscv::Reg, create_program, Addr},
|
||||||
ir::{
|
ir::{
|
||||||
arch::riscv64::{RV64Instruction as AI, RegRef},
|
arch::riscv64::{RV64Instruction as AI, RegRef},
|
||||||
IRLInstruction as IRI, IRLProgram, Len, Size,
|
IRLInstruction as IRI, IRLProgram, Len, Size,
|
||||||
@@ -24,18 +24,18 @@ fn mov_mem(
|
|||||||
mut len: Len,
|
mut len: Len,
|
||||||
) {
|
) {
|
||||||
let mut off = 0;
|
let mut off = 0;
|
||||||
for width in Width::MAIN.iter().rev() {
|
for width in width::MAIN.iter().rev().copied() {
|
||||||
let wl = width.len();
|
let wl = width::len(width);
|
||||||
while len >= wl {
|
while len >= wl {
|
||||||
v.extend([
|
v.extend([
|
||||||
LI::Load {
|
LI::Load {
|
||||||
width: *width,
|
width,
|
||||||
dest: temp,
|
dest: temp,
|
||||||
offset: src_offset + off,
|
offset: src_offset + off,
|
||||||
base: src,
|
base: src,
|
||||||
},
|
},
|
||||||
LI::Store {
|
LI::Store {
|
||||||
width: *width,
|
width,
|
||||||
src: temp,
|
src: temp,
|
||||||
offset: dest_offset + off,
|
offset: dest_offset + off,
|
||||||
base: dest,
|
base: dest,
|
||||||
@@ -164,23 +164,12 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
|
|||||||
base: r(base),
|
base: r(base),
|
||||||
}),
|
}),
|
||||||
AI::Op {
|
AI::Op {
|
||||||
op,
|
|
||||||
dest,
|
|
||||||
src1,
|
|
||||||
src2,
|
|
||||||
} => v.push(LI::Op {
|
|
||||||
op,
|
|
||||||
dest: r(dest),
|
|
||||||
src1: r(src1),
|
|
||||||
src2: r(src2),
|
|
||||||
}),
|
|
||||||
AI::OpF7 {
|
|
||||||
op,
|
op,
|
||||||
funct,
|
funct,
|
||||||
dest,
|
dest,
|
||||||
src1,
|
src1,
|
||||||
src2,
|
src2,
|
||||||
} => v.push(LI::OpF7 {
|
} => v.push(LI::Op {
|
||||||
op,
|
op,
|
||||||
funct,
|
funct,
|
||||||
dest: r(dest),
|
dest: r(dest),
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::util::Bits32;
|
use crate::{
|
||||||
|
compiler::arch::riscv::Reg,
|
||||||
use super::{Funct3, Reg};
|
util::{Bits32, BitsI32},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct RawInstruction(u32);
|
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(
|
pub const fn r_type(
|
||||||
funct7: Bits32<6, 0>,
|
funct7: Bits32<6, 0>,
|
||||||
rs2: Reg,
|
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 {
|
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)
|
I((imm.val() << 20) + (rs1.val() << 15) + (funct.val() << 12) + (rd.val() << 7) + opcode)
|
||||||
}
|
}
|
||||||
pub const fn s_type(
|
pub const fn s_type(rs2: Reg, rs1: Reg, funct3: Funct3, imm: Bits32<11, 0>, opcode: u32) -> I {
|
||||||
rs2: Reg,
|
|
||||||
rs1: Reg,
|
|
||||||
funct3: Funct3,
|
|
||||||
imm: Bits32<11, 0>,
|
|
||||||
opcode: u32,
|
|
||||||
) -> I {
|
|
||||||
I((imm.bits(11, 5) << 25)
|
I((imm.bits(11, 5) << 25)
|
||||||
+ (rs2.val() << 20)
|
+ (rs2.val() << 20)
|
||||||
+ (rs1.val() << 15)
|
+ (rs1.val() << 15)
|
||||||
@@ -47,13 +54,7 @@ pub const fn s_type(
|
|||||||
+ (imm.bits(4, 0) << 7)
|
+ (imm.bits(4, 0) << 7)
|
||||||
+ opcode)
|
+ opcode)
|
||||||
}
|
}
|
||||||
pub const fn b_type(
|
pub const fn b_type(rs2: Reg, rs1: Reg, funct3: Funct3, imm: Bits32<12, 1>, opcode: u32) -> I {
|
||||||
rs2: Reg,
|
|
||||||
rs1: Reg,
|
|
||||||
funct3: Funct3,
|
|
||||||
imm: Bits32<12, 1>,
|
|
||||||
opcode: u32,
|
|
||||||
) -> I {
|
|
||||||
I((imm.bit(12) << 31)
|
I((imm.bit(12) << 31)
|
||||||
+ (imm.bits(10, 5) << 25)
|
+ (imm.bits(10, 5) << 25)
|
||||||
+ (rs2.val() << 20)
|
+ (rs2.val() << 20)
|
||||||
@@ -74,3 +75,19 @@ pub const fn j_type(imm: Bits32<20, 1>, rd: Reg, opcode: u32) -> I {
|
|||||||
+ (rd.val() << 7)
|
+ (rd.val() << 7)
|
||||||
+ opcode)
|
+ 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
8
src/compiler/arch/riscv/instr/mod.rs
Normal file
8
src/compiler/arch/riscv/instr/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
mod base;
|
||||||
|
mod rv32i;
|
||||||
|
mod rv32m;
|
||||||
|
mod string;
|
||||||
|
pub use base::*;
|
||||||
|
pub use rv32i::*;
|
||||||
|
pub use rv32m::*;
|
||||||
|
pub use string::*;
|
||||||
68
src/compiler/arch/riscv/instr/rv32i.rs
Normal file
68
src/compiler/arch/riscv/instr/rv32i.rs
Normal file
@@ -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)
|
||||||
|
}
|
||||||
16
src/compiler/arch/riscv/instr/rv32m.rs
Normal file
16
src/compiler/arch/riscv/instr/rv32m.rs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
27
src/compiler/arch/riscv/instr/string.rs
Normal file
27
src/compiler/arch/riscv/instr/string.rs
Normal file
@@ -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",
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
mod asm;
|
mod asm;
|
||||||
mod base;
|
|
||||||
mod compile;
|
mod compile;
|
||||||
mod funct;
|
|
||||||
mod opcode;
|
|
||||||
mod reg;
|
mod reg;
|
||||||
mod single;
|
mod single;
|
||||||
|
mod instr;
|
||||||
|
|
||||||
use crate::util::BitsI32;
|
use crate::util::BitsI32;
|
||||||
use base::*;
|
|
||||||
use opcode::*;
|
|
||||||
use single::*;
|
use single::*;
|
||||||
|
|
||||||
pub use asm::*;
|
pub use asm::*;
|
||||||
pub use compile::*;
|
pub use compile::*;
|
||||||
pub use reg::*;
|
pub use reg::*;
|
||||||
pub use funct::*;
|
pub use instr::*;
|
||||||
@@ -47,43 +47,6 @@ pub const t4: Reg = Reg(29);
|
|||||||
pub const t5: Reg = Reg(30);
|
pub const t5: Reg = Reg(30);
|
||||||
pub const t6: Reg = Reg(31);
|
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 {
|
impl Reg {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn val(&self) -> u32 {
|
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);
|
||||||
|
|
||||||
39
src/compiler/arch/riscv/single.rs
Normal file
39
src/compiler/arch/riscv/single.rs
Normal file
@@ -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)
|
||||||
|
}
|
||||||
@@ -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",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,6 @@ pub use program::*;
|
|||||||
use crate::ir::IRLProgram;
|
use crate::ir::IRLProgram;
|
||||||
|
|
||||||
pub fn compile(program: IRLProgram) -> Vec<u8> {
|
pub fn compile(program: IRLProgram) -> Vec<u8> {
|
||||||
let (compiled, start) = arch::riscv64::compile(program);
|
let (compiled, start) = arch::riscv::compile(program);
|
||||||
elf::create(compiled, start.expect("no start method found"))
|
elf::create(compiled, start.expect("no start method found"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{compiler::arch::riscv64::*, ir::VarInst};
|
use crate::{compiler::arch::riscv::*, ir::VarInst};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum RV64Instruction {
|
pub enum RV64Instruction {
|
||||||
@@ -16,38 +16,32 @@ pub enum RV64Instruction {
|
|||||||
src: VarInst,
|
src: VarInst,
|
||||||
},
|
},
|
||||||
Load {
|
Load {
|
||||||
width: Width,
|
width: Funct3,
|
||||||
dest: RegRef,
|
dest: RegRef,
|
||||||
offset: i64,
|
offset: i64,
|
||||||
base: RegRef,
|
base: RegRef,
|
||||||
},
|
},
|
||||||
Store {
|
Store {
|
||||||
width: Width,
|
width: Funct3,
|
||||||
src: RegRef,
|
src: RegRef,
|
||||||
offset: i64,
|
offset: i64,
|
||||||
base: RegRef,
|
base: RegRef,
|
||||||
},
|
},
|
||||||
Op {
|
Op {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
dest: RegRef,
|
|
||||||
src1: RegRef,
|
|
||||||
src2: RegRef,
|
|
||||||
},
|
|
||||||
OpF7 {
|
|
||||||
op: Op,
|
|
||||||
funct: Funct7,
|
funct: Funct7,
|
||||||
dest: RegRef,
|
dest: RegRef,
|
||||||
src1: RegRef,
|
src1: RegRef,
|
||||||
src2: RegRef,
|
src2: RegRef,
|
||||||
},
|
},
|
||||||
OpImm {
|
OpImm {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
dest: RegRef,
|
dest: RegRef,
|
||||||
src: RegRef,
|
src: RegRef,
|
||||||
imm: i64,
|
imm: i64,
|
||||||
},
|
},
|
||||||
OpImmF7 {
|
OpImmF7 {
|
||||||
op: Op,
|
op: Funct3,
|
||||||
funct: Funct7,
|
funct: Funct7,
|
||||||
dest: RegRef,
|
dest: RegRef,
|
||||||
src: RegRef,
|
src: RegRef,
|
||||||
@@ -82,28 +76,22 @@ impl std::fmt::Debug for RV64Instruction {
|
|||||||
dest,
|
dest,
|
||||||
offset,
|
offset,
|
||||||
base,
|
base,
|
||||||
} => write!(f, "l{} {dest:?}, {offset}({base:?})", width.str()),
|
} => write!(f, "l{} {dest:?}, {offset}({base:?})", width::str(*width)),
|
||||||
Self::Store {
|
Self::Store {
|
||||||
width,
|
width,
|
||||||
src,
|
src,
|
||||||
offset,
|
offset,
|
||||||
base,
|
base,
|
||||||
} => write!(f, "s{} {src:?}, {offset}({base:?})", width.str()),
|
} => write!(f, "s{} {src:?}, {offset}({base:?})", width::str(*width)),
|
||||||
Self::Op {
|
Self::Op {
|
||||||
op,
|
|
||||||
dest,
|
|
||||||
src1,
|
|
||||||
src2,
|
|
||||||
} => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", op.str()),
|
|
||||||
Self::OpF7 {
|
|
||||||
op,
|
op,
|
||||||
funct,
|
funct,
|
||||||
dest,
|
dest,
|
||||||
src1,
|
src1,
|
||||||
src2,
|
src2,
|
||||||
} => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", op.fstr(*funct)),
|
} => write!(f, "{} {dest:?}, {src1:?}, {src2:?}", opstr(*op, *funct)),
|
||||||
Self::OpImm { op, dest, src, imm } => {
|
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 {
|
Self::OpImmF7 {
|
||||||
op,
|
op,
|
||||||
@@ -111,7 +99,7 @@ impl std::fmt::Debug for RV64Instruction {
|
|||||||
dest,
|
dest,
|
||||||
src,
|
src,
|
||||||
imm,
|
imm,
|
||||||
} => write!(f, "{}i {dest:?}, {src:?}, {imm}", op.fstr(*funct)),
|
} => write!(f, "{}i {dest:?}, {src:?}, {imm}", opstr(*op, *funct)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::compiler::arch::riscv64::Reg;
|
use crate::compiler::arch::riscv::Reg;
|
||||||
use arch::riscv64::RV64Instruction;
|
use arch::riscv64::RV64Instruction;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, Type, VarID};
|
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 struct IRUFunction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::{FnLowerCtx, Node, PAsmArg, PIdent, PInstruction};
|
use super::{FnLowerCtx, Node, PAsmArg, PIdent, PInstruction};
|
||||||
use crate::{
|
use crate::{
|
||||||
compiler::arch::riscv64::*,
|
compiler::arch::riscv::*,
|
||||||
ir::{
|
ir::{
|
||||||
arch::riscv64::{RV64Instruction, RegRef},
|
arch::riscv64::{RV64Instruction, RegRef},
|
||||||
VarInst,
|
VarInst,
|
||||||
@@ -11,22 +11,7 @@ impl RV64Instruction {
|
|||||||
pub fn parse(inst: &PInstruction, ctx: &mut FnLowerCtx) -> Option<Self> {
|
pub fn parse(inst: &PInstruction, ctx: &mut FnLowerCtx) -> Option<Self> {
|
||||||
let args = &inst.args[..];
|
let args = &inst.args[..];
|
||||||
let opstr = &**inst.op.inner.as_ref()?;
|
let opstr = &**inst.op.inner.as_ref()?;
|
||||||
let op = |ctx: &mut FnLowerCtx<'_, '_>, op: Op| -> Option<Self> {
|
let opi = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3| -> Option<Self> {
|
||||||
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<Self> {
|
|
||||||
let [dest, src, imm] = args else {
|
let [dest, src, imm] = args else {
|
||||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||||
return None;
|
return None;
|
||||||
@@ -36,7 +21,7 @@ impl RV64Instruction {
|
|||||||
let imm = i64_from_arg(imm, ctx)?;
|
let imm = i64_from_arg(imm, ctx)?;
|
||||||
Some(Self::OpImm { op, dest, src, imm })
|
Some(Self::OpImm { op, dest, src, imm })
|
||||||
};
|
};
|
||||||
let opf7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Op, funct: Funct7| -> Option<Self> {
|
let op = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||||
let [dest, src1, src2] = args else {
|
let [dest, src1, src2] = args else {
|
||||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||||
return None;
|
return None;
|
||||||
@@ -44,7 +29,7 @@ impl RV64Instruction {
|
|||||||
let dest = RegRef::from_arg(dest, ctx)?;
|
let dest = RegRef::from_arg(dest, ctx)?;
|
||||||
let src1 = RegRef::from_arg(src1, ctx)?;
|
let src1 = RegRef::from_arg(src1, ctx)?;
|
||||||
let src2 = RegRef::from_arg(src2, ctx)?;
|
let src2 = RegRef::from_arg(src2, ctx)?;
|
||||||
Some(Self::OpF7 {
|
Some(Self::Op {
|
||||||
op,
|
op,
|
||||||
funct,
|
funct,
|
||||||
dest,
|
dest,
|
||||||
@@ -52,7 +37,7 @@ impl RV64Instruction {
|
|||||||
src2,
|
src2,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let opif7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Op, funct: Funct7| -> Option<Self> {
|
let opif7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||||
let [dest, src, imm] = args else {
|
let [dest, src, imm] = args else {
|
||||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||||
return None;
|
return None;
|
||||||
@@ -68,7 +53,7 @@ impl RV64Instruction {
|
|||||||
imm,
|
imm,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let store = |ctx: &mut FnLowerCtx<'_, '_>, width: Width| -> Option<Self> {
|
let store = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option<Self> {
|
||||||
let [src, offset, base] = args else {
|
let [src, offset, base] = args else {
|
||||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||||
return None;
|
return None;
|
||||||
@@ -83,7 +68,7 @@ impl RV64Instruction {
|
|||||||
base,
|
base,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let load = |ctx: &mut FnLowerCtx<'_, '_>, width: Width| -> Option<Self> {
|
let load = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option<Self> {
|
||||||
let [dest, offset, base] = args else {
|
let [dest, offset, base] = args else {
|
||||||
ctx.err("ld requires 3 arguments".to_string());
|
ctx.err("ld requires 3 arguments".to_string());
|
||||||
return None;
|
return None;
|
||||||
@@ -128,40 +113,49 @@ impl RV64Instruction {
|
|||||||
Self::Mv { dest, src }
|
Self::Mv { dest, src }
|
||||||
}
|
}
|
||||||
|
|
||||||
"lb" => load(ctx, Width::B)?,
|
"lb" => load(ctx, width::B)?,
|
||||||
"lh" => load(ctx, Width::H)?,
|
"lh" => load(ctx, width::H)?,
|
||||||
"lw" => load(ctx, Width::W)?,
|
"lw" => load(ctx, width::W)?,
|
||||||
"ld" => load(ctx, Width::D)?,
|
"ld" => load(ctx, width::D)?,
|
||||||
"lbu" => load(ctx, Width::BU)?,
|
"lbu" => load(ctx, width::BU)?,
|
||||||
"lhu" => load(ctx, Width::HU)?,
|
"lhu" => load(ctx, width::HU)?,
|
||||||
"lwu" => load(ctx, Width::WU)?,
|
"lwu" => load(ctx, width::WU)?,
|
||||||
|
|
||||||
"sb" => store(ctx, Width::B)?,
|
"sb" => store(ctx, width::B)?,
|
||||||
"sh" => store(ctx, Width::H)?,
|
"sh" => store(ctx, width::H)?,
|
||||||
"sw" => store(ctx, Width::W)?,
|
"sw" => store(ctx, width::W)?,
|
||||||
"sd" => store(ctx, Width::D)?,
|
"sd" => store(ctx, width::D)?,
|
||||||
|
|
||||||
"addi" => opi(ctx, Op::Add)?,
|
"addi" => opi(ctx, op32i::ADD)?,
|
||||||
"slti" => opi(ctx, Op::Slt)?,
|
"slti" => opi(ctx, op32i::SLT)?,
|
||||||
"sltiu" => opi(ctx, Op::Sltu)?,
|
"sltiu" => opi(ctx, op32i::SLTU)?,
|
||||||
"xori" => opi(ctx, Op::Xor)?,
|
"xori" => opi(ctx, op32i::XOR)?,
|
||||||
"ori" => opi(ctx, Op::Or)?,
|
"ori" => opi(ctx, op32i::OR)?,
|
||||||
"andi" => opi(ctx, Op::And)?,
|
"andi" => opi(ctx, op32i::AND)?,
|
||||||
|
|
||||||
"slli" => opif7(ctx, Op::Sl, funct7::LOGICAL)?,
|
"slli" => opif7(ctx, op32i::SL, op32i::LOGICAL)?,
|
||||||
"srli" => opif7(ctx, Op::Sr, funct7::LOGICAL)?,
|
"srli" => opif7(ctx, op32i::SR, op32i::LOGICAL)?,
|
||||||
"srla" => opif7(ctx, Op::Sr, funct7::ARITHMETIC)?,
|
"srla" => opif7(ctx, op32i::SR, op32i::ARITHMETIC)?,
|
||||||
|
|
||||||
"add" => opf7(ctx, Op::Add, funct7::ADD)?,
|
"add" => op(ctx, op32i::ADD, op32i::F7ADD)?,
|
||||||
"sub" => opf7(ctx, Op::Add, funct7::SUB)?,
|
"sub" => op(ctx, op32i::ADD, op32i::F7SUB)?,
|
||||||
"sll" => op(ctx, Op::Sl)?,
|
"sll" => op(ctx, op32i::SL, op32i::FUNCT7)?,
|
||||||
"slt" => op(ctx, Op::Slt)?,
|
"slt" => op(ctx, op32i::SLT, op32i::FUNCT7)?,
|
||||||
"sltu" => op(ctx, Op::Sltu)?,
|
"sltu" => op(ctx, op32i::SLTU, op32i::FUNCT7)?,
|
||||||
"xor" => op(ctx, Op::Xor)?,
|
"xor" => op(ctx, op32i::XOR, op32i::FUNCT7)?,
|
||||||
"srl" => opf7(ctx, Op::Sr, funct7::LOGICAL)?,
|
"srl" => op(ctx, op32i::SR, op32i::LOGICAL)?,
|
||||||
"sra" => opf7(ctx, Op::Sr, funct7::ARITHMETIC)?,
|
"sra" => op(ctx, op32i::SR, op32i::ARITHMETIC)?,
|
||||||
"or" => op(ctx, Op::Or)?,
|
"or" => op(ctx, op32i::OR, op32i::FUNCT7)?,
|
||||||
"and" => op(ctx, Op::And)?,
|
"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 => {
|
w => {
|
||||||
ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w));
|
ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compiler::arch::riscv64::Reg,
|
compiler::arch::riscv::Reg,
|
||||||
ir::{arch::riscv64::RV64Instruction, IRUInstruction, VarInst},
|
ir::{arch::riscv64::RV64Instruction, IRUInstruction, VarInst},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user