Commit 364ece82 authored by qinsoon's avatar qinsoon

[wip] implementing most operations for float type

parent db99809f
......@@ -37,6 +37,10 @@ lazy_static! {
MuType::new(new_internal_id(), MuType_::double())
);
pub static ref FLOAT_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::float())
);
pub static ref VOID_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::void())
);
......@@ -49,6 +53,7 @@ lazy_static! {
UINT32_TYPE.clone(),
UINT64_TYPE.clone(),
DOUBLE_TYPE.clone(),
FLOAT_TYPE.clone(),
VOID_TYPE.clone()
];
}
......@@ -179,6 +184,20 @@ impl MuType {
_ => None
}
}
pub fn is_float(&self) -> bool {
match self.v {
MuType_::Float => true,
_ => false
}
}
pub fn is_double(&self) -> bool {
match self.v {
MuType_::Double => true,
_ => false
}
}
}
pub type StructTag = MuName;
......
......@@ -1710,6 +1710,26 @@ impl ASMCodeGen {
)
}
fn internal_fp_mov_f_f(&mut self, inst: &str, dest: Reg, src: Reg) {
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn internal_fp_mov_f_mem(&mut self, inst: &str, dest: Reg, src: Mem,
is_spill_related: bool
) {
......@@ -1837,6 +1857,52 @@ impl ASMCodeGen {
unimplemented!()
}
fn internal_gpr_to_fpr(&mut self, inst: &str, dest: Reg, src: Reg) {
let len = check_op_len(src);
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {}, {}", inst, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn internal_fpr_to_gpr(&mut self, inst: &str, dest: Reg, src: Reg) {
let len = check_op_len(dest);
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg (dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn emit_spill_store_gpr(&mut self, dest: Mem, src: Reg) {
self.internal_mov_mem_r("mov", dest, src, true)
}
......@@ -2925,36 +2991,36 @@ impl CodeGenerator for ASMCodeGen {
)
}
fn emit_movsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) {
trace!("emit: movsd {} -> {}", src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, 5 + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, 5 + 1 + reg1.len() + 1);
// mov - double
let asm = format!("movsd {},{}", reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
fn emit_movsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_f("movsd", dest, src)
}
// load
fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_mem("movsd", dest, src, false)
}
// store
fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_mem_f("movsd", dest, src, false)
}
// mov - float
fn emit_movss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_f("movss", dest, src)
}
// load
fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_mem("movss", dest, src, false)
}
// store
fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_mem_f("movss", dest, src, false)
}
// compare - double
fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("comisd", op1, op2);
}
......@@ -2962,14 +3028,35 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_no_def_r_r("ucomisd", op1, op2);
}
// compare - float
fn emit_comiss_f32_f32 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("comiss", op1, op2);
}
fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("ucomiss", op1, op2);
}
// add - double
fn emit_addsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_r("addsd", dest, src);
}
fn emit_addsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_mem("addsd", dest, src);
}
// add - float
fn emit_addss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_r("addss", dest, src);
}
fn emit_addss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_mem("addss", dest, src);
}
// sub - double
fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("subsd", dest, src);
}
......@@ -2977,6 +3064,17 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("subsd", dest, src);
}
// sub - float
fn emit_subss_f32_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("subss", dest, src);
}
fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem) {
self.internal_fp_binop_def_r_mem("subss", dest, src);
}
// div - double
fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("divsd", dest, src);
}
......@@ -2984,6 +3082,17 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("divsd", dest, src);
}
// div - float
fn emit_divss_f32_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("divss", dest, src);
}
fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem) {
self.internal_fp_binop_def_r_mem("divss", dest, src);
}
// mul - double
fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("mulsd", dest, src);
}
......@@ -2991,50 +3100,31 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("mulsd", dest, src);
}
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg) {
let len = check_op_len(src);
// mul - float
let inst = "cvtsi2sd".to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_reg (src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1);
fn emit_mulss_f32_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("mulss", dest, src);
}
fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem) {
self.internal_fp_binop_def_r_mem("mulss", dest, src);
}
let asm = format!("{} {},{}", inst, reg1, reg2);
// convert - double
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg) {
self.internal_gpr_to_fpr("cvtsi2sd", dest, src);
}
fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg) {
let len = check_op_len(dest);
let inst = "cvtsd2si".to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg (dest, inst.len() + 1 + reg1.len() + 1);
self.internal_fpr_to_gpr("cvtsd2si", dest, src);
}
let asm = format!("{} {},{}", inst, reg1, reg2);
// convert - single
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
fn emit_cvtsi2ss_f32_r (&mut self, dest: Reg, src: Reg) {
self.internal_gpr_to_fpr("cvtsi2ss", dest, src);
}
fn emit_cvtss2si_r_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fpr_to_gpr("cvtss2si", dest, src);
}
// unpack low data - interleave low byte
......
......@@ -188,33 +188,56 @@ pub trait CodeGenerator {
fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>); // store
fn emit_movss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>);
fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>); // store
// fp add
fn emit_addsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_addss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp sub
fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_subss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp div
fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_divss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp mul
fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_mulss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp comparison
fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_comiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
// fp conversion
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvtsi2ss_f32_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtss2si_r_f32 (&mut self, dest: Reg, src: Reg);
// used for unsigned int to fp conversion
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
// unpack low data - interleave low byte
fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
// substract packed double-fp
......
<
......@@ -594,44 +594,47 @@ impl <'a> InstructionSelection {
let values = inst.value.as_ref().unwrap();
let mut status_value_index = 1;
// negative flag
if status.flag_n {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
self.backend.emit_sets_r8(&tmp_status);
}
// status flags only works with int operations
if values[0].is_int_reg() {
// negative flag
if status.flag_n {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
self.backend.emit_sets_r8(&tmp_status);
}
// zero flag
if status.flag_z {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
// zero flag
if status.flag_z {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
self.backend.emit_setz_r8(&tmp_status);
}
self.backend.emit_setz_r8(&tmp_status);
}
// unsigned overflow
if status.flag_c {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
// unsigned overflow
if status.flag_c {
let tmp_status = values[status_value_index].clone();
status_value_index += 1;
match op {
BinOp::Add | BinOp::Sub | BinOp::Mul => {
self.backend.emit_setb_r8(&tmp_status);
match op {
BinOp::Add | BinOp::Sub | BinOp::Mul => {
self.backend.emit_setb_r8(&tmp_status);
}
_ => panic!("Only Add/Sub/Mul has #C flag")
}
_ => panic!("Only Add/Sub/Mul has #C flag")
}
}
// signed overflow
if status.flag_v {
let tmp_status = values[status_value_index].clone();
// signed overflow
if status.flag_v {
let tmp_status = values[status_value_index].clone();
match op {
BinOp::Add | BinOp::Sub | BinOp::Mul => {
self.backend.emit_seto_r8(&tmp_status);
match op {
BinOp::Add | BinOp::Sub | BinOp::Mul => {
self.backend.emit_seto_r8(&tmp_status);
}
_ => panic!("Only Add/Sub/Mul has #V flag")
}
_ => panic!("Only Add/Sub/Mul has #V flag")
}
}
}
......@@ -729,129 +732,135 @@ impl <'a> InstructionSelection {
op::ConvOp::SITOFP => {
let tmp_res = self.get_result_value(node);
if self.match_ireg(op) {
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp_op);
} else {
panic!("unexpected op (expected ireg): {}", op)
assert!(self.match_ireg(op), "unexpected op (expected ireg): {}", op);
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
match to_ty.v {
MuType_::Double => self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp_op),
MuType_::Float => self.backend.emit_cvtsi2ss_f32_r(&tmp_res, &tmp_op),
_ => panic!("expecing fp type as to type in SITOFP, found {}", to_ty)
}
}
op::ConvOp::FPTOSI => {
let tmp_res = self.get_result_value(node);
if self.match_fpreg(op) {
let tmp_op = self.emit_fpreg(op, f_content, f_context, vm);
assert!(self.match_fpreg(op), "unexpected op (expected fpreg): {}", op);
let tmp_op = self.emit_fpreg(op, f_content, f_context, vm);
if from_ty.is_double() {
self.backend.emit_cvtsd2si_r_f64(&tmp_res, &tmp_op);
} else if from_ty.is_float() {
self.backend.emit_cvtss2si_r_f32(&tmp_res, &tmp_op);
} else {
panic!("unexpected op (expected fpreg): {}", op)
panic!("expected fp type as from type in FPTOSI, found {}", to_ty)
}
}
op::ConvOp::UITOFP => {
let tmp_res = self.get_result_value(node);
if self.match_ireg(op) {
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
// FIXME:
assert!(to_ty.is_double(), "only support uitofp (double)");
let op_ty_size = vm.get_backend_type_info(tmp_op.ty.id()).size;
assert!(self.match_ireg(op), "unexpected op (expected ireg): {}", op);
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
match op_ty_size {
8 => {
// movd/movq op -> res
self.backend.emit_mov_fpr_r64(&tmp_res, &tmp_op);
let op_ty_size = vm.get_backend_type_info(tmp_op.ty.id()).size;
// punpckldq UITOFP_C0, tmp_res -> tmp_res
// (interleaving low bytes: xmm = xmm[0] mem[0] xmm[1] mem[1]
let mem_c0 = self.get_mem_for_const(UITOFP_C0.clone(), vm);
self.backend.emit_punpckldq_f64_mem128(&tmp_res, &mem_c0);
match op_ty_size {
8 => {
// movd/movq op -> res
self.backend.emit_mov_fpr_r64(&tmp_res, &tmp_op);
// subpd UITOFP_C1, tmp_res -> tmp_res
let mem_c1 = self.get_mem_for_const(UITOFP_C1.clone(), vm);
self.backend.emit_subpd_f64_mem128(&tmp_res, &mem_c1);
// punpckldq UITOFP_C0, tmp_res -> tmp_res
// (interleaving low bytes: xmm = xmm[0] mem[0] xmm[1] mem[1]
let mem_c0 = self.get_mem_for_const(UITOFP_C0.clone(), vm);
self.backend.emit_punpckldq_f64_mem128(&tmp_res, &mem_c0);
// haddpd tmp_res, tmp_res -> tmp_res
self.backend.emit_haddpd_f64_f64(&tmp_res, &tmp_res);
}
4 => {
let tmp = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
// subpd UITOFP_C1, tmp_res -> tmp_res
let mem_c1 = self.get_mem_for_const(UITOFP_C1.clone(), vm);
self.backend.emit_subpd_f64_mem128(&tmp_res, &mem_c1);
// movl op -> tmp(32)
let tmp32 = unsafe {tmp.as_type(UINT32_TYPE.clone())};
self.backend.emit_mov_r_r(&tmp32, &tmp_op);
// haddpd tmp_res, tmp_res -> tmp_res
self.backend.emit_haddpd_f64_f64(&tmp_res, &tmp_res);
}
4 => {
let tmp = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
// cvtsi2sd %tmp(64) -> %tmp_res
self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp);
}
2 | 1 => {
let tmp_op32 = unsafe {tmp_op.as_type(UINT32_TYPE.clone())};
self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp_op32);
}
_ => panic!("not implemented int length {}", op_ty_size)
// movl op -> tmp(32)
let tmp32 = unsafe {tmp.as_type(UINT32_TYPE.clone())};
self.backend.emit_mov_r_r(&tmp32, &tmp_op);
// cvtsi2sd %tmp(64) -> %tmp_res
self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp);
}
} else {
panic!("unexpected op (expected ireg): {}", op)
2 | 1 => {
let tmp_op32 = unsafe {tmp_op.as_type(UINT32_TYPE.clone())};
self.backend.emit_cvtsi2sd_f64_r(&tmp_res, &tmp_op32);
}
_ => panic!("not implemented int length {}", op_ty_size)
}
}
op::ConvOp::FPTOUI => {
let tmp_res = self.get_result_value(node);
let res_ty_size = vm.get_backend_type_info(tmp_res.ty.id()).size;
// FIXME:
assert!(from_ty.is_double(), "only support fptoui (double)");
assert!(self.match_fpreg(op), "unexpected op (expected fpreg): {}", op);
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
if self.match_fpreg(op) {
let tmp_op = self.emit_fpreg(op, f_content, f_context, vm);
let res_ty_size = vm.get_backend_type_info(tmp_res.ty.id()).size;
match res_ty_size {
8 => {
let tmp1 = self.make_temporary(f_context, DOUBLE_TYPE.clone(), vm);
let tmp2 = self.make_temporary(f_context, DOUBLE_TYPE.clone(), vm);
match res_ty_size {
8 => {
let tmp1 = self.make_temporary(f_context, DOUBLE_TYPE.clone(), vm);
let tmp2 = self.make_temporary(f_context, DOUBLE_TYPE.clone(), vm);
// movsd FPTOUI_C -> %tmp1
let mem_c = self.get_mem_for_const(FPTOUI_C.clone(), vm);
self.backend.emit_movsd_f64_mem64(&tmp1, &mem_c);
// movsd FPTOUI_C -> %tmp1
let mem_c = self.get_mem_for_const(FPTOUI_C.clone(), vm);
self.backend.emit_movsd_f64_mem64(&tmp1, &mem_c);
// movapd %tmp_op -> %tmp2
self.backend.emit_movapd_f64_f64(&tmp2, &tmp_op);
// movapd %tmp_op -> %tmp2
self.backend.emit_movapd_f64_f64(&tmp2, &tmp_op);
// subsd %tmp1, %tmp2 -> %tmp2
self.backend.emit_subsd_f64_f64(&tmp2, &tmp1);
// subsd %tmp1, %tmp2 -> %tmp2
self.backend.emit_subsd_f64_f64(&tmp2, &tmp1);
// cvttsd2si %tmp2 -> %tmp_res
self.backend.emit_cvttsd2si_r_f64(&tmp_res, &tmp2);
// cvttsd2si %tmp2 -> %tmp_res
self.backend.emit_cvttsd2si_r_f64(&tmp_res, &tmp2);
let tmp_const = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
// mov 0x8000000000000000 -> %tmp_const
self.backend.emit_mov_r64_imm64(&tmp_const, -9223372036854775808i64);
let tmp_const = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
// mov 0x8000000000000000 -> %tmp_const
self.backend.emit_mov_r64_imm64(&tmp_const, -9223372036854775808i64);
// xor %tmp_res, %tmp_const -> %tmp_const
self.backend.emit_xor_r_r(&tmp_const, &tmp_res);
// xor %tmp_res, %tmp_const -> %tmp_const
self.backend.emit_xor_r_r(&tmp_const, &tmp_res);
// cvttsd2si %tmp_op -> %tmp_res
self.backend.emit_cvttsd2si_r_f64(&tmp_res, &tmp_op);
// cvttsd2si %tmp_op -> %tmp_res
self.backend.emit_cvttsd2si_r_f64(&tmp_res, &tmp_op);
// ucomisd %tmp_op %tmp1
self.backend.emit_ucomisd_f64_f64(&tmp1, &tmp_op);
// ucomisd %tmp_op %tmp1
self.backend.emit_ucomisd_f64_f64(&tmp1, &tmp_op);
// cmovaeq %tmp_const -> %tmp_res
self.backend.emit_cmovae_r_r(&tmp_res, &tmp_const);
}
4 => {
let tmp_res64 = unsafe {tmp_res.as_type(UINT64_TYPE.clone())};
// cmovaeq %tmp_const -> %tmp_res
self.backend.emit_cmovae_r_r(&tmp_res, &tmp_const);
}
4 => {
let tmp_res64 = unsafe {tmp_res.as_type(UINT64_TYPE.clone())};
// cvttsd2si %tmp_op -> %tmp_res(64)
self.backend.emit_cvttsd2si_r_f64(&tmp_res64, &tmp_op);
}
2 | 1 => {
let tmp_res32 = unsafe {tmp_res.as_type(UINT32_TYPE.clone())};
// cvttsd2si %tmp_op -> %tmp_res(64)
self.backend.emit_cvttsd2si_r_f64(&tmp_res64, &tmp_op);
}
2 | 1 => {
let tmp_res32 = unsafe {tmp_res.as_type(UINT32_TYPE.clone())};
// cvttsd2si %tmp_op -> %tmp_res(32)
self.backend.emit_cvttsd2si_r_f64(&tmp_res32, &tmp_op);
// cvttsd2si %tmp_op -> %tmp_res(32)
self.backend.emit_cvttsd2si_r_f64(&tmp_res32, &tmp_op);
// movz %tmp_res -> %tmp_res(32)
self.backend.emit_movz_r_r(&tmp_res32, &tmp_res);
}
_ => panic!("not implemented int length {}", res_ty_size)
// movz %tmp_res -> %tmp_res(32)
self.backend.emit_movz_r_r(&tmp_res32, &tmp_res);
}
} else {
panic!("unexpected op (expected ireg): {}", op)
_ => panic!("not implemented int length {}", res_ty_size)
}
}
_ => unimplemented!()
......@@ -878,14 +887,8 @@ impl <'a> InstructionSelection {
let resolved_loc = self.emit_node_addr_to_value(loc_op, f_content, f_context, vm);
let res_temp = self.get_result_value(node);
if self.match_ireg(node) {
// emit mov(GPR)
self.backend.emit_mov_r_mem(&res_temp, &resolved_loc);
} else {
// emit mov(FPR)
self.backend.emit_movsd_f64_mem64(&res_temp, &resolved_loc);
}
self.emit_move_value_to_value(&res_temp, &resolved_loc);
}