Skip to content

Commit

Permalink
boots: support sub and mul instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Aug 2, 2023
1 parent 138e77e commit abf0443
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 100 deletions.
12 changes: 12 additions & 0 deletions dora-boots/assembler/arm64.dora
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ impl AssemblerArm64 {
)
}

pub fn createLabel(): Label {
self.buffer.createLabel()
}

pub fn bindLabel(lbl: Label) {
self.buffer.bindLabel(lbl);
}

pub fn createAndBindLabel(): Label {
self.buffer.createAndBindLabel()
}

pub fn add(rd: Register, rn: Register, rm: Register) {
if rd == REG_SP || rn == REG_SP {
self.add_ext(rd, rn, rm, Extend::UXTX, 0i32);
Expand Down
65 changes: 30 additions & 35 deletions dora-boots/codegen.dora
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ pub trait CodeGen {
fn prolog();
fn finalize(): CodeDescriptor;

fn setSubLocationData(inst: Inst, loc: LocationData);

fn emitInt64Const(inst: Inst);
fn emitAdd(inst: Inst);
fn emitSub(inst: Inst);
fn emitMul(inst: Inst);
fn emitDiv(inst: Inst);
fn emitMod(inst: Inst);
fn emitCheckedAdd(inst: Inst);
fn emitCheckedSub(inst: Inst);
fn emitCheckedMul(inst: Inst);
fn emitCheckedDiv(inst: Inst);
fn emitCheckedMod(inst: Inst);
fn emitDivZeroCheck(inst: Inst);
fn emitReturn(inst: Inst);

}
Expand All @@ -38,27 +37,18 @@ pub fn setLocationConstraints(codegen: CodeGen, inst: Inst) {
loc.requireOutputRegister();
},

Op::Add => {
Op::DivZeroCheck => {
loc.requireInputRegister(0);
loc.requireInputRegister(1);
loc.requireOutputRegister();
},

Op::Sub => {
codegen.setSubLocationData(inst, loc);
},

Op::Mul => {
unreachable[()]();
},

Op::Div => {
unreachable[()]();

},

Op::Mod => {
unreachable[()]();
Op::CheckedAdd
| Op::CheckedSub
| Op::CheckedMul
| Op::CheckedDiv
| Op::CheckedMod => {
loc.requireInputRegister(0);
loc.requireInputRegister(1);
loc.requireOutputRegister();
},

Op::Return => {
Expand All @@ -68,6 +58,7 @@ pub fn setLocationConstraints(codegen: CodeGen, inst: Inst) {
},

_ => {
println("unsupported op ${inst.op().name()}");
unreachable[()]();
}
}
Expand All @@ -83,24 +74,28 @@ pub fn emitInst(codegen: CodeGen, inst: Inst) {
codegen.emitInt64Const(inst);
},

Op::Add => {
codegen.emitAdd(inst);
Op::CheckedAdd => {
codegen.emitCheckedAdd(inst);
},

Op::CheckedSub => {
codegen.emitCheckedSub(inst);
},

Op::Sub => {
codegen.emitSub(inst);
Op::CheckedMul => {
codegen.emitCheckedMul(inst);
},

Op::Mul => {
codegen.emitMul(inst);
Op::CheckedDiv => {
codegen.emitCheckedDiv(inst);
},

Op::Div => {
codegen.emitDiv(inst);
Op::CheckedMod => {
codegen.emitCheckedMod(inst);
},

Op::Mod => {
codegen.emitMod(inst);
Op::DivZeroCheck => {
codegen.emitDivZeroCheck(inst);
},

Op::Return => {
Expand Down
70 changes: 53 additions & 17 deletions dora-boots/codegen/arm64.dora
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use package::interface::CompilationInfo;
use package::interface::Architecture;
use package::interface::{Architecture, CompilationInfo, trap_trampoline};
use package::codegen::{CodeGen, CodeDescriptor, CommentTable, LocationTable};
use package::assembler::arm64::AssemblerArm64;
use package::assembler::arm64::{R0, R1, R2, R3, R4, R5, R6, R7};
use package::assembler::arm64::{R0, R1, R2, R3, R4, R5, R6, R7, R10, R11};
use package::assembler::arm64::{REG_FP, REG_SP, REG_LR};
use package::assembler::{Label, RegSet, Register};
use package::graph::{Inst, Op, LocationData};
Expand All @@ -28,10 +27,23 @@ impl CodeGenArm64 {
self.asm.ldp_post(REG_FP, REG_LR, REG_SP, 16i32);
self.asm.ret();
}

fn trap(tmp: Register, trap: Int32) {
self.asm.movz(REG_PARAMS(0), trap, 0i32);
self.mov_imm(tmp, trap_trampoline.toInt64());
self.asm.bl_r(tmp);
}

fn mov_imm(dest: Register, imm: Int64) {
unimplemented();
}
}

let REG_PARAMS: Array[Register] = Array[Register]::new(R0, R1, R2, R3, R4, R5, R6, R7);

let REG_TMP1: Register = R10;
let REG_TMP2: Register = R11;

impl CodeGen for CodeGenArm64 {
fn allocatableRegisters(): RegSet {
RegSet::new(R0, R1, R2, R3, R4, R5, R6, R7)
Expand All @@ -46,19 +58,13 @@ impl CodeGen for CodeGenArm64 {
self.asm.mov(REG_FP, REG_SP);
}

fn setSubLocationData(inst: Inst, loc: LocationData) {
loc.requireInputRegister(0);
loc.requireInputRegister(1);
loc.requireOutputRegister();
}

fn emitInt64Const(inst: Inst) {
let loc = inst.getLocationData();
let register = loc.getOutput().getRegister();
self.asm.movz(register, inst.auxAsInt64().toInt32(), 0i32);
}

fn emitAdd(inst: Inst) {
fn emitCheckedAdd(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();
Expand All @@ -68,7 +74,7 @@ impl CodeGen for CodeGenArm64 {
self.asm.add(output, lhs, rhs);
}

fn emitSub(inst: Inst) {
fn emitCheckedSub(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();
Expand All @@ -78,16 +84,46 @@ impl CodeGen for CodeGenArm64 {
self.asm.sub(output, lhs, rhs);
}

fn emitMul(inst: Inst) {
unreachable[()]();
fn emitCheckedMul(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();

self.asm.mul(output, lhs, rhs);
}

fn emitDiv(inst: Inst) {
unreachable[()]();
fn emitCheckedDiv(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();

self.asm.sdiv(output, lhs, rhs);
}

fn emitCheckedMod(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();

self.asm.sdiv(output, lhs, rhs);
self.asm
.msub(output, REG_TMP1, rhs, lhs);
}

fn emitMod(inst: Inst) {
unreachable[()]();
fn emitDivZeroCheck(inst: Inst) {
let loc = inst.getLocationData();
let op = loc.getInput(0).getRegister();

let lbl_continue = self.asm.createLabel();
self.asm.cbnz(op, lbl_continue);
self.asm.brk(0i32);
self.asm.bindLabel(lbl_continue);
}

fn emitReturn(inst: Inst) {
Expand Down
37 changes: 23 additions & 14 deletions dora-boots/codegen/x64.dora
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use package::assembler::x64::{AssemblerX64, Address, Immediate, ScaleFactor};
use package::assembler::x64::{RAX, RDI, RDX, RCX, RSI, RBP, RSP};
use package::assembler::x64::{R8, R9};
use package::assembler::x64::{R8, R9, R10, R11};
use package::assembler::{Register, RegSet};
use package::codegen::{CodeGen, CodeDescriptor, CommentTable, LocationTable};
use package::interface::CompilationInfo;
Expand All @@ -26,6 +26,10 @@ impl CodeGenX64 {

pub let REG_PARAMS: Array[Register] = Array[Register]::new(RDI, RSI, RDX, RCX, R8, R9);

// Temporary registers that can be used within an instruction.
pub let REG_TMP1: Register = R10;
pub let REG_TMP2: Register = R11;

impl CodeGen for CodeGenX64 {
fn allocatableRegisters(): RegSet {
RegSet::new(RDI, RSI, RDX, RCX, R8, R9)
Expand All @@ -40,19 +44,13 @@ impl CodeGen for CodeGenX64 {
self.asm.movq_rr(RBP, RSP);
}

fn setSubLocationData(inst: Inst, loc: LocationData) {
loc.requireInputRegister(0);
loc.requireInputRegister(1);
loc.requireOutputSameAsFirstInput();
}

fn emitInt64Const(inst: Inst) {
let loc = inst.getLocationData();
let register = loc.getOutput().getRegister();
self.asm.movq_ri(register, Immediate(inst.auxAsInt64()));
}

fn emitAdd(inst: Inst) {
fn emitCheckedAdd(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();
Expand All @@ -62,29 +60,40 @@ impl CodeGen for CodeGenX64 {
self.asm.lea(output, Address::array(lhs, rhs, ScaleFactor::One, 0i32));
}

fn emitSub(inst: Inst) {
fn emitCheckedSub(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();
assert(output == lhs);

self.asm.movq_rr(output, lhs);
self.asm.subq_rr(output, rhs);
}

fn emitMul(inst: Inst) {
unreachable[()]();
fn emitCheckedMul(inst: Inst) {
let loc = inst.getLocationData();
let lhs = loc.getInput(0).getRegister();
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();

self.asm.movq_rr(output, lhs);
self.asm.imulq_rr(output, rhs);
}

fn emitDiv(inst: Inst) {
fn emitCheckedDiv(inst: Inst) {
unreachable[()]();
}

fn emitMod(inst: Inst) {
fn emitCheckedMod(inst: Inst) {
unreachable[()]();
}

fn emitDivZeroCheck(inst: Inst) {
let lbl_continue = self.asm.createLabel();
}

fn emitReturn(inst: Inst) {
if inst.hasInput() {
let loc = inst.getLocationData();
Expand Down
7 changes: 7 additions & 0 deletions dora-boots/graph.dora
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ pub enum Op {
Return,

Neg,
CheckedNeg,
Not,

Add,
Expand Down Expand Up @@ -498,6 +499,10 @@ impl Op {
_ => false
}
}

pub fn name(): String {
opName(self)
}
}

pub fn opName(op: Op): String {
Expand All @@ -515,6 +520,7 @@ pub fn opName(op: Op): String {
Op::If => "If",
Op::Return => "Return",
Op::Neg => "Neg",
Op::CheckedNeg => "CheckedNeg",
Op::Not => "Not",
Op::Add => "Add",
Op::CheckedAdd => "CheckedAdd",
Expand Down Expand Up @@ -829,6 +835,7 @@ impl Inst {
Op::If => true,
Op::Return => true,
Op::Neg => false,
Op::CheckedNeg => true,
Op::Not => false,
Op::Add => false,
Op::CheckedAdd => true,
Expand Down
1 change: 1 addition & 0 deletions dora-boots/graph/dump.dora
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ fn dumpInstName(inst: Inst): String {
}
},
Op::Neg => "Neg.${inst.getType()}",
Op::CheckedNeg => "CheckedNeg.${inst.getType()}",
Op::Not => "Not.${inst.getType()}",
Op::Add => "Add.${inst.getType()}",
Op::CheckedAdd => "CheckedAdd.${inst.getType()}",
Expand Down
Loading

0 comments on commit abf0443

Please sign in to comment.