mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-05 02:20:19 +00:00
Integer subset done.
This commit is contained in:
parent
a124d87d0f
commit
3dadbc15c9
@ -264,6 +264,62 @@ macro_rules! binop_all_nofp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! binop_shift {
|
||||||
|
($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
|
||||||
|
match ($sz, $src, $dst) {
|
||||||
|
(Size::S32, Location::Imm8(imm), Location::GPR(dst)) => {
|
||||||
|
assert!(imm < 32);
|
||||||
|
dynasm!($assembler ; $ins W(map_gpr(dst).x()), W(map_gpr(dst).x()), imm as u32);
|
||||||
|
},
|
||||||
|
(Size::S32, Location::Imm8(imm), Location::Memory(base, disp)) => {
|
||||||
|
assert!(imm < 32);
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!($assembler
|
||||||
|
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
; $ins w_tmp1, w_tmp1, imm as u32
|
||||||
|
; str w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Size::S32, Location::GPR(GPR::RCX), Location::GPR(dst)) => {
|
||||||
|
dynasm!($assembler ; $ins W(map_gpr(dst).x()), W(map_gpr(dst).x()), W(map_gpr(GPR::RCX).x()));
|
||||||
|
},
|
||||||
|
(Size::S32, Location::GPR(GPR::RCX), Location::Memory(base, disp)) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!($assembler
|
||||||
|
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
; $ins w_tmp1, w_tmp1, W(map_gpr(GPR::RCX).x())
|
||||||
|
; str w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Size::S64, Location::Imm8(imm), Location::GPR(dst)) => {
|
||||||
|
assert!(imm < 32);
|
||||||
|
dynasm!($assembler ; $ins X(map_gpr(dst).x()), X(map_gpr(dst).x()), imm as u32);
|
||||||
|
},
|
||||||
|
(Size::S64, Location::Imm8(imm), Location::Memory(base, disp)) => {
|
||||||
|
assert!(imm < 32);
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!($assembler
|
||||||
|
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
; $ins x_tmp1, x_tmp1, imm as u32
|
||||||
|
; str x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Size::S64, Location::GPR(GPR::RCX), Location::GPR(dst)) => {
|
||||||
|
dynasm!($assembler ; $ins X(map_gpr(dst).x()), X(map_gpr(dst).x()), X(map_gpr(GPR::RCX).x()));
|
||||||
|
},
|
||||||
|
(Size::S64, Location::GPR(GPR::RCX), Location::Memory(base, disp)) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!($assembler
|
||||||
|
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
; $ins x_tmp1, x_tmp1, X(map_gpr(GPR::RCX).x())
|
||||||
|
; str x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
_ => $otherwise
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for Assembler {
|
impl Emitter for Assembler {
|
||||||
type Label = DynamicLabel;
|
type Label = DynamicLabel;
|
||||||
type Offset = AssemblyOffset;
|
type Offset = AssemblyOffset;
|
||||||
@ -629,26 +685,155 @@ impl Emitter for Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_div(&mut self, sz: Size, divisor: Location) {
|
fn emit_div(&mut self, sz: Size, divisor: Location) {
|
||||||
unimplemented!("instruction")
|
match sz {
|
||||||
|
Size::S32 => {
|
||||||
|
match divisor {
|
||||||
|
Location::GPR(x) => dynasm!(
|
||||||
|
self
|
||||||
|
; mov w_tmp1, W(map_gpr(x).x())
|
||||||
|
),
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov w_tmp2, W(map_gpr(GPR::RAX).x())
|
||||||
|
; udiv W(map_gpr(GPR::RAX).x()), w_tmp2, w_tmp1
|
||||||
|
; msub W(map_gpr(GPR::RDX).x()), W(map_gpr(GPR::RAX).x()), w_tmp1, w_tmp2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Size::S64 => {
|
||||||
|
match divisor {
|
||||||
|
Location::GPR(x) => dynasm!(
|
||||||
|
self
|
||||||
|
; mov x_tmp1, X(map_gpr(x).x())
|
||||||
|
),
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov x_tmp2, X(map_gpr(GPR::RAX).x())
|
||||||
|
; udiv X(map_gpr(GPR::RAX).x()), x_tmp2, x_tmp1
|
||||||
|
; msub X(map_gpr(GPR::RDX).x()), X(map_gpr(GPR::RAX).x()), x_tmp1, x_tmp2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn emit_idiv(&mut self, sz: Size, divisor: Location) {
|
fn emit_idiv(&mut self, sz: Size, divisor: Location) {
|
||||||
unimplemented!("instruction")
|
match sz {
|
||||||
|
Size::S32 => {
|
||||||
|
match divisor {
|
||||||
|
Location::GPR(x) => dynasm!(
|
||||||
|
self
|
||||||
|
; mov w_tmp1, W(map_gpr(x).x())
|
||||||
|
),
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov w_tmp2, W(map_gpr(GPR::RAX).x())
|
||||||
|
; sdiv W(map_gpr(GPR::RAX).x()), w_tmp2, w_tmp1
|
||||||
|
; msub W(map_gpr(GPR::RDX).x()), W(map_gpr(GPR::RAX).x()), w_tmp1, w_tmp2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Size::S64 => {
|
||||||
|
match divisor {
|
||||||
|
Location::GPR(x) => dynasm!(
|
||||||
|
self
|
||||||
|
; mov x_tmp1, X(map_gpr(x).x())
|
||||||
|
),
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov x_tmp2, X(map_gpr(GPR::RAX).x())
|
||||||
|
; sdiv X(map_gpr(GPR::RAX).x()), x_tmp2, x_tmp1
|
||||||
|
; msub X(map_gpr(GPR::RDX).x()), X(map_gpr(GPR::RAX).x()), x_tmp1, x_tmp2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
//binop_all_nofp!(ushl, self, sz, src, dst, { unreachable!("shl") });
|
binop_shift!(lsl, self, sz, src, dst, { unreachable!("shl") });
|
||||||
unimplemented!("instruction")
|
|
||||||
}
|
}
|
||||||
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
binop_shift!(lsr, self, sz, src, dst, { unreachable!("shr") });
|
||||||
}
|
}
|
||||||
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
binop_shift!(asr, self, sz, src, dst, { unreachable!("sar") });
|
||||||
}
|
}
|
||||||
fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
// TODO: We are changing content of `src` (possibly RCX) here. Will this break any assumptions?
|
||||||
|
match sz {
|
||||||
|
Size::S32 => {
|
||||||
|
match src {
|
||||||
|
Location::Imm8(x) => {
|
||||||
|
assert!(x < 32);
|
||||||
|
binop_shift!(ror, self, sz, Location::Imm8(32 - x), dst, { unreachable!("rol") });
|
||||||
|
}
|
||||||
|
Location::GPR(GPR::RCX) => {
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov w_tmp1, 32
|
||||||
|
; sub W(map_gpr(GPR::RCX).x()), w_tmp1, W(map_gpr(GPR::RCX).x())
|
||||||
|
);
|
||||||
|
binop_shift!(ror, self, sz, src, dst, { unreachable!("rol") });
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Size::S64 => {
|
||||||
|
match src {
|
||||||
|
Location::Imm8(x) => {
|
||||||
|
assert!(x < 64);
|
||||||
|
binop_shift!(ror, self, sz, Location::Imm8(64 - x), dst, { unreachable!("rol") });
|
||||||
|
}
|
||||||
|
Location::GPR(GPR::RCX) => {
|
||||||
|
dynasm!(
|
||||||
|
self
|
||||||
|
; mov x_tmp1, 64
|
||||||
|
; sub X(map_gpr(GPR::RCX).x()), x_tmp1, X(map_gpr(GPR::RCX).x())
|
||||||
|
);
|
||||||
|
binop_shift!(ror, self, sz, src, dst, { unreachable!("rol") });
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
binop_shift!(ror, self, sz, src, dst, { unreachable!("ror") });
|
||||||
}
|
}
|
||||||
fn emit_and(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_and(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(and, self, sz, src, dst, { unreachable!("and") });
|
binop_all_nofp!(and, self, sz, src, dst, { unreachable!("and") });
|
||||||
@ -657,89 +842,16 @@ impl Emitter for Assembler {
|
|||||||
binop_all_nofp!(orr, self, sz, src, dst, { unreachable!("or") });
|
binop_all_nofp!(orr, self, sz, src, dst, { unreachable!("or") });
|
||||||
}
|
}
|
||||||
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
match sz {
|
emit_clz_variant(self, sz, &src, &dst, false);
|
||||||
Size::S32 => {
|
|
||||||
match src {
|
|
||||||
Location::Imm32(x) => dynasm!(self
|
|
||||||
; b >after
|
|
||||||
; data:
|
|
||||||
; .dword x as i32
|
|
||||||
; after:
|
|
||||||
; ldr w_tmp2, <data
|
|
||||||
; clz w_tmp1, w_tmp2
|
|
||||||
),
|
|
||||||
Location::GPR(x) => dynasm!(self
|
|
||||||
; clz w_tmp1, W(map_gpr(x).x())
|
|
||||||
),
|
|
||||||
Location::Memory(base, disp) => {
|
|
||||||
assert!(disp >= 0);
|
|
||||||
dynasm!(self
|
|
||||||
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
|
||||||
; clz w_tmp1, w_tmp1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
match dst {
|
|
||||||
Location::GPR(x) => dynasm!(
|
|
||||||
self
|
|
||||||
; mov W(map_gpr(x).x()), w_tmp1
|
|
||||||
),
|
|
||||||
Location::Memory(base, disp) => {
|
|
||||||
assert!(disp >= 0);
|
|
||||||
dynasm!(
|
|
||||||
self
|
|
||||||
; str w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Size::S64 => {
|
|
||||||
match src {
|
|
||||||
Location::Imm32(x) => dynasm!(self
|
|
||||||
; b >after
|
|
||||||
; data:
|
|
||||||
; .qword x as i64
|
|
||||||
; after:
|
|
||||||
; ldr x_tmp2, <data
|
|
||||||
; clz x_tmp1, x_tmp2
|
|
||||||
),
|
|
||||||
Location::GPR(x) => dynasm!(self
|
|
||||||
; clz x_tmp1, X(map_gpr(x).x())
|
|
||||||
),
|
|
||||||
Location::Memory(base, disp) => {
|
|
||||||
assert!(disp >= 0);
|
|
||||||
dynasm!(self
|
|
||||||
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
|
||||||
; clz x_tmp1, x_tmp1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
match dst {
|
|
||||||
Location::GPR(x) => dynasm!(
|
|
||||||
self
|
|
||||||
; mov X(map_gpr(x).x()), x_tmp1
|
|
||||||
),
|
|
||||||
Location::Memory(base, disp) => {
|
|
||||||
assert!(disp >= 0);
|
|
||||||
dynasm!(
|
|
||||||
self
|
|
||||||
; str x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
emit_clz_variant(self, sz, &src, &dst, true);
|
||||||
}
|
}
|
||||||
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
unimplemented!("instruction")
|
dynasm!(
|
||||||
|
self
|
||||||
|
; brk 90 // TODO: Implement
|
||||||
|
);
|
||||||
}
|
}
|
||||||
fn emit_movzx(&mut self, sz_src: Size, src: Location, _sz_dst: Size, dst: Location) {
|
fn emit_movzx(&mut self, sz_src: Size, src: Location, _sz_dst: Size, dst: Location) {
|
||||||
match (sz_src, src, dst) {
|
match (sz_src, src, dst) {
|
||||||
@ -799,16 +911,15 @@ impl Emitter for Assembler {
|
|||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
unimplemented!("instruction")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: These instructions are only used in FP opcodes. Implement later.
|
||||||
fn emit_btc_gpr_imm8_32(&mut self, src: u8, dst: GPR) {
|
fn emit_btc_gpr_imm8_32(&mut self, src: u8, dst: GPR) {
|
||||||
unimplemented!("instruction")
|
unimplemented!("instruction")
|
||||||
}
|
}
|
||||||
fn emit_btc_gpr_imm8_64(&mut self, src: u8, dst: GPR) {
|
fn emit_btc_gpr_imm8_64(&mut self, src: u8, dst: GPR) {
|
||||||
unimplemented!("instruction")
|
unimplemented!("instruction")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_cmovae_gpr_32(&mut self, src: GPR, dst: GPR) {
|
fn emit_cmovae_gpr_32(&mut self, src: GPR, dst: GPR) {
|
||||||
unimplemented!("instruction")
|
unimplemented!("instruction")
|
||||||
}
|
}
|
||||||
@ -1093,3 +1204,69 @@ impl Emitter for Assembler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_clz_variant(assembler: &mut Assembler, sz: Size, src: &Location, dst: &Location, reversed: bool) {
|
||||||
|
match sz {
|
||||||
|
Size::S32 => {
|
||||||
|
match *src {
|
||||||
|
Location::GPR(src) => {
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; mov w_tmp1, W(map_gpr(src).x())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; ldr w_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
match *dst {
|
||||||
|
Location::GPR(dst) => {
|
||||||
|
if reversed {
|
||||||
|
dynasm!(assembler ; rbit w_tmp1, w_tmp1);
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; clz W(map_gpr(dst).x()), w_tmp1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Size::S64 => {
|
||||||
|
match *src {
|
||||||
|
Location::GPR(src) => {
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; mov x_tmp1, X(map_gpr(src).x())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Location::Memory(base, disp) => {
|
||||||
|
assert!(disp >= 0);
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; ldr x_tmp1, [X(map_gpr(base).x()), disp as u32]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
match *dst {
|
||||||
|
Location::GPR(dst) => {
|
||||||
|
if reversed {
|
||||||
|
dynasm!(assembler ; rbit x_tmp1, x_tmp1)
|
||||||
|
}
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; clz X(map_gpr(dst).x()), x_tmp1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user