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,6 +594,8 @@ impl <'a> InstructionSelection {
let values = inst.value.as_ref().unwrap();
let mut status_value_index = 1;
// 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();
......@@ -635,6 +637,7 @@ impl <'a> InstructionSelection {
}
}
}
}
Instruction_::ConvOp{operation, ref from_ty, ref to_ty, operand} => {
trace!("instsel on CONVOP");
......@@ -729,27 +732,36 @@ impl <'a> InstructionSelection {
op::ConvOp::SITOFP => {
let tmp_res = self.get_result_value(node);
if self.match_ireg(op) {
assert!(self.match_ireg(op), "unexpected op (expected 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)
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) {
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) {
// FIXME:
assert!(to_ty.is_double(), "only support uitofp (double)");
assert!(self.match_ireg(op), "unexpected op (expected ireg): {}", op);
let tmp_op = self.emit_ireg(op, f_content, f_context, vm);
let op_ty_size = vm.get_backend_type_info(tmp_op.ty.id()).size;
......@@ -787,17 +799,17 @@ impl <'a> InstructionSelection {
}
_ => panic!("not implemented int length {}", op_ty_size)
}
} else {
panic!("unexpected op (expected ireg): {}", op)
}
}
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)");
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_ireg(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 => {
......@@ -850,9 +862,6 @@ impl <'a> InstructionSelection {
}
_ => panic!("not implemented int length {}", res_ty_size)
}
} else {
panic!("unexpected op (expected ireg): {}", op)
}
}
_ => unimplemented!()
}
......@@ -879,13 +888,7 @@ 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);
}
Instruction_::Store{is_ptr, order, mem_loc, value} => {
......@@ -921,11 +924,16 @@ impl <'a> InstructionSelection {
} else {
unimplemented!()
}
} else {
} else if self.match_fpreg(val_op) {
let val = self.emit_fpreg(val_op, f_content, f_context, vm);
// emit mov(FPR)
self.backend.emit_movsd_mem64_f64(&resolved_loc, &val);
match val.ty.v {
MuType_::Double => self.backend.emit_movsd_mem64_f64(&resolved_loc, &val),
MuType_::Float => self.backend.emit_movss_mem32_f32(&resolved_loc, &val),
_ => panic!("unexpected fp type: {}", val.ty)
}
} else {
unimplemented!()
}
}
......@@ -1662,20 +1670,43 @@ impl <'a> InstructionSelection {
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let mem_op2 = self.emit_mem(&ops[op2], vm);
match reg_op1.ty.v {
MuType_::Double => {
// mov op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// add op2 res
self.backend.emit_addsd_f64_mem64(&res_tmp, &mem_op2);
}
MuType_::Float => {
// mov op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// add op2 res
self.backend.emit_addss_f32_mem32(&res_tmp, &mem_op2);
}
_ => panic!("expect double or float")
}
} else if self.match_fpreg(&ops[op1]) && self.match_fpreg(&ops[op2]) {
trace!("emit add-fpreg-fpreg");
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let reg_op2 = self.emit_fpreg(&ops[op2], f_content, f_context, vm);
match reg_op1.ty.v {
MuType_::Double => {
// movsd op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// add op2 res
self.backend.emit_addsd_f64_f64(&res_tmp, &reg_op2);
}
MuType_::Float => {
// movsd op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// add op2 res
self.backend.emit_addss_f32_f32(&res_tmp, &reg_op2);
}
_ => panic!("expect double or float")
}
} else {
panic!("unexpected fadd: {}", node)
}
......@@ -1688,20 +1719,42 @@ impl <'a> InstructionSelection {
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let mem_op2 = self.emit_mem(&ops[op2], vm);
match reg_op1.ty.v {
MuType_::Double => {
// mov op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// sub op2 res
self.backend.emit_subsd_f64_mem64(&res_tmp, &mem_op2);
}
MuType_::Float => {
// mov op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// sub op2 res
self.backend.emit_subss_f32_mem32(&res_tmp, &mem_op2);
}
_ => panic!("expect double or float")
}
} else if self.match_fpreg(&ops[op1]) && self.match_fpreg(&ops[op2]) {
trace!("emit sub-fpreg-fpreg");
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let reg_op2 = self.emit_fpreg(&ops[op2], f_content, f_context, vm);
match reg_op1.ty.v {
MuType_::Double => {
// movsd op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// sub op2 res
self.backend.emit_subsd_f64_f64(&res_tmp, &reg_op2);
}
MuType_::Float => {
// movss op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// sub op2 res
self.backend.emit_subss_f32_f32(&res_tmp, &reg_op2);
}
_ => panic!("expect double or float")
}
} else {
panic!("unexpected fsub: {}", node)
}
......@@ -1714,20 +1767,42 @@ impl <'a> InstructionSelection {
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let mem_op2 = self.emit_mem(&ops[op2], vm);
match reg_op1.ty.v {
MuType_::Double => {
// mov op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// mul op2 res
self.backend.emit_mulsd_f64_mem64(&res_tmp, &mem_op2);
}
MuType_::Float => {
// mov op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// mul op2 res
self.backend.emit_mulss_f32_mem32(&res_tmp, &mem_op2);
}
_ => panic!("expect double or float")
}
} else if self.match_fpreg(&ops[op1]) && self.match_fpreg(&ops[op2]) {
trace!("emit mul-fpreg-fpreg");
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let reg_op2 = self.emit_fpreg(&ops[op2], f_content, f_context, vm);
match reg_op1.ty.v {
MuType_::Double => {
// movsd op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// mul op2 res
self.backend.emit_mulsd_f64_f64(&res_tmp, &reg_op2);
}
MuType_::Float => {
// movss op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// mul op2 res
self.backend.emit_mulss_f32_f32(&res_tmp, &reg_op2);
}
_ => panic!("expect double or float")
}
} else {
panic!("unexpected fmul: {}", node)
}
......@@ -1740,20 +1815,42 @@ impl <'a> InstructionSelection {
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let mem_op2 = self.emit_mem(&ops[op2], vm);
match reg_op1.ty.v {
MuType_::Double => {
// mov op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// div op2 res
self.backend.emit_divsd_f64_mem64(&res_tmp, &mem_op2);
}
MuType_::Float => {
// mov op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// div op2 res
self.backend.emit_divss_f32_mem32(&res_tmp, &mem_op2);
}
_ => panic!("expect double or float")
}
} else if self.match_fpreg(&ops[op1]) && self.match_fpreg(&ops[op2]) {
trace!("emit div-fpreg-fpreg");
let reg_op1 = self.emit_fpreg(&ops[op1], f_content, f_context, vm);
let reg_op2 = self.emit_fpreg(&ops[op2], f_content, f_context, vm);
match reg_op1.ty.v {
MuType_::Double => {
// movsd op1, res
self.backend.emit_movsd_f64_f64(&res_tmp, &reg_op1);
// div op2 res
self.backend.emit_divsd_f64_f64(&res_tmp, &reg_op2);
}
MuType_::Float => {
// movss op1, res
self.backend.emit_movss_f32_f32(&res_tmp, &reg_op1);
// div op2 res
self.backend.emit_divss_f32_f32(&res_tmp, &reg_op2);
}
_ => panic!("expect double or float")
}
} else {
panic!("unexpected fdiv: {}", node)
}
......@@ -1768,7 +1865,21 @@ impl <'a> InstructionSelection {
let reg_tmp = self.get_result_value(node);
self.emit_runtime_entry(&entrypoints::FREM, vec![reg_op1.clone(), reg_op2.clone()], Some(vec![reg_tmp.clone()]), Some(node), f_content, f_context, vm);
match reg_op1.ty.v {
MuType_::Double => {
self.emit_runtime_entry(&entrypoints::FREM_DOUBLE,
vec![reg_op1.clone(), reg_op2.clone()],
Some(vec![reg_tmp.clone()]),
Some(node), f_content, f_context, vm);
}
MuType_::Float => {
self.emit_runtime_entry(&entrypoints::FREM_FLOAT,
vec![reg_op1.clone(), reg_op2.clone()],
Some(vec![reg_tmp.clone()]),
Some(node), f_content,