Skip to content

Commit

Permalink
stdlib: implement Int64#reverseBytes and Int32#reverseBytes
Browse files Browse the repository at this point in the history
fixes #83
  • Loading branch information
soc committed Sep 6, 2023
1 parent 316a656 commit 61288a8
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 0 deletions.
12 changes: 12 additions & 0 deletions dora-asm/src/x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,18 @@ impl AssemblerX64 {
self.emit_modrm_opcode(0b001, opnd);
}

pub fn bswapl_r(&mut self, opnd: Register) {
self.emit_rex_optional(false, opnd.needs_rex(), false, false);
self.emit_u8(0x0f);
self.emit_u8(0xc8 | opnd.low_bits());
}

pub fn bswapq_r(&mut self, opnd: Register) {
self.emit_rex(true, opnd.needs_rex(), false, false);
self.emit_u8(0x0f);
self.emit_u8(0xc8 | opnd.low_bits());
}

pub fn xaddq_ar(&mut self, dest: Address, src: Register) {
self.emit_rex64_modrm_address(src, dest);
self.emit_u8(0x0f);
Expand Down
21 changes: 21 additions & 0 deletions dora/src/cannon/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,21 @@ impl<'a> CannonCodeGen<'a> {
self.emit_store_register(REG_RESULT.into(), dest);
}

fn emit_reverse_bytes(&mut self, dest: Register, src: Register) {
assert_eq!(
self.bytecode.register_type(src),
self.bytecode.register_type(dest)
);

self.emit_load_register(src, REG_RESULT.into());

let bytecode_type = self.bytecode.register_type(dest);
self.asm
.int_reverse_bytes(mode(self.vm, bytecode_type), REG_RESULT, REG_RESULT);

self.emit_store_register(REG_RESULT.into(), dest);
}

fn emit_reinterpret(&mut self, dest: Register, src: Register) {
assert_ne!(
self.bytecode.register_type(dest),
Expand Down Expand Up @@ -3883,6 +3898,12 @@ impl<'a> CannonCodeGen<'a> {
self.emit_ror_int(dest, lhs_reg, rhs_reg);
}

Intrinsic::Int32ReverseBytes | Intrinsic::Int64ReverseBytes => {
assert_eq!(arguments.len(), 1);
let src_reg = arguments[0];
self.emit_reverse_bytes(dest, src_reg);
}

Intrinsic::ThreadCurrent => {
assert_eq!(arguments.len(), 0);
self.asm.thread_current(REG_RESULT);
Expand Down
4 changes: 4 additions & 0 deletions dora/src/compiler/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,10 @@ impl<'a> BaselineAssembler<'a> {
self.masm.int_ror(mode, dest, lhs, rhs);
}

pub fn int_reverse_bytes(&mut self, mode: MachineMode, dest: Reg, src: Reg) {
self.masm.int_reverse_bytes(mode, dest, src);
}

pub fn count_bits(&mut self, mode: MachineMode, dest: Reg, src: Reg, count_one_bits: bool) {
self.masm.count_bits(mode, dest, src, count_one_bits);
}
Expand Down
8 changes: 8 additions & 0 deletions dora/src/language/sem_analysis/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ pub enum Intrinsic {
Int32RotateLeft,
Int32RotateRight,

Int32ReverseBytes,

Int32Not,
Int32Neg,
Int32Plus,
Expand Down Expand Up @@ -383,6 +385,8 @@ pub enum Intrinsic {
Int64RotateLeft,
Int64RotateRight,

Int64ReverseBytes,

Int64Not,
Int64Neg,
Int64Plus,
Expand Down Expand Up @@ -546,6 +550,8 @@ impl Intrinsic {
| Intrinsic::Int32RotateRight
| Intrinsic::Int64RotateLeft
| Intrinsic::Int64RotateRight
| Intrinsic::Int32ReverseBytes
| Intrinsic::Int64ReverseBytes
| Intrinsic::ThreadCurrent => true,
_ => false,
}
Expand All @@ -569,6 +575,7 @@ impl Intrinsic {
| Intrinsic::Int32Sar
| Intrinsic::Int32RotateLeft
| Intrinsic::Int32RotateRight
| Intrinsic::Int32ReverseBytes
| Intrinsic::Int32Not
| Intrinsic::Int32Plus
| Intrinsic::Int32Neg
Expand Down Expand Up @@ -616,6 +623,7 @@ impl Intrinsic {
| Intrinsic::Int64Sar
| Intrinsic::Int64RotateLeft
| Intrinsic::Int64RotateRight
| Intrinsic::Int64ReverseBytes
| Intrinsic::Int64Not
| Intrinsic::Int64Plus
| Intrinsic::Int64Neg
Expand Down
16 changes: 16 additions & 0 deletions dora/src/language/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,14 @@ pub fn resolve_internal_functions(sa: &mut SemAnalysis) {
Intrinsic::Int32RotateRight,
);

intrinsic_method(
sa,
stdlib_id,
"primitives::Int32",
"reverseBytes",
Intrinsic::Int32ReverseBytes,
);

intrinsic_method(
sa,
stdlib_id,
Expand Down Expand Up @@ -920,6 +928,14 @@ pub fn resolve_internal_functions(sa: &mut SemAnalysis) {
Intrinsic::Int64RotateRight,
);

intrinsic_method(
sa,
stdlib_id,
"primitives::Int64",
"reverseBytes",
Intrinsic::Int64ReverseBytes,
);

intrinsic_method(
sa,
stdlib_id,
Expand Down
8 changes: 8 additions & 0 deletions dora/src/masm/arm64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ impl MacroAssembler {
}
}

pub fn int_reverse_bytes(&mut self, mode: MachineMode, dest: Reg, src: Reg) {
match mode {
MachineMode::Int32 => self.asm.rev_w(dest.into(), src.into()),
MachineMode::Int64 => self.asm.rev(dest.into(), src.into()),
_ => panic!("unimplemented mode {:?}", mode),
}
}

pub fn count_bits(&mut self, mode: MachineMode, dest: Reg, src: Reg, count_one_bits: bool) {
let scratch = FREG_TMP1;
let scratch_src = self.get_scratch();
Expand Down
12 changes: 12 additions & 0 deletions dora/src/masm/x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,18 @@ impl MacroAssembler {
}
}

pub fn int_reverse_bytes(&mut self, mode: MachineMode, dest: Reg, src: Reg) {
if mode.is64() {
self.asm.bswapq_r(src.into());
} else {
self.asm.bswapl_r(src.into());
}

if dest != src {
self.mov_rr(mode.is64(), dest.into(), src.into());
}
}

pub fn count_bits(&mut self, mode: MachineMode, dest: Reg, src: Reg, count_one_bits: bool) {
if count_one_bits {
if mode.is64() {
Expand Down
4 changes: 4 additions & 0 deletions dora/stdlib/primitives.dora
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ impl Int32 {
@pub @internal fun rotateLeft(by: Int32): Int32;
@pub @internal fun rotateRight(by: Int32): Int32;

@pub @internal fun reverseBytes(): Int32;

@pub @internal fun unaryPlus(): Int32;
@pub @internal fun unaryMinus(): Int32;
@pub @internal fun not(): Int32;
Expand Down Expand Up @@ -243,6 +245,8 @@ impl Int64 {
@pub @internal fun rotateLeft(by: Int32): Int64;
@pub @internal fun rotateRight(by: Int32): Int64;

@pub @internal fun reverseBytes(): Int64;

@pub @internal fun unaryPlus(): Int64;
@pub @internal fun unaryMinus(): Int64;
@pub @internal fun not(): Int64;
Expand Down
3 changes: 3 additions & 0 deletions tests/int/int32-reverseBytes.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fun main(): Unit {
assert(0x01234567i32.reverseBytes() == 0x67452301i32);
}
3 changes: 3 additions & 0 deletions tests/int/int64-reverseBytes.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fun main(): Unit {
assert(0x0123456789ABCDEF.reverseBytes() == 0xEFCDAB8967452301);
}

0 comments on commit 61288a8

Please sign in to comment.