GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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);
}