Commit d4ace197 authored by qinsoon's avatar qinsoon

shift right

parent 1e9f0bc7
Pipeline #53 failed with stage
in 13 minutes and 52 seconds
......@@ -1865,6 +1865,156 @@ impl CodeGenerator for ASMCodeGen {
)
}
fn emit_shr_r64_cl (&mut self, dest: &P<Value>) {
trace!("emit shr {}, CL -> {}", dest, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, 4 + 1 + 3 + 1);
let rcx = self.prepare_machine_reg(&x86_64::RCX);
let asm = format!("shrq %cl,{}", reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1.clone()]
},
hashmap!{
id1 => vec![loc1],
rcx => vec![]
},
false
)
}
fn emit_shr_mem64_cl (&mut self, dest: &P<Value>) {
trace!("emit shr {}, CL -> {}", dest, dest);
let (mem, mut uses) = self.prepare_mem(dest, 4 + 1 + 3 + 1);
let rcx = self.prepare_machine_reg(&x86_64::RCX);
if !uses.contains_key(&rcx) {
uses.insert(rcx, vec![]);
}
let asm = format!("shrq %cl,{}", mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
fn emit_shr_r64_imm8 (&mut self, dest: &P<Value>, src: i8) {
trace!("emit shr {},{} -> {}", dest, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, 4 + 1 + 1 + src.to_string().len() + 1);
let asm = format!("shrq ${},{}", src, reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1.clone()]
},
hashmap!{
id1 => vec![loc1]
},
false
)
}
fn emit_shr_mem64_imm8(&mut self, dest: &P<Value>, src: i8) {
trace!("emit shr {},{} -> {}", dest, src, dest);
let (mem, mut uses) = self.prepare_mem(dest, 4 + 1 + 1 + src.to_string().len() + 1);
let asm = format!("shrq ${},{}", src, mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
fn emit_sar_r64_cl (&mut self, dest: &P<Value>) {
trace!("emit sar {}, CL -> {}", dest, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, 4 + 1 + 3 + 1);
let rcx = self.prepare_machine_reg(&x86_64::RCX);
let asm = format!("sarq %cl,{}", reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1.clone()]
},
hashmap!{
id1 => vec![loc1],
rcx => vec![]
},
false
)
}
fn emit_sar_mem64_cl (&mut self, dest: &P<Value>) {
trace!("emit sar {}, CL -> {}", dest, dest);
let (mem, mut uses) = self.prepare_mem(dest, 4 + 1 + 3 + 1);
let rcx = self.prepare_machine_reg(&x86_64::RCX);
if !uses.contains_key(&rcx) {
uses.insert(rcx, vec![]);
}
let asm = format!("sarq %cl,{}", mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
fn emit_sar_r64_imm8 (&mut self, dest: &P<Value>, src: i8) {
trace!("emit sar {},{} -> {}", dest, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, 4 + 1 + 1 + src.to_string().len() + 1);
let asm = format!("sarq ${},{}", src, reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1.clone()]
},
hashmap!{
id1 => vec![loc1]
},
false
)
}
fn emit_sar_mem64_imm8(&mut self, dest: &P<Value>, src: i8) {
trace!("emit sar {},{} -> {}", dest, src, dest);
let (mem, mut uses) = self.prepare_mem(dest, 4 + 1 + 1 + src.to_string().len() + 1);
let asm = format!("sarq ${},{}", src, mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
fn emit_cqo(&mut self) {
trace!("emit: cqo rax -> rdx:rax");
......
......@@ -69,6 +69,16 @@ pub trait CodeGenerator {
fn emit_shl_r64_imm8 (&mut self, dest: &P<Value>, src: i8);
fn emit_shl_mem64_imm8(&mut self, dest: &P<Value>, src: i8);
fn emit_shr_r64_cl (&mut self, dest: &P<Value>);
fn emit_shr_mem64_cl (&mut self, dest: &P<Value>);
fn emit_shr_r64_imm8 (&mut self, dest: &P<Value>, src: i8);
fn emit_shr_mem64_imm8(&mut self, dest: &P<Value>, src: i8);
fn emit_sar_r64_cl (&mut self, dest: &P<Value>);
fn emit_sar_mem64_cl (&mut self, dest: &P<Value>);
fn emit_sar_r64_imm8 (&mut self, dest: &P<Value>, src: i8);
fn emit_sar_mem64_imm8(&mut self, dest: &P<Value>, src: i8);
fn emit_cqo(&mut self);
fn emit_jmp(&mut self, dest: MuName);
......
......@@ -375,7 +375,78 @@ impl <'a> InstructionSelection {
} else if self.match_mem(op1) {
unimplemented!()
}
}
},
op::BinOp::Lshr => {
let op1 = &ops[op1];
let op2 = &ops[op2];
if self.match_ireg(op1) {
let tmp_op1 = self.emit_ireg(op1, f_content, f_context, vm);
if self.match_ireg(op2) {
let tmp_op2 = self.emit_ireg(op2, f_content, f_context, vm);
// mov op2 -> rcx
self.backend.emit_mov_r64_r64(&x86_64::RCX, &tmp_op2);
// shr op1, cl -> op1
self.backend.emit_shr_r64_cl(&tmp_op1);
// mov op1 -> result
let res_tmp = self.get_result_value(node);
self.backend.emit_mov_r64_r64(&res_tmp, &tmp_op1);
} else if self.match_iimm(op2) {
let imm_op2 = self.node_iimm_to_i32(op2) as i8;
// shr op1, op2 -> op1
self.backend.emit_shr_r64_imm8(&tmp_op1, imm_op2);
// mov op1 -> result
let res_tmp = self.get_result_value(node);
self.backend.emit_mov_r64_r64(&res_tmp, &tmp_op1);
} else {
panic!("unexpected op2 (not ireg not iimm): {}", op2);
}
} else if self.match_mem(op1) {
unimplemented!()
}
},
op::BinOp::Ashr => {
let op1 = &ops[op1];
let op2 = &ops[op2];
if self.match_ireg(op1) {
let tmp_op1 = self.emit_ireg(op1, f_content, f_context, vm);
if self.match_ireg(op2) {
let tmp_op2 = self.emit_ireg(op2, f_content, f_context, vm);
// mov op2 -> rcx
self.backend.emit_mov_r64_r64(&x86_64::RCX, &tmp_op2);
// sar op1, cl -> op1
self.backend.emit_sar_r64_cl(&tmp_op1);
// mov op1 -> result
let res_tmp = self.get_result_value(node);
self.backend.emit_mov_r64_r64(&res_tmp, &tmp_op1);
} else if self.match_iimm(op2) {
let imm_op2 = self.node_iimm_to_i32(op2) as i8;
// sar op1, op2 -> op1
self.backend.emit_sar_r64_imm8(&tmp_op1, imm_op2);
// mov op1 -> result
let res_tmp = self.get_result_value(node);
self.backend.emit_mov_r64_r64(&res_tmp, &tmp_op1);
} else {
panic!("unexpected op2 (not ireg not iimm): {}", op2);
}
} else if self.match_mem(op1) {
unimplemented!()
}
},
// floating point
op::BinOp::FAdd => {
......
......@@ -260,5 +260,88 @@ fn shl() -> VM {
vm.define_func_version(func_ver);
vm
}
#[test]
fn test_lshr() {
let lib = testutil::compile_fnc("lshr", &lshr);
unsafe {
let lshr : libloading::Symbol<unsafe extern fn(u64, u8) -> u64> = lib.get(b"lshr").unwrap();
let lshr_8_3 = lshr(8, 3);
println!("lshr(8, 3) = {}", lshr_8_3);
assert!(lshr_8_3 == 1);
}
}
fn lshr() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), Mu("int64"));
// .typedef @int8 = int<8>
let type_def_int8 = vm.declare_type(vm.next_id(), MuType_::int(8));
vm.set_name(type_def_int8.as_entity(), Mu("int8"));
// .funcsig @lshr_sig = (@int64 @int8) -> (@int64)
let lshr_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![type_def_int64.clone(), type_def_int8.clone()]);
vm.set_name(lshr_sig.as_entity(), Mu("lshr_sig"));
// .funcdecl @lshr <@lshr_sig>
let func_id = vm.next_id();
let func = MuFunction::new(func_id, lshr_sig.clone());
vm.set_name(func.as_entity(), Mu("lshr"));
vm.declare_func(func);
// .funcdef @lshr VERSION @lshr_v1 <@lshr_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, lshr_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("lshr_v1"));
// %entry(<@int64> %a, <@int8> %b):
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));
let blk_entry_a = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_entry_a.as_entity(), Mu("blk_entry_a"));
let blk_entry_b = func_ver.new_ssa(vm.next_id(), type_def_int8.clone());
vm.set_name(blk_entry_b.as_entity(), Mu("blk_entry_b"));
// %r = LSHR %a %b
let blk_entry_r = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_entry_r.as_entity(), Mu("blk_entry_r"));
let blk_entry_add = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_entry_r.clone_value()]),
ops: RwLock::new(vec![blk_entry_a.clone(), blk_entry_b.clone()]),
v: Instruction_::BinOp(BinOp::Lshr, 0, 1)
});
// RET %r
let blk_entry_term = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![blk_entry_r.clone()]),
v: Instruction_::Return(vec![0])
});
blk_entry.content = Some(BlockContent{
args: vec![blk_entry_a.clone_value(), blk_entry_b.clone_value()],
exn_arg: None,
body: vec![blk_entry_add, blk_entry_term],
keepalives: None
});
func_ver.define(FunctionContent{
entry: blk_entry.id(),
blocks: hashmap!{
blk_entry.id() => blk_entry
}
});
vm.define_func_version(func_ver);
vm
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment