Commit 81a87444 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Implemented 128-bit arithmetici.

parent fe287e80
Pipeline #559 failed with stages
in 6 minutes and 16 seconds
......@@ -21,6 +21,7 @@ ast = {path = "src/ast"}
utils = {path = "src/utils"}
gc = {path = "src/gc"}
field-offset = "0.1.1"
libloading = "0.3"
lazy_static = "0.1.15"
......@@ -34,4 +35,5 @@ time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
petgraph = "0.4.1"
extprim = "*"
\ No newline at end of file
extprim = "*"
num-traits = "*"
......@@ -735,6 +735,14 @@ impl Value {
})
}
pub fn is_int_ex_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::IntEx(_)) => true,
_ => false
}
}
pub fn is_int_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::Int(_)) => true,
......@@ -742,7 +750,13 @@ impl Value {
_ => false
}
}
pub fn is_fp_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::Float(_)) => true,
Value_::Constant(Constant::Double(_)) => true,
_ => false
}
}
pub fn extract_int_const(&self) -> u64 {
match self.v {
Value_::Constant(Constant::Int(val)) => val,
......@@ -751,6 +765,13 @@ impl Value {
}
}
pub fn extract_int_ex_const(&self) -> Vec<u64> {
match self.v {
Value_::Constant(Constant::IntEx(ref val)) => val.clone(),
_ => panic!("expect int ex const")
}
}
pub fn extract_ssa_id(&self) -> Option<MuID> {
match self.v {
Value_::SSAVar(id) => Some(id),
......
......@@ -210,7 +210,7 @@ impl CmpOp {
FUGT => FULT,
FULT => FUGT,
_ => self, // all other comparisons are reflexive
_ => self, // all other comparisons are symmetric
}
}
pub fn invert(self) -> CmpOp {
......@@ -256,6 +256,18 @@ impl CmpOp {
FTRUE => FFALSE,
}
}
// gets the unsigned version of the comparison
pub fn get_unsigned(self) -> CmpOp {
use op::CmpOp::*;
match self {
SGE => UGE,
SLT => ULT,
SGT => UGT,
SLE => ULE,
_ => self,
}
}
pub fn is_signed(self) -> bool {
use op::CmpOp::*;
match self {
......@@ -263,6 +275,14 @@ impl CmpOp {
_ => false
}
}
pub fn is_symmetric(self) -> bool {
use op::CmpOp::*;
match self {
EQ | NE | FORD| FUNO| FUNE | FUEQ | FONE | FOEQ => true,
_ => false
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
......
#![allow(dead_code)]
use compiler::backend::AOT_EMIT_CONTEXT_FILE;
use compiler::backend::RegGroup;
use utils::ByteSize;
......@@ -16,7 +18,6 @@ use utils::LinkedHashMap;
use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use std::str;
use std::usize;
......@@ -272,17 +273,6 @@ impl ASMCode {
let ref blocks = self.blocks;
let ref mut asm = self.code;
let block_start = {
let mut ret = vec![];
for block in blocks.values() {
if TRACE_CFA {
trace!("Block starts at {}", block.start_inst);
}
ret.push(block.start_inst);
}
ret
};
for i in 0..n_insts {
if TRACE_CFA {
trace!("---inst {}---", i);
......@@ -994,13 +984,11 @@ impl ASMCodeGen {
}
fn add_asm_label(&mut self, code: String) {
let l = self.line();
trace!("emit: {}", code);
self.cur_mut().code.push(ASMInst::symbolic(code));
}
fn add_asm_block_label(&mut self, code: String, block_name: MuName) {
let l = self.line();
trace!("emit: [{}]{}", block_name, code);
self.cur_mut().code.push(ASMInst::symbolic(code));
}
......@@ -1819,8 +1807,8 @@ impl ASMCodeGen {
let inst = inst.to_string();
trace!("emit: \t{} {} -> {},{}", inst, src, dest1, dest2);
let (reg1, id1, loc1) = self.prepare_reg(dest1, 3 + 1);
let (reg2, id2, loc2) = self.prepare_reg(dest2, 3 + 1 + reg1.len() + 1);
let (reg1, id1, loc1) = self.prepare_reg(dest1, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(dest2, inst.len() + 1 + reg1.len() + 1);
let (mem, uses) = self.prepare_mem(src, inst.len() + 1 + reg1.len() + 1 + reg2.len() + 1);
let asm = format!("{} {},{},{}", inst, reg1, reg2, mem);
......@@ -1931,8 +1919,8 @@ impl ASMCodeGen {
let inst = inst.to_string();
trace!("emit: \t{} {},{} -> {}", inst, src1, src2, dest);
let (reg1, id1, loc1) = self.prepare_reg(src2, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(src1, inst.len() + 1 + reg1.len() + 1);
let (reg1, id1, loc1) = self.prepare_reg(src1, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(src2, inst.len() + 1 + reg1.len() + 1);
let (mem, mut uses) = self.prepare_mem(dest, inst.len() + 1 + reg1.len() + 1 + reg2.len() + 1);
if is_zero_register_id(id1) {
......@@ -1968,8 +1956,8 @@ impl ASMCodeGen {
trace!("emit: \t{} {},{} -> {},{}", inst, src1, src2, dest, status);
let (reg1, id1, loc1) = self.prepare_reg(status, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(src2, inst.len() + 1 + reg1.len() + 1);
let (reg3, id3, loc3) = self.prepare_reg(src1, inst.len() + 1 + reg1.len() + 1 + reg2.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(src1, inst.len() + 1 + reg1.len() + 1);
let (reg3, id3, loc3) = self.prepare_reg(src2, inst.len() + 1 + reg1.len() + 1 + reg2.len() + 1);
let (mem, mut uses) = self.prepare_mem(dest, inst.len() + 1 + reg1.len() + 1 + reg2.len() + 1 + reg3.len() + 1);
if is_zero_register_id(id2) {
......@@ -2172,23 +2160,28 @@ impl CodeGenerator for ASMCodeGen {
}
}
fn add_cfi_sections(&mut self, arg: &str) { self.add_asm_symbolic(format!(".cfi_sections {}", arg)); }
fn add_cfi_startproc(&mut self) {
self.add_asm_symbolic("\t.cfi_startproc".to_string());
self.add_asm_symbolic(".cfi_startproc".to_string());
}
fn add_cfi_endproc(&mut self) {
self.add_asm_symbolic("\t.cfi_endproc".to_string());
self.add_asm_symbolic(".cfi_endproc".to_string());
}
fn add_cfi_def_cfa_register(&mut self, reg: Reg) {
let reg = self.asm_reg_op(reg);
self.add_asm_symbolic(format!("\t.cfi_def_cfa_register {}", reg));
self.add_asm_symbolic(format!(".cfi_def_cfa_register {}", reg));
}
fn add_cfi_def_cfa_offset(&mut self, offset: i32) {
self.add_asm_symbolic(format!("\t.cfi_def_cfa_offset {}", offset));
self.add_asm_symbolic(format!(".cfi_def_cfa_offset {}", offset));
}
fn add_cfi_def_cfa(&mut self, reg: Reg, offset: i32) {
let reg = self.asm_reg_op(reg);
self.add_asm_symbolic(format!(".cfi_def_cfa {}, {}", reg, offset));
}
fn add_cfi_offset(&mut self, reg: Reg, offset: i32) {
let reg = self.asm_reg_op(reg);
self.add_asm_symbolic(format!("\t.cfi_offset {}, {}", reg, offset));
self.add_asm_symbolic(format!(".cfi_offset {}, {}", reg, offset));
}
fn emit_frame_grow(&mut self) {
......@@ -2745,10 +2738,10 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
Ok(file) => file
};
file.write("\t.arch armv8-a\n".as_bytes()).unwrap();
file.write(".arch armv8-a\n".as_bytes()).unwrap();
// constants in text section
file.write("\t.text\n".as_bytes()).unwrap();
file.write(".text\n".as_bytes()).unwrap();
write_const_min_align(&mut file);
......@@ -2784,7 +2777,7 @@ fn write_const_min_align(f: &mut File) {
#[cfg(target_os = "linux")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
f.write_fmt(format_args!("\t.balign {}\n", check_min_align(align))).unwrap();
f.write_fmt(format_args!(".balign {}\n", check_min_align(align))).unwrap();
}
fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) {
......@@ -2815,30 +2808,30 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
&Constant::Int(val) => {
let len = ty.get_int_length().unwrap();
match len {
8 => f.write_fmt(format_args!("\t.byte {}\n", val as u8 )).unwrap(),
16 => f.write_fmt(format_args!("\t.word {}\n", val as u16)).unwrap(),
32 => f.write_fmt(format_args!("\t.long {}\n", val as u32)).unwrap(),
64 => f.write_fmt(format_args!("\t.quad {}\n", val as u64)).unwrap(),
8 => f.write_fmt(format_args!(".byte {}\n", val as u8 )).unwrap(),
16 => f.write_fmt(format_args!(".word {}\n", val as u16)).unwrap(),
32 => f.write_fmt(format_args!(".long {}\n", val as u32)).unwrap(),
64 => f.write_fmt(format_args!(".quad {}\n", val as u64)).unwrap(),
_ => panic!("unimplemented int length: {}", len)
}
}
&Constant::Float(val) => {
let bytes: [u8; 4] = unsafe {mem::transmute(val)};
f.write("\t.long ".as_bytes()).unwrap();
f.write(".long ".as_bytes()).unwrap();
f.write(&bytes).unwrap();
f.write("\n".as_bytes()).unwrap();
}
&Constant::Double(val) => {
let bytes: [u8; 8] = unsafe {mem::transmute(val)};
f.write("\t.quad ".as_bytes()).unwrap();
f.write(".quad ".as_bytes()).unwrap();
f.write(&bytes).unwrap();
f.write("\n".as_bytes()).unwrap();
}
&Constant::NullRef => {
f.write_fmt(format_args!("\t.quad 0\n")).unwrap()
f.write_fmt(format_args!(".quad 0\n")).unwrap()
}
&Constant::ExternSym(ref name) => {
f.write_fmt(format_args!("\t.quad {}\n", name)).unwrap()
f.write_fmt(format_args!(".quad {}\n", name)).unwrap()
}
&Constant::List(ref vals) => {
for val in vals {
......@@ -2871,10 +2864,10 @@ pub fn emit_context_with_reloc(vm: &VM,
};
// bss
file.write_fmt(format_args!("\t.bss\n")).unwrap();
file.write_fmt(format_args!(".bss\n")).unwrap();
// data
file.write("\t.data\n".as_bytes()).unwrap();
file.write(".data\n".as_bytes()).unwrap();
{
use runtime::mm;
......@@ -2943,20 +2936,20 @@ pub fn emit_context_with_reloc(vm: &VM,
let load_ref = unsafe {cur_addr.load::<Address>()};
if load_ref.is_zero() {
// write 0
file.write("\t.quad 0\n".as_bytes()).unwrap();
file.write(".quad 0\n".as_bytes()).unwrap();
} else {
let label = match relocatable_refs.get(&load_ref) {
Some(label) => label,
None => panic!("cannot find label for address {}, it is not dumped by GC (why GC didn't trace to it)", load_ref)
};
file.write_fmt(format_args!("\t.quad {}\n", label.clone())).unwrap();
file.write_fmt(format_args!(".quad {}\n", label.clone())).unwrap();
}
} else if fields.contains_key(&cur_addr) {
// write uptr (or other relocatable value) with label
let label = fields.get(&cur_addr).unwrap();
file.write_fmt(format_args!("\t.quad {}\n", label.clone())).unwrap();
file.write_fmt(format_args!(".quad {}\n", label.clone())).unwrap();
} else {
// write plain word (as bytes)
let next_word_addr = cur_addr.plus(POINTER_SIZE);
......@@ -3002,7 +2995,7 @@ fn write_data_bytes(f: &mut File, from: Address, to: Address) {
use std::io::Write;
if from < to {
f.write("\t.byte ".as_bytes()).unwrap();
f.write(".byte ".as_bytes()).unwrap();
let mut cursor = from;
while cursor < to {
......@@ -3025,7 +3018,7 @@ fn directive_globl(name: String) -> String {
}
fn directive_comm(name: String, size: ByteSize, align: ByteSize) -> String {
format!("\t.comm {},{},{}", name, size, align)
format!(".comm {},{},{}", name, size, align)
}
use compiler::machine_code::CompiledFunction;
......
......@@ -23,8 +23,10 @@ pub trait CodeGenerator {
fn end_block(&mut self, block_name: MuName);
// add CFI info
fn add_cfi_sections(&mut self, arg: &str);
fn add_cfi_startproc(&mut self);
fn add_cfi_endproc(&mut self);
fn add_cfi_def_cfa(&mut self, reg: Reg, offset: i32);
fn add_cfi_def_cfa_register(&mut self, reg: Reg);
fn add_cfi_def_cfa_offset(&mut self, offset: i32);
fn add_cfi_offset(&mut self, reg: Reg, offset: i32);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -1910,14 +1910,9 @@ impl <'a> InstructionSelection {
}
}
128 => {
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);
self.emit_runtime_entry(&entrypoints::UDIV_U128,
vec![op1_l.clone(), op1_h.clone(), op2_l.clone(), op2_h.clone()],
Some(vec![res_l.clone(), res_h.clone()]),
vec![op1.clone(), op2.clone()],
Some(vec![res_tmp.clone()]),
Some(node), f_content, f_context, vm);
}
_ => unimplemented!()
......@@ -1946,14 +1941,9 @@ impl <'a> InstructionSelection {
}
}
128 => {
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);
self.emit_runtime_entry(&entrypoints::SDIV_I128,
vec![op1_l.clone(), op1_h.clone(), op2_l.clone(), op2_h.clone()],
Some(vec![res_l.clone(), res_h.clone()]),
vec![op1.clone(), op2.clone()],
Some(vec![res_tmp.clone()]),
Some(node), f_content, f_context, vm);
}
_ => unimplemented!()
......@@ -1982,14 +1972,9 @@ impl <'a> InstructionSelection {
}
}
128 => {
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);
self.emit_runtime_entry(&entrypoints::UREM_U128,
vec![op1_l.clone(), op1_h.clone(), op2_l.clone(), op2_h.clone()],
Some(vec![res_l.clone(), res_h.clone()]),
vec![op1.clone(), op2.clone()],
Some(vec![res_tmp.clone()]),
Some(node), f_content, f_context, vm);
}
_ => unimplemented!()
......@@ -2018,14 +2003,9 @@ impl <'a> InstructionSelection {
}
}
128 => {
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);
self.emit_runtime_entry(&entrypoints::SREM_I128,
vec![op1_l.clone(), op1_h.clone(), op2_l.clone(), op2_h.clone()],
Some(vec![res_l.clone(), res_h.clone()]),
vec![op1.clone(), op2.clone()],
Some(vec![res_tmp.clone()]),
Some(node), f_content, f_context, vm);
}
_ => unimplemented!()
......
......@@ -132,8 +132,8 @@ lazy_static! {
pub static ref UDIV_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_udiv_u128")),
jit: RwLock::new(None)
......@@ -142,8 +142,8 @@ lazy_static! {
pub static ref SDIV_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sdiv_i128")),
jit: RwLock::new(None)
......@@ -152,8 +152,8 @@ lazy_static! {
pub static ref UREM_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_urem_u128")),
jit: RwLock::new(None)
......@@ -162,13 +162,92 @@ lazy_static! {
pub static ref SREM_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_srem_i128")),
jit: RwLock::new(None)
};
pub static ref FPTOUI_DOUBLE_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![DOUBLE_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptoui_double_u128")),
jit: RwLock::new(None)
};
pub static ref FPTOSI_DOUBLE_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![DOUBLE_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptosi_double_i128")),
jit: RwLock::new(None)
};
pub static ref UITOFP_U128_DOUBLE : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![DOUBLE_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_uitofp_u128_double")),
jit: RwLock::new(None)
};
pub static ref SITOFP_I128_DOUBLE : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![DOUBLE_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sitofp_i128_double")),
jit: RwLock::new(None)
};
// Conversion to/from int<128> from/to float
pub static ref FPTOUI_FLOAT_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![FLOAT_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptoui_float_u128")),
jit: RwLock::new(None)
};
pub static ref FPTOSI_FLOAT_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![FLOAT_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptosi_float_i128")),
jit: RwLock::new(None)
};
pub static ref UITOFP_U128_FLOAT : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![FLOAT_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_uitofp_u128_float")),
jit: RwLock::new(None)
};
pub static ref SITOFP_I128_FLOAT : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![FLOAT_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sitofp_i128_float")),
jit: RwLock::new(None)
};
// impl/decl: mod.rs
pub static ref PRINT_HEX : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
......
......@@ -14,29 +14,46 @@ pub extern fn muentry_frem64(a: f64, b: f64) -> f64 {
a.rem(b)
}
extern crate num_traits;
use extprim::u128::u128;
use extprim::i128::i128;
use runtime::math::num_traits::ToPrimitive;
use runtime::math::num_traits::FromPrimitive;
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_udiv_u128(a: u128, b: u128) -> u128 {
a.wrapping_div(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_sdiv_i128(a: i128, b: i128) -> i128 {
a.wrapping_div(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_urem_u128(a: u128, b: u128) -> u128 {
a.wrapping_rem(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_srem_i128(a: i128, b: i128) -> i128 {
a.wrapping_rem(b)
}
\ No newline at end of file
}
#[no_mangle]
pub extern fn muentry_fptoui_double_u128(a: f64) -> u128 { u128::from_f64(a).unwrap() }
#[no_mangle]
pub extern fn muentry_fptosi_double_i128(a: f64) -> i128 { i128::from_f64(a).unwrap() }
#[no_mangle]
pub extern fn muentry_uitofp_u128_double(a: u128) -> f64 { a.to_f64().unwrap() }
#[no_mangle]
pub extern fn muentry_sitofp_i128_double(a: i128) -> f64 { a.to_f64().unwrap() }
#[no_mangle]
pub extern fn muentry_fptoui_float_u128(a: f32) -> u128 { u128::from_f32(a).unwrap() }
#[no_mangle]
pub extern fn muentry_fptosi_float_i128(a: f32) -> i128 { i128::from_f32(a).unwrap() }
#[no_mangle]
pub extern fn muentry_uitofp_u128_float(a: u128) -> f32 { a.to_f32().unwrap() }
#[no_mangle]
pub extern fn muentry_sitofp_i128_float(a: i128) -> f32 { a.to_f32().unwrap() }
\ No newline at end of file
......@@ -127,6 +127,7 @@ impl MuStack {
match reg_group {
RegGroup::GPR => gpr_used.push(word),
RegGroup::FPR => fpr_used.push(word),
RegGroup::GPREX => unimplemented!(),
}
}
......
......@@ -61,6 +61,56 @@ fn add_u128() -> VM {
vm
}
#[test]
fn test_sub_u128() {
let lib = testutil::compile_fnc("sub_u128", &sub_u128);
unsafe {
use std::u64;
let sub_u128 : libloading::Symbol<unsafe extern fn(u64, u64, u64, u64) -> (u64, u64)> = lib.get(b"sub_u128").unwrap();
let res = sub_u128(1, 0, 1, 0);
println!("sub_u128(1, 1) = {:?}", res);
assert!(res == (0, 0));
let res = sub_u128(u64::MAX, 0, u64::MAX, u64::MAX);
println!("sub_u128(u64::MAX, -1) = {:?}", res);
assert!(res == (0, 1));
}
}
fn sub_u128() -> VM {
let vm = VM::new();
typedef! ((vm) u128 = mu_int(128));
funcsig! ((vm) sig = (u128, u128) -> (u128));
funcdecl! ((vm) <sig> sub_u128);
funcdef! ((vm) <sig> sub_u128 VERSION sub_u128_v1);
block! ((vm, sub_u128_v1) blk_entry);
ssa! ((vm, sub_u128_v1) <u128> a);
ssa! ((vm, sub_u128_v1) <u128> b);
// sum = sub %a %b
ssa! ((vm, sub_u128_v1) <u128> sum);
inst! ((vm, sub_u128_v1) blk_entry_sub_u128:
sum = BINOP (BinOp::Sub) a b
);
inst! ((vm, sub_u128_v1) blk_entry_ret:
RET (sum)
);
define_block! ((vm, sub_u128_v1) blk_entry(a, b) {
blk_entry_sub_u128, blk_entry_ret
});
define_func_ver!((vm) sub_u128_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_add_const_u128() {
let lib = testutil::compile_fnc("add_const_u128", &add_const_u128);
......
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