Skip to content

Commit f8d0aee

Browse files
s390x-z17: Implement load indexed address instruction (bytecodealliance#12707)
1 parent 51959f2 commit f8d0aee

9 files changed

Lines changed: 376 additions & 1 deletion

File tree

cranelift/codegen/src/isa/s390x/inst.isle

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,22 @@
10081008
(rd WritableReg)
10091009
(mem MemArg))
10101010

1011+
;; Load address referenced by `mem` into `rd`.
1012+
(LoadIndexedAddr
1013+
(rd WritableReg)
1014+
(base Reg)
1015+
(index Reg)
1016+
(offset SImm20)
1017+
(size u8))
1018+
1019+
;; Load address referenced by `mem` into `rd`.
1020+
(LoadLogicalIndexedAddr
1021+
(rd WritableReg)
1022+
(base Reg)
1023+
(index Reg)
1024+
(offset SImm20)
1025+
(size u8))
1026+
10111027
;; Meta-instruction to emit a loop around a sequence of instructions.
10121028
;; This control flow is not visible to the compiler core, in particular
10131029
;; the register allocator. Therefore, instructions in the loop may not
@@ -1774,6 +1790,9 @@
17741790
(decl uimm16shifted_from_value (UImm16Shifted) Value)
17751791
(extern extractor uimm16shifted_from_value uimm16shifted_from_value)
17761792

1793+
(decl simm20_from_value (SImm20) Value)
1794+
(extern extractor simm20_from_value simm20_from_value)
1795+
17771796
(decl uimm32shifted_from_value (UImm32Shifted) Value)
17781797
(extern extractor uimm32shifted_from_value uimm32shifted_from_value)
17791798

@@ -1927,6 +1946,23 @@
19271946
(if-let final_offset (memarg_symbol_offset_sum offset sym_offset))
19281947
(memarg_symbol name final_offset flags))
19291948

1949+
(rule 2 (lower_address flags (has_type (mie4_enabled)
1950+
(iadd $I64 (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z)))
1951+
(u8_from_value shift)) y)) (i64_from_offset offset))
1952+
(memarg_reg_plus_off (load_logical_indexed_addr x y z shift) offset 0 flags))
1953+
1954+
(rule 3 (lower_address flags (has_type (mie4_enabled)
1955+
(iadd $I64 y (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z)))
1956+
(u8_from_value shift)))) (i64_from_offset offset))
1957+
(memarg_reg_plus_off (load_logical_indexed_addr y x z shift) offset 0 flags))
1958+
1959+
(rule 4 (lower_address flags (has_type (mie4_enabled)
1960+
(iadd $I64 (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)) (i64_from_offset offset))
1961+
(memarg_reg_plus_off (load_indexed_addr x y z shift) offset 0 flags))
1962+
1963+
(rule 5 (lower_address flags (has_type (mie4_enabled)
1964+
(iadd $I64 y (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))) (i64_from_offset offset))
1965+
(memarg_reg_plus_off (load_indexed_addr y x z shift) offset 0 flags))
19301966

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

@@ -2817,6 +2853,20 @@
28172853
(_ Unit (emit (MInst.LoadAddr dst mem))))
28182854
dst))
28192855

2856+
;; Helper for emitting `MInst.LoadIndexedAddr` instructions.
2857+
(decl load_indexed_addr (Reg Reg SImm20 u8) Reg)
2858+
(rule (load_indexed_addr base index offset size)
2859+
(let ((dst WritableReg (temp_writable_reg $I64))
2860+
(_ Unit (emit (MInst.LoadIndexedAddr dst base index offset size))))
2861+
dst))
2862+
2863+
;; Helper for emitting `MInst.LoadLogicalIndexedAddr` instructions.
2864+
(decl load_logical_indexed_addr (Reg Reg SImm20 u8) Reg)
2865+
(rule (load_logical_indexed_addr base index offset size)
2866+
(let ((dst WritableReg (temp_writable_reg $I64))
2867+
(_ Unit (emit (MInst.LoadLogicalIndexedAddr dst base index offset size))))
2868+
dst))
2869+
28202870
;; Helper for emitting `MInst.Call` instructions.
28212871
(decl call_impl (WritableReg BoxCallInfo) SideEffectNoResult)
28222872
(rule (call_impl reg info)

cranelift/codegen/src/isa/s390x/inst/emit.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,6 +2321,32 @@ impl Inst {
23212321
rd, &mem, opcode_rx, opcode_rxy, opcode_ril, false, sink, emit_info, state,
23222322
);
23232323
}
2324+
&Inst::LoadIndexedAddr {
2325+
rd,
2326+
base,
2327+
index,
2328+
offset,
2329+
size,
2330+
} => {
2331+
let opcode: u16 = 0xe360 | (size as u16 & 0xf) << 1;
2332+
put(
2333+
sink,
2334+
&enc_rxy(opcode, rd.to_reg(), base, index, offset.bits()),
2335+
);
2336+
}
2337+
&Inst::LoadLogicalIndexedAddr {
2338+
rd,
2339+
base,
2340+
index,
2341+
offset,
2342+
size,
2343+
} => {
2344+
let opcode: u16 = 0xe361 | (size as u16 & 0xf) << 1;
2345+
put(
2346+
sink,
2347+
&enc_rxy(opcode, rd.to_reg(), base, index, offset.bits()),
2348+
);
2349+
}
23242350

23252351
&Inst::Mov64 { rd, rm } => {
23262352
let opcode = 0xb904; // LGR

cranelift/codegen/src/isa/s390x/inst/emit_tests.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13929,6 +13929,50 @@ fn test_s390x_binemit() {
1392913929
"E7480001384D",
1393013930
"vrepg %v20, %v8, 1",
1393113931
));
13932+
insns.push((
13933+
Inst::LoadIndexedAddr {
13934+
rd: writable_gpr(1),
13935+
base: gpr(2),
13936+
index: gpr(3),
13937+
offset: SImm20::maybe_from_i64(0x7ffff).unwrap(),
13938+
size: 3,
13939+
},
13940+
"E3132FFF7F66",
13941+
"lxag %r1, 524287(%r3,%r2)",
13942+
));
13943+
insns.push((
13944+
Inst::LoadIndexedAddr {
13945+
rd: writable_gpr(1),
13946+
base: gpr(2),
13947+
index: gpr(3),
13948+
offset: SImm20::maybe_from_i64(-2).unwrap(),
13949+
size: 4,
13950+
},
13951+
"E3132FFEFF68",
13952+
"lxaq %r1, -2(%r3,%r2)",
13953+
));
13954+
insns.push((
13955+
Inst::LoadLogicalIndexedAddr {
13956+
rd: writable_gpr(1),
13957+
base: gpr(2),
13958+
index: gpr(3),
13959+
offset: SImm20::maybe_from_i64(0x7ffff).unwrap(),
13960+
size: 2,
13961+
},
13962+
"E3132FFF7F65",
13963+
"llxaf %r1, 524287(%r3,%r2)",
13964+
));
13965+
insns.push((
13966+
Inst::LoadLogicalIndexedAddr {
13967+
rd: writable_gpr(1),
13968+
base: gpr(2),
13969+
index: gpr(3),
13970+
offset: SImm20::maybe_from_i64(-2).unwrap(),
13971+
size: 1,
13972+
},
13973+
"E3132FFEFF63",
13974+
"llxah %r1, -2(%r3,%r2)",
13975+
));
1393213976

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

cranelift/codegen/src/isa/s390x/inst/mod.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module defines s390x-specific machine instruction types.
22
33
use crate::binemit::{Addend, CodeOffset, Reloc};
4-
use crate::ir::{ExternalName, Type, types};
4+
use crate::ir::{ExternalName, MemFlags, Type, types};
55
use crate::isa::s390x::abi::S390xMachineDeps;
66
use crate::isa::{CallConv, FunctionAlignment};
77
use crate::machinst::*;
@@ -240,6 +240,10 @@ impl Inst {
240240
| Inst::Unwind { .. }
241241
| Inst::ElfTlsGetOffset { .. } => InstructionSet::Base,
242242

243+
Inst::LoadIndexedAddr { .. } | Inst::LoadLogicalIndexedAddr { .. } => {
244+
InstructionSet::MIE4
245+
}
246+
243247
// These depend on the opcode
244248
Inst::AluRRR { alu_op, .. } => match alu_op {
245249
ALUOp::NotAnd32 | ALUOp::NotAnd64 => InstructionSet::MIE3,
@@ -1030,6 +1034,20 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
10301034
collector.reg_def(rd);
10311035
memarg_operands(mem, collector);
10321036
}
1037+
Inst::LoadIndexedAddr {
1038+
rd, base, index, ..
1039+
} => {
1040+
collector.reg_def(rd);
1041+
collector.reg_use(base);
1042+
collector.reg_use(index);
1043+
}
1044+
Inst::LoadLogicalIndexedAddr {
1045+
rd, base, index, ..
1046+
} => {
1047+
collector.reg_def(rd);
1048+
collector.reg_use(base);
1049+
collector.reg_use(index);
1050+
}
10331051
Inst::StackProbeLoop { probe_count, .. } => {
10341052
collector.reg_early_def(probe_count);
10351053
}
@@ -3507,6 +3525,56 @@ impl Inst {
35073525

35083526
format!("{mem_str}{op} {rd}, {mem}")
35093527
}
3528+
&Inst::LoadIndexedAddr {
3529+
rd,
3530+
base,
3531+
index,
3532+
offset,
3533+
size,
3534+
} => {
3535+
let rd = pretty_print_reg(rd.to_reg());
3536+
let op = match size {
3537+
1 => "lxah",
3538+
2 => "lxaf",
3539+
3 => "lxag",
3540+
4 => "lxaq",
3541+
_ => unreachable!(),
3542+
};
3543+
let flags = MemFlags::trusted();
3544+
let mem = MemArg::BXD20 {
3545+
base,
3546+
index,
3547+
disp: offset,
3548+
flags,
3549+
};
3550+
let mem = mem.pretty_print_default();
3551+
format!("{op} {rd}, {mem}")
3552+
}
3553+
&Inst::LoadLogicalIndexedAddr {
3554+
rd,
3555+
base,
3556+
index,
3557+
offset,
3558+
size,
3559+
} => {
3560+
let rd = pretty_print_reg(rd.to_reg());
3561+
let op = match size {
3562+
1 => "llxah",
3563+
2 => "llxaf",
3564+
3 => "llxag",
3565+
4 => "llxaq",
3566+
_ => unreachable!(),
3567+
};
3568+
let flags = MemFlags::trusted();
3569+
let mem = MemArg::BXD20 {
3570+
base,
3571+
index,
3572+
disp: offset,
3573+
flags,
3574+
};
3575+
let mem = mem.pretty_print_default();
3576+
format!("{op} {rd}, {mem}")
3577+
}
35103578
&Inst::StackProbeLoop {
35113579
probe_count,
35123580
guard_size,

cranelift/codegen/src/isa/s390x/lower.isle

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@
115115
(rule 1 (lower (has_type (vr128_ty ty) (iadd _ x y)))
116116
(vec_add ty x y))
117117

118+
(rule 16 (lower (has_type (mie4_enabled)
119+
(iadd $I64 (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)))
120+
(load_logical_indexed_addr x y z shift))
121+
122+
(rule 17 (lower (has_type (mie4_enabled)
123+
(iadd $I64 y (ishl $I64 (uextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))))
124+
(load_logical_indexed_addr y x z shift))
125+
126+
(rule 18 (lower (has_type (and (ty_addr64 _) (mie4_enabled))
127+
(iadd $I64 (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)) y)))
128+
(load_indexed_addr x y z shift))
129+
130+
(rule 19 (lower (has_type (and (ty_addr64 _) (mie4_enabled))
131+
(iadd $I64 y (ishl $I64 (sextend $I64 (iadd $I32 x (simm20_from_value z))) (u8_from_value shift)))))
132+
(load_indexed_addr y x z shift))
118133

119134
;;;; Rules for `uadd_sat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120135

cranelift/codegen/src/isa/s390x/lower/isle.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,12 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
547547
UImm16Shifted::maybe_from_u64(constant)
548548
}
549549

550+
#[inline]
551+
fn simm20_from_value(&mut self, val: Value) -> Option<SImm20> {
552+
let constant = self.u64_from_signed_value(val)? as i64;
553+
SImm20::maybe_from_i64(constant)
554+
}
555+
550556
#[inline]
551557
fn uimm32shifted_from_value(&mut self, val: Value) -> Option<UImm32Shifted> {
552558
let constant = self.u64_from_value(val)?;

cranelift/filetests/filetests/isa/s390x/arithmetic-arch15.clif

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,49 @@ block0(v0: i128):
327327
; vst %v4, 0(%r2)
328328
; br %r14
329329

330+
function %i64_i32_offset_mul_unsigned(i64, i32) -> i64 {
331+
block0(v0: i64, v1: i32):
332+
v2 = iconst.i8 4
333+
v3 = iconst.i32 8000
334+
v4 = iadd v1, v3
335+
v5 = uextend.i64 v4
336+
v6 = ishl v5, v2
337+
v7 = iadd v0, v6
338+
return v7
339+
}
340+
341+
; VCode:
342+
; block0:
343+
; llxaq %r2, 8000(%r3,%r2)
344+
; br %r14
345+
;
346+
; Disassembled:
347+
; block0: ; offset 0x0
348+
; .byte 0xe3, 0x23
349+
; swr %f4, %f0
350+
; .byte 0x01, 0x69
351+
; br %r14
352+
353+
function %uload8_i64_i64_offset_mul_signed(i64, i32) -> i64 {
354+
block0(v0: i64, v1: i32):
355+
v2 = iconst.i8 4
356+
v3 = iconst.i32 8000
357+
v4 = iadd v1, v3
358+
v5 = sextend.i64 v4
359+
v6 = ishl v5, v2
360+
v7 = iadd v0, v6
361+
return v7
362+
}
363+
364+
; VCode:
365+
; block0:
366+
; lxaq %r2, 8000(%r3,%r2)
367+
; br %r14
368+
;
369+
; Disassembled:
370+
; block0: ; offset 0x0
371+
; .byte 0xe3, 0x23
372+
; swr %f4, %f0
373+
; .byte 0x01, 0x68
374+
; br %r14
375+

0 commit comments

Comments
 (0)