fn line<S: Display>(&mut self, line: S) {
self.lines.push(format!(" {}", line));
+
}
fn label<S: Display>(&mut self, line: S) {
asm_macro!(copy_top_stack_value_to, "lw {}, 0(s2)", &str);
asm_macro!(copy_offset_stack_value_to, "lw {}, {}*8(s2)", &str, isize);
- asm_macro!(deref_pointer_to_from, "lw {}, 0({})", &str, &str);
asm_macro!(copy_to_top_of_stack, "sw {}, 0(s2)", &str);
asm_macro!(move_stack_ptr_by_cells, "addi s2, s2, {}*8", isize);
self.move_stack_ptr_by_cells(1);
}
+ fn pop_some_to(&mut self, regs: &str) {
+ let regs = regs.trim().split(" ").collect::<Vec<_>>();
+ let count = regs.len();
+ let mut index = 0;
+ for reg in regs {
+ self.copy_offset_stack_value_to(reg, index);
+ index += 1;
+ }
+ self.move_stack_ptr_by_cells(count as isize);
+ }
+
fn push_from(&mut self, reg: &str) {
self.move_stack_ptr_by_cells(-1);
self.copy_to_top_of_stack(reg);
}
+ fn pop_call_push(&mut self, regs: &str, call: &str, reg: &str) {
+ self.pop_some_to(regs);
+ self.line(call);
+ self.push_from(reg);
+ }
+
pub fn assembly(&mut self) -> Result<String>{
let mut string_table = HashMap::new();
},
IR::Load => {
self.copy_top_stack_value_to("t0");
- self.deref_pointer_to_from("t0", "t0");
+ self.line(format!("lw {}, 0({})", "t0", "t0")); // deref pointer int t0 to t0
self.copy_to_top_of_stack("t0");
},
IR::Store => { // ( x addr -- )
self.push_from("t0");
},
IR::AddU64 => {
- self.pop_to("t0");
- self.pop_to("t1");
- self.line("add t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "add t0, t0, t1", "t0");
},
IR::SubtractU64 => {
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("sub t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "sub t0, t0, t1", "t0");
},
IR::MultiplyU64 => {
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("mul t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "mul t0, t0, t1", "t0");
},
IR::DivideU64 => {
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("div t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "div t0, t0, t1", "t0");
},
IR::ModU64 => {
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("rem t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "rem t0, t0, t1", "t0");
},
IR::Dup => {
self.copy_top_stack_value_to("t0");
self.push_from("t0");
},
IR::Swap => {
- self.pop_to("t0");
- self.pop_to("t1");
+ self.pop_some_to("t1 t0");
self.push_from("t0");
self.push_from("t1");
},
IR::Equals => {
// Yes, this is the same as subtract, since we're treating 0 as true, and
// others as false.
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("sub t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "sub t0, t0, t1", "t0");
},
IR::GreaterThan => {
- self.pop_to("t1");
- self.pop_to("t0");
+ self.pop_some_to("t0 t1");
self.line("sgt t0, t0, t1");
self.line("seqz t0, t0"); // remember, 0 is true, others are false
self.push_from("t0");
},
IR::BitwiseOr => {
- self.pop_to("t1");
- self.pop_to("t0");
- self.line("or t0, t0, t1");
- self.push_from("t0");
+ self.pop_call_push("t0 t1", "or t0, t0, t1", "t0");
},
IR::Sys0 => {
- self.pop_to("a7");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a7", "ecall", "a0");
},
IR::Sys1 => {
- self.pop_to("a7");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a7", "ecall", "a0");
},
IR::Sys2 => {
- self.pop_to("a7");
- self.pop_to("a1");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a1 a7", "ecall", "a0");
},
IR::Sys3 => {
- self.pop_to("a7");
- self.pop_to("a2");
- self.pop_to("a1");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a1 a2 a7", "ecall", "a0");
},
IR::Sys4 => {
- self.pop_to("a7");
- self.pop_to("a3");
- self.pop_to("a2");
- self.pop_to("a1");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a1 a2 a3 a7", "ecall", "a0");
},
IR::Sys5 => {
- self.pop_to("a7");
- self.pop_to("a4");
- self.pop_to("a3");
- self.pop_to("a2");
- self.pop_to("a1");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a1 a2 a3 a4 a7", "ecall", "a0");
},
IR::Sys6 => {
- self.pop_to("a7");
- self.pop_to("a5");
- self.pop_to("a4");
- self.pop_to("a3");
- self.pop_to("a2");
- self.pop_to("a1");
- self.pop_to("a0");
- self.line("ecall");
- self.push_from("a0");
+ self.pop_call_push("a0 a1 a2 a3 a4 a5 a7", "ecall", "a0");
},
IR::PutN => {
self.line("call putn");