diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 7d0b92c5b0f5..d4cd8f4c086e 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -2769,6 +2769,23 @@ pub(crate) fn define( .operands_out(vec![a]), ); + // todo evan: are the argument types right for u64/u32/16 ?? + // what is an iB? + // + ig.push( + Inst::new( + "bswap", + r#" + Reverse the byte order of an integer. + + Reverses the bytes in ``x``. + "#, + &formats.unary, + ) + .operands_in(vec![x]) + .operands_out(vec![a]), + ); + ig.push( Inst::new( "clz", diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index 808c79f71691..49402d0425fe 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -96,6 +96,14 @@ pub(crate) fn lower_insn_to_regs( Opcode::Bitrev | Opcode::Clz | Opcode::Cls | Opcode::Ctz => implemented_in_isle(ctx), + Opcode::Bswap => { + unreachable!( + "TODO: not yet implemented in ISLE: inst = `{}`, type = `{:?}`", + ctx.dfg().display_inst(ir_inst), + ty + ) + } + Opcode::Popcnt => implemented_in_isle(ctx), Opcode::Load diff --git a/cranelift/codegen/src/isa/s390x/lower.rs b/cranelift/codegen/src/isa/s390x/lower.rs index a78a099aabb4..6951b9837461 100644 --- a/cranelift/codegen/src/isa/s390x/lower.rs +++ b/cranelift/codegen/src/isa/s390x/lower.rs @@ -207,7 +207,8 @@ impl LowerBackend for S390xBackend { | Opcode::DynamicStackLoad | Opcode::DynamicStackStore | Opcode::DynamicStackAddr - | Opcode::ExtractVector => { + | Opcode::ExtractVector + | Opcode::Bswap => { unreachable!( "TODO: not yet implemented in ISLE: inst = `{}`, type = `{:?}`", ctx.dfg().display_inst(ir_inst), diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 0700b628744a..11086982f076 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -151,6 +151,12 @@ (Setcc (cc CC) (dst WritableGpr)) + ;; todo evan how to give different sizes + ;; todo evan where to put the xchg impl - hide behind this or expose? + ;; Byteswap + (Bswap (size OperandSize) ;; 4 or 8 + (dst WritableGpr)) + ;; ========================================= ;; Conditional moves. @@ -566,6 +572,8 @@ Tzcnt Popcnt)) +;; todo evan define Opcodes for BSWAP and XCHG + (type DivOrRemKind extern (enum SignedDiv UnsignedDiv @@ -1965,6 +1973,26 @@ (rule (x64_sar ty src1 src2) (shift_r ty (ShiftKind.ShiftRightArithmetic) src1 src2)) +;; Helpers for creating byteswap instructions. +;; In x64, 32- and 64-bit registers use BSWAP instruction, however +;; this instruction is undefined for 16-bit registers, which instead +;; use XCHG + +;; TODO EVAN +;; (decl unaryop_bswap (Type) UnaryOp) +;; (rule (unaryop_bswap $I32) (UnaryOp.BSwap32)) +;; (rule (unaryop_bswap $I64) (UnaryOp.BSwap64)) + +;; (decl bswap_reg (Type Reg) Reg) +;; (rule (bswap_reg ty x) (unary_rr ty (unaryop_bswap ty) x)) + +;; (decl x64_bswap (Type Gpr) Gpr) +;; (rule (x64_bswap ty src) +;; (let ((dst WritableGpr (temp_writable_gpr)) +;; (size OperandSize (operand_size_of_type_32_64 ty)) +;; (_ Unit (emit (MInst.UnaryRmR size (UnaryRmROpcode.Lzcnt) src dst)))) +;; dst)) + ;; Helper for creating `MInst.CmpRmiR` instructions. (decl cmp_rmi_r (OperandSize CmpOpcode GprMemImm Gpr) ProducesFlags) (rule (cmp_rmi_r size opcode src1 src2) diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index e51e7e29c761..38e4bb84f979 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -1115,6 +1115,8 @@ pub(crate) fn emit( ); } + // todo evan: implement BSWAP like the ShiftR? + Inst::Cmove { size, cc, diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index ae92b7307ef2..85caf49c97d9 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -68,6 +68,7 @@ impl Inst { Inst::AluRmiR { .. } | Inst::AluRM { .. } | Inst::AtomicRmwSeq { .. } + | Inst::Bswap { .. } | Inst::CallKnown { .. } | Inst::CallUnknown { .. } | Inst::CheckedDivOrRemSeq { .. } @@ -1373,6 +1374,11 @@ impl PrettyPrint for Inst { format!("{} {}", ljustify2("set".to_string(), cc.to_string()), dst) } + Inst::Bswap { size, dst } => { + let dst = pretty_print_reg(dst.to_reg().to_reg(), size.to_bytes(), allocs); + format!("{} {}", ljustify2("bswap".to_string(), suffix_bwlq(*size)), dst) + } + Inst::Cmove { size, cc, @@ -1953,6 +1959,9 @@ fn x64_get_operands VReg>(inst: &Inst, collector: &mut OperandCol Inst::Setcc { dst, .. } => { collector.reg_def(dst.to_writable_reg()); } + Inst::Bswap { dst, .. } => { + collector.reg_def(dst.to_writable_reg()); + } Inst::Cmove { consequent, alternative, diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index c03239b8de74..4b15b194aec9 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -2044,6 +2044,12 @@ hi32))) swap32)) +;; todo evan +;; Rules for `bswap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; (rule (lower (has_type $I64 (bswap src))) +;; (do_bswap64 $I64 src)) + ;; Rules for `is_null` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Null references are represented by the constant value `0`. diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index 836b2c005663..367eff24a800 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -365,6 +365,7 @@ fn lower_insn_to_regs( | Opcode::Ctz | Opcode::Popcnt | Opcode::Bitrev + | Opcode::Bswap | Opcode::IsNull | Opcode::IsInvalid | Opcode::Uextend