Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,22 @@
(rd WritableReg)
(mem MemArg))

;; Load address referenced by `mem` into `rd`.
(LoadIndexedAddr
(rd WritableReg)
(base Reg)
(index Reg)
(offset SImm20)
(size u8))

;; Load address referenced by `mem` into `rd`.
(LoadLogicalIndexedAddr
(rd WritableReg)
(base Reg)
(index Reg)
(offset SImm20)
(size u8))

;; Meta-instruction to emit a loop around a sequence of instructions.
;; This control flow is not visible to the compiler core, in particular
;; the register allocator. Therefore, instructions in the loop may not
Expand Down Expand Up @@ -1741,6 +1757,9 @@
(decl u32_from_value (u32) Value)
(extern extractor u32_from_value u32_from_value)

(decl u16_from_value (u16) Value)
(extern extractor u16_from_value u16_from_value)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now this is unused :-)


(decl u8_from_value (u8) Value)
(extern extractor u8_from_value u8_from_value)

Expand Down Expand Up @@ -1774,6 +1793,9 @@
(decl uimm16shifted_from_value (UImm16Shifted) Value)
(extern extractor uimm16shifted_from_value uimm16shifted_from_value)

(decl simm20_from_value (SImm20) Value)
(extern extractor simm20_from_value simm20_from_value)

(decl uimm32shifted_from_value (UImm32Shifted) Value)
(extern extractor uimm32shifted_from_value uimm32shifted_from_value)

Expand Down Expand Up @@ -1927,6 +1949,23 @@
(if-let final_offset (memarg_symbol_offset_sum offset sym_offset))
(memarg_symbol name final_offset flags))

(rule 2 (lower_address flags (has_type (mie4_enabled)
(iadd $I64 (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z)))
(u8_from_value shift)) y)) (i64_from_offset offset))
(memarg_reg_plus_off (load_logical_indexed_addr x y z shift) offset 0 flags))

(rule 3 (lower_address flags (has_type (mie4_enabled)
(iadd $I64 y (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z)))
(u8_from_value shift)))) (i64_from_offset offset))
(memarg_reg_plus_off (load_logical_indexed_addr y x z shift) offset 0 flags))

(rule 4 (lower_address flags (has_type (mie4_enabled)
(iadd $I64 (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)) (i64_from_offset offset))
(memarg_reg_plus_off (load_indexed_addr x y z shift) offset 0 flags))

(rule 5 (lower_address flags (has_type (mie4_enabled)
(iadd $I64 y (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))) (i64_from_offset offset))
(memarg_reg_plus_off (load_indexed_addr y x z shift) offset 0 flags))

;; Lower an address plus a small bias into a `MemArg`.

Expand Down Expand Up @@ -2817,6 +2856,20 @@
(_ Unit (emit (MInst.LoadAddr dst mem))))
dst))

;; Helper for emitting `MInst.LoadIndexedAddr` instructions.
(decl load_indexed_addr (Reg Reg SImm20 u8) Reg)
(rule (load_indexed_addr base index offset size)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.LoadIndexedAddr dst base index offset size))))
dst))

;; Helper for emitting `MInst.LoadLogicalIndexedAddr` instructions.
(decl load_logical_indexed_addr (Reg Reg SImm20 u8) Reg)
(rule (load_logical_indexed_addr base index offset size)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.LoadLogicalIndexedAddr dst base index offset size))))
dst))

;; Helper for emitting `MInst.Call` instructions.
(decl call_impl (WritableReg BoxCallInfo) SideEffectNoResult)
(rule (call_impl reg info)
Expand Down
26 changes: 26 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,32 @@ impl Inst {
rd, &mem, opcode_rx, opcode_rxy, opcode_ril, false, sink, emit_info, state,
);
}
&Inst::LoadIndexedAddr {
rd,
base,
index,
offset,
size,
} => {
let opcode: u16 = 0xe360 | (size as u16 & 0xf) << 1;
put(
sink,
&enc_rxy(opcode, rd.to_reg(), base, index, offset.bits()),
);
}
&Inst::LoadLogicalIndexedAddr {
rd,
base,
index,
offset,
size,
} => {
let opcode: u16 = 0xe361 | (size as u16 & 0xf) << 1;
put(
sink,
&enc_rxy(opcode, rd.to_reg(), base, index, offset.bits()),
);
}

&Inst::Mov64 { rd, rm } => {
let opcode = 0xb904; // LGR
Expand Down
44 changes: 44 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13929,6 +13929,50 @@ fn test_s390x_binemit() {
"E7480001384D",
"vrepg %v20, %v8, 1",
));
insns.push((
Inst::LoadIndexedAddr {
rd: writable_gpr(1),
base: gpr(2),
index: gpr(3),
offset: SImm20::maybe_from_i64(0x7ffff).unwrap(),
size: 3,
},
"E3132FFF7F66",
"lxag %r1, 524287(%r3,%r2)",
));
insns.push((
Inst::LoadIndexedAddr {
rd: writable_gpr(1),
base: gpr(2),
index: gpr(3),
offset: SImm20::maybe_from_i64(-2).unwrap(),
size: 4,
},
"E3132FFEFF68",
"lxaq %r1, -2(%r3,%r2)",
));
insns.push((
Inst::LoadLogicalIndexedAddr {
rd: writable_gpr(1),
base: gpr(2),
index: gpr(3),
offset: SImm20::maybe_from_i64(0x7ffff).unwrap(),
size: 2,
},
"E3132FFF7F65",
"llxaf %r1, 524287(%r3,%r2)",
));
insns.push((
Inst::LoadLogicalIndexedAddr {
rd: writable_gpr(1),
base: gpr(2),
index: gpr(3),
offset: SImm20::maybe_from_i64(-2).unwrap(),
size: 1,
},
"E3132FFEFF63",
"llxah %r1, -2(%r3,%r2)",
));

let flags = settings::Flags::new(settings::builder());

Expand Down
70 changes: 69 additions & 1 deletion cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module defines s390x-specific machine instruction types.

use crate::binemit::{Addend, CodeOffset, Reloc};
use crate::ir::{ExternalName, Type, types};
use crate::ir::{ExternalName, MemFlags, Type, types};
use crate::isa::s390x::abi::S390xMachineDeps;
use crate::isa::{CallConv, FunctionAlignment};
use crate::machinst::*;
Expand Down Expand Up @@ -240,6 +240,10 @@ impl Inst {
| Inst::Unwind { .. }
| Inst::ElfTlsGetOffset { .. } => InstructionSet::Base,

Inst::LoadIndexedAddr { .. } | Inst::LoadLogicalIndexedAddr { .. } => {
InstructionSet::MIE4
}

// These depend on the opcode
Inst::AluRRR { alu_op, .. } => match alu_op {
ALUOp::NotAnd32 | ALUOp::NotAnd64 => InstructionSet::MIE3,
Expand Down Expand Up @@ -1030,6 +1034,20 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
collector.reg_def(rd);
memarg_operands(mem, collector);
}
Inst::LoadIndexedAddr {
rd, base, index, ..
} => {
collector.reg_def(rd);
collector.reg_use(base);
collector.reg_use(index);
}
Inst::LoadLogicalIndexedAddr {
rd, base, index, ..
} => {
collector.reg_def(rd);
collector.reg_use(base);
collector.reg_use(index);
}
Inst::StackProbeLoop { probe_count, .. } => {
collector.reg_early_def(probe_count);
}
Expand Down Expand Up @@ -3507,6 +3525,56 @@ impl Inst {

format!("{mem_str}{op} {rd}, {mem}")
}
&Inst::LoadIndexedAddr {
rd,
base,
index,
offset,
size,
} => {
let rd = pretty_print_reg(rd.to_reg());
let op = match size {
1 => "lxah",
2 => "lxaf",
3 => "lxag",
4 => "lxaq",
_ => unreachable!(),
};
let flags = MemFlags::trusted();
let mem = MemArg::BXD20 {
base,
index,
disp: offset,
flags,
};
let mem = mem.pretty_print_default();
format!("{op} {rd}, {mem}")
}
&Inst::LoadLogicalIndexedAddr {
rd,
base,
index,
offset,
size,
} => {
let rd = pretty_print_reg(rd.to_reg());
let op = match size {
1 => "llxah",
2 => "llxaf",
3 => "llxag",
4 => "llxaq",
_ => unreachable!(),
};
let flags = MemFlags::trusted();
let mem = MemArg::BXD20 {
base,
index,
disp: offset,
flags,
};
let mem = mem.pretty_print_default();
format!("{op} {rd}, {mem}")
}
&Inst::StackProbeLoop {
probe_count,
guard_size,
Expand Down
15 changes: 15 additions & 0 deletions cranelift/codegen/src/isa/s390x/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@
(rule 1 (lower (has_type (vr128_ty ty) (iadd _ x y)))
(vec_add ty x y))

(rule 16 (lower (has_type (mie4_enabled)
(iadd $I64 (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)))
(load_logical_indexed_addr x y z shift))

(rule 17 (lower (has_type (mie4_enabled)
(iadd $I64 y (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))))
(load_logical_indexed_addr y x z shift))

(rule 18 (lower (has_type (and (ty_addr64 _) (mie4_enabled))
(iadd $I64 (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)))
(load_indexed_addr x y z shift))

(rule 19 (lower (has_type (and (ty_addr64 _) (mie4_enabled))
(iadd $I64 y (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))))
(load_indexed_addr y x z shift))

;;;; Rules for `uadd_sat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
13 changes: 13 additions & 0 deletions cranelift/codegen/src/isa/s390x/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,13 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
Some(imm)
}

#[inline]
fn u16_from_value(&mut self, val: Value) -> Option<u16> {
let constant = self.u64_from_value(val)?;
let imm = u16::try_from(constant).ok()?;
Some(imm)
}

#[inline]
fn u8_from_value(&mut self, val: Value) -> Option<u8> {
let constant = self.u64_from_value(val)?;
Expand Down Expand Up @@ -547,6 +554,12 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
UImm16Shifted::maybe_from_u64(constant)
}

#[inline]
fn simm20_from_value(&mut self, val: Value) -> Option<SImm20> {
let constant = self.u64_from_value(val)? as i64;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be u64_from_signed_value I think.

SImm20::maybe_from_i64(constant)
}

#[inline]
fn uimm32shifted_from_value(&mut self, val: Value) -> Option<UImm32Shifted> {
let constant = self.u64_from_value(val)?;
Expand Down
46 changes: 46 additions & 0 deletions cranelift/filetests/filetests/isa/s390x/arithmetic-arch15.clif
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,49 @@ block0(v0: i128):
; vst %v4, 0(%r2)
; br %r14

function %i64_i32_offset_mul_unsigned(i64, i32) -> i64 {
block0(v0: i64, v1: i32):
v2 = iconst.i8 4
v3 = iconst.i32 8000
v4 = iadd v1, v3
v5 = uextend.i64 v4
v6 = ishl v5, v2
v7 = iadd v0, v6
return v7
}

; VCode:
; block0:
; llxaq %r2, 8000(%r3,%r2)
; br %r14
;
; Disassembled:
; block0: ; offset 0x0
; .byte 0xe3, 0x23
; swr %f4, %f0
; .byte 0x01, 0x69
; br %r14

function %uload8_i64_i64_offset_mul_signed(i64, i32) -> i64 {
block0(v0: i64, v1: i32):
v2 = iconst.i8 4
v3 = iconst.i32 8000
v4 = iadd v1, v3
v5 = sextend.i64 v4
v6 = ishl v5, v2
v7 = iadd v0, v6
return v7
}

; VCode:
; block0:
; lxaq %r2, 8000(%r3,%r2)
; br %r14
;
; Disassembled:
; block0: ; offset 0x0
; .byte 0xe3, 0x23
; swr %f4, %f0
; .byte 0x01, 0x68
; br %r14

Loading
Loading