Commit 98157fa0 authored by qinsoon's avatar qinsoon

shl int128

parent 20b2d04e
......@@ -1555,6 +1555,43 @@ impl ASMCodeGen {
)
}
fn internal_triop_def_r_r_mr(&mut self, inst: &str, dest: Reg, src1: Reg, src2: Reg) {
let len = check_op_len(dest);
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {}, {}, {} -> {}", inst, dest, src1, src2, dest);
let mreg = self.prepare_machine_reg(src2);
let mreg_name = src2.name().unwrap();
let (reg1, id1, loc1) = self.prepare_reg(src1, inst.len() + 1 + 1 + mreg_name.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(dest, inst.len() + 1 + 1 + mreg_name.len() + 1 + reg1.len() + 1);
let asm = format!("{} %{},{},{}", inst, mreg_name, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2.clone()]
},
{
if id1 == id2 {
linked_hashmap! {
id1 => vec![loc1, loc2],
mreg => vec![]
}
} else {
linked_hashmap! {
id1 => vec![loc1],
id2 => vec![loc2],
mreg => vec![]
}
}
},
false
)
}
fn internal_mov_r64_imm64(&mut self, inst: &str, dest: &P<Value>, src: i64) {
let inst = inst.to_string() + &op_postfix(64);
trace!("emit: {} {} -> {}", inst, src, dest);
......@@ -2161,6 +2198,10 @@ impl CodeGenerator for ASMCodeGen {
self.internal_binop_no_def_r_r("test", op1, op2)
}
fn emit_test_imm_r(&mut self, op1: i32, op2: Reg) {
self.internal_binop_no_def_imm_r("test", op1, op2)
}
// mov
fn emit_mov_r64_imm64 (&mut self, dest: &P<Value>, src: i64) {
......@@ -2743,6 +2784,10 @@ impl CodeGenerator for ASMCodeGen {
self.internal_binop_def_r_imm("shl", dest, src as i32)
}
fn emit_shld_r_r_cl (&mut self, dest: Reg, src: Reg) {
self.internal_triop_def_r_r_mr("shld", dest, src, &x86_64::CL);
}
fn emit_shr_r_cl (&mut self, dest: &P<Value>) {
self.internal_binop_def_r_mr("shr", dest, &x86_64::CL)
}
......@@ -2751,6 +2796,10 @@ impl CodeGenerator for ASMCodeGen {
self.internal_binop_def_r_imm("shr", dest, src as i32)
}
fn emit_shrd_r_r_cl (&mut self, dest: Reg, src: Reg) {
self.internal_triop_def_r_r_mr("shrd", dest, src, &x86_64::CL);
}
fn emit_sar_r_cl (&mut self, dest: &P<Value>) {
self.internal_binop_def_r_mr("sar", dest, &x86_64::CL)
}
......
......@@ -39,7 +39,8 @@ pub trait CodeGenerator {
fn emit_cmp_imm_r(&mut self, op1: i32, op2: Reg);
fn emit_cmp_mem_r(&mut self, op1: Reg, op2: Reg);
fn emit_test_r_r (&mut self, op1: Reg, op2: Reg);
fn emit_test_r_r (&mut self, op1: Reg, op2: Reg);
fn emit_test_imm_r(&mut self, op1: i32, op2: Reg);
// gpr move
......@@ -166,9 +167,13 @@ pub trait CodeGenerator {
fn emit_shl_r_cl (&mut self, dest: Reg);
fn emit_shl_r_imm8 (&mut self, dest: Reg, src: i8);
fn emit_shld_r_r_cl (&mut self, dest: Reg, src: Reg);
fn emit_shr_r_cl (&mut self, dest: &P<Value>);
fn emit_shr_r_imm8 (&mut self, dest: &P<Value>, src: i8);
fn emit_shrd_r_r_cl (&mut self, dest: Reg, src: Reg);
fn emit_sar_r_cl (&mut self, dest: &P<Value>);
fn emit_sar_r_imm8 (&mut self, dest: &P<Value>, src: i8);
......@@ -177,15 +182,15 @@ pub trait CodeGenerator {
fn emit_cwd(&mut self); // sign extend ax to dx:ax
fn emit_jmp(&mut self, dest: MuName);
fn emit_je(&mut self, dest: MuName);
fn emit_je (&mut self, dest: MuName);
fn emit_jne(&mut self, dest: MuName);
fn emit_ja(&mut self, dest: MuName);
fn emit_ja (&mut self, dest: MuName);
fn emit_jae(&mut self, dest: MuName);
fn emit_jb(&mut self, dest: MuName);
fn emit_jb (&mut self, dest: MuName);
fn emit_jbe(&mut self, dest: MuName);
fn emit_jg(&mut self, dest: MuName);
fn emit_jg (&mut self, dest: MuName);
fn emit_jge(&mut self, dest: MuName);
fn emit_jl(&mut self, dest: MuName);
fn emit_jl (&mut self, dest: MuName);
fn emit_jle(&mut self, dest: MuName);
fn emit_js(&mut self, dest: MuName);
......
......@@ -1896,35 +1896,71 @@ impl <'a> InstructionSelection {
let op1 = &ops[op1];
let op2 = &ops[op2];
if self.match_mem(op1) {
unimplemented!()
} else if self.match_ireg(op1) {
if self.match_ireg(op1) && self.match_iimm(op2) {
trace!("emit shl-ireg-iimm");
let tmp_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let imm_op2 = self.node_iimm_to_i32(op2);
if self.match_iimm(op2) {
let imm_op2 = self.node_iimm_to_i32(op2) as i8;
// mov op1 -> res
self.backend.emit_mov_r_r(&res_tmp, &tmp_op1);
// mov op1 -> result
self.backend.emit_mov_r_r(&res_tmp, &tmp_op1);
// shl result, op2 -> result
self.backend.emit_shl_r_imm8(&res_tmp, imm_op2 as i8);
} else if self.match_ireg(op1) && self.match_ireg(op2) {
trace!("emit shl-ireg-ireg");
// shl result, op2 -> result
self.backend.emit_shl_r_imm8(&res_tmp, imm_op2);
} else if self.match_ireg(op2) {
let tmp_op2 = self.emit_ireg(op2, f_content, f_context, vm);
let tmp_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let tmp_op2 = self.emit_ireg(op2, f_content, f_context, vm);
// mov op2 -> cl
self.backend.emit_mov_r_r(&x86_64::CL, &tmp_op2);
// mov op2 -> cl
self.backend.emit_mov_r_r(&x86_64::CL, unsafe {&tmp_op2.as_type(UINT8_TYPE.clone())});
// mov op1 -> result
self.backend.emit_mov_r_r(&res_tmp, &tmp_op1);
// mov op1 -> result
self.backend.emit_mov_r_r(&res_tmp, &tmp_op1);
// shl result, cl -> result
self.backend.emit_shl_r_cl(&res_tmp);
} else {
panic!("unexpected op2 (not ireg not iimm): {}", op2);
}
// shl result, cl -> result
self.backend.emit_shl_r_cl(&res_tmp);
} else if self.match_ireg_ex(op1) && self.match_ireg_ex(op2) {
trace!("emit shl-iregex-iregex");
let (op1_l, op1_h) = self.emit_ireg_ex(op1, f_content, f_context, vm);
let (op2_l, op2_h) = self.emit_ireg_ex(op2, f_content, f_context, vm);
let (res_l, res_h) = self.split_int128(&res_tmp, f_context, vm);
// mov op2_l -> ecx (we do not care higher bits)
self.backend.emit_mov_r_r(&x86_64::ECX, unsafe {&op2_l.as_type(UINT32_TYPE.clone())});
// mov op1_h -> t1
let t1 = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
self.backend.emit_mov_r_r(&t1, &op1_h);
// shld op1_l, t1, cl -> t1
self.backend.emit_shld_r_r_cl(&t1, &op1_l);
// mov op1_l -> t2
let t2 = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
self.backend.emit_mov_r_r(&t2, &op1_l);
// shl t2, cl -> t2
self.backend.emit_shl_r_cl(&t2);
// clear res_l
self.backend.emit_mov_r_imm(&res_l, 0);
// test 64, cl
self.backend.emit_test_imm_r(64i32, &x86_64::CL);
// cmovne t2 -> t1
self.backend.emit_cmovne_r_r(&t1, &t2);
// cmove t2 -> res_l
self.backend.emit_cmove_r_r(&res_l, &t2);
// mov t1 -> res_h
self.backend.emit_mov_r_r(&res_h, &t1);
} else {
panic!("unexpected op1 (not ireg not mem): {}", op1);
unimplemented!()
}
},
op::BinOp::Lshr => {
......
......@@ -168,5 +168,56 @@ fn udiv_u128() -> VM {
define_func_ver!((vm) udiv_u128_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_shl_u128() {
let lib = testutil::compile_fnc("shl_u128", &shl_u128);
unsafe {
use self::extprim::u128::u128;
let shl_u128 : libloading::Symbol<unsafe extern fn(u64, u64, u64, u64) -> (u64, u64)> = lib.get(b"shl_u128").unwrap();
let res = shl_u128(1, 0, 64, 0);
println!("shl_u128(1, 64) = {:?}", res);
assert!(res == (0, 1));
let res = shl_u128(1, 1, 64, 0);
println!("shl_u128(1, 64) = {:?}", res);
assert!(res == (0, 1));
}
}
fn shl_u128() -> VM {
let vm = VM::new();
typedef! ((vm) u128 = mu_int(128));
funcsig! ((vm) sig = (u128, u128) -> (u128));
funcdecl! ((vm) <sig> shl_u128);
funcdef! ((vm) <sig> shl_u128 VERSION shl_u128_v1);
block! ((vm, shl_u128_v1) blk_entry);
ssa! ((vm, shl_u128_v1) <u128> a);
ssa! ((vm, shl_u128_v1) <u128> b);
// sum = Add %a %b
ssa! ((vm, shl_u128_v1) <u128> sum);
inst! ((vm, shl_u128_v1) blk_entry_shl_u128:
sum = BINOP (BinOp::Shl) a b
);
inst! ((vm, shl_u128_v1) blk_entry_ret:
RET (sum)
);
define_block! ((vm, shl_u128_v1) blk_entry(a, b) {
blk_entry_shl_u128, blk_entry_ret
});
define_func_ver!((vm) shl_u128_v1 (entry: blk_entry) {blk_entry});
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