cranelift_codegen/isa/s390x/inst/
args.rs
1use crate::ir::condcodes::{FloatCC, IntCC};
4use crate::ir::MemFlags;
5use crate::isa::s390x::inst::*;
6
7#[derive(Clone, Debug)]
12pub enum MemArg {
13 BXD12 {
18 base: Reg,
19 index: Reg,
20 disp: UImm12,
21 flags: MemFlags,
22 },
23
24 BXD20 {
26 base: Reg,
27 index: Reg,
28 disp: SImm20,
29 flags: MemFlags,
30 },
31
32 Label { target: MachLabel },
34
35 Symbol {
37 name: Box<ExternalName>,
38 offset: i32,
39 flags: MemFlags,
40 },
41
42 RegOffset { reg: Reg, off: i64, flags: MemFlags },
48
49 InitialSPOffset { off: i64 },
51
52 NominalSPOffset { off: i64 },
54
55 SlotOffset { off: i64 },
66}
67
68impl MemArg {
69 pub fn reg(reg: Reg, flags: MemFlags) -> MemArg {
71 MemArg::BXD12 {
72 base: reg,
73 index: zero_reg(),
74 disp: UImm12::zero(),
75 flags,
76 }
77 }
78
79 pub fn reg_plus_reg(reg1: Reg, reg2: Reg, flags: MemFlags) -> MemArg {
81 MemArg::BXD12 {
82 base: reg1,
83 index: reg2,
84 disp: UImm12::zero(),
85 flags,
86 }
87 }
88
89 pub fn reg_plus_off(reg: Reg, off: i64, flags: MemFlags) -> MemArg {
91 MemArg::RegOffset { reg, off, flags }
92 }
93
94 pub fn offset(base: &MemArg, offset: i64) -> MemArg {
96 match base {
97 &MemArg::RegOffset { reg, off, flags } => MemArg::RegOffset {
98 reg,
99 off: off + offset,
100 flags,
101 },
102 &MemArg::InitialSPOffset { off } => MemArg::InitialSPOffset { off: off + offset },
103 &MemArg::NominalSPOffset { off } => MemArg::NominalSPOffset { off: off + offset },
104 &MemArg::SlotOffset { off } => MemArg::SlotOffset { off: off + offset },
105 &MemArg::BXD12 { .. }
107 | &MemArg::BXD20 { .. }
108 | &MemArg::Label { .. }
109 | &MemArg::Symbol { .. } => unreachable!(),
110 }
111 }
112
113 pub(crate) fn get_flags(&self) -> MemFlags {
114 match self {
115 MemArg::BXD12 { flags, .. } => *flags,
116 MemArg::BXD20 { flags, .. } => *flags,
117 MemArg::RegOffset { flags, .. } => *flags,
118 MemArg::Label { .. } => MemFlags::trusted(),
119 MemArg::Symbol { flags, .. } => *flags,
120 MemArg::InitialSPOffset { .. } => MemFlags::trusted(),
121 MemArg::NominalSPOffset { .. } => MemFlags::trusted(),
122 MemArg::SlotOffset { .. } => MemFlags::trusted(),
123 }
124 }
125}
126
127#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub struct Cond {
134 mask: u8,
135}
136
137impl Cond {
138 pub fn from_mask(mask: u8) -> Cond {
139 assert!(mask >= 1 && mask <= 14);
140 Cond { mask }
141 }
142
143 pub fn from_intcc(cc: IntCC) -> Cond {
144 let mask = match cc {
145 IntCC::Equal => 8,
146 IntCC::NotEqual => 4 | 2,
147 IntCC::SignedGreaterThanOrEqual => 8 | 2,
148 IntCC::SignedGreaterThan => 2,
149 IntCC::SignedLessThanOrEqual => 8 | 4,
150 IntCC::SignedLessThan => 4,
151 IntCC::UnsignedGreaterThanOrEqual => 8 | 2,
152 IntCC::UnsignedGreaterThan => 2,
153 IntCC::UnsignedLessThanOrEqual => 8 | 4,
154 IntCC::UnsignedLessThan => 4,
155 };
156 Cond { mask }
157 }
158
159 pub fn from_floatcc(cc: FloatCC) -> Cond {
160 let mask = match cc {
161 FloatCC::Ordered => 8 | 4 | 2,
162 FloatCC::Unordered => 1,
163 FloatCC::Equal => 8,
164 FloatCC::NotEqual => 4 | 2 | 1,
165 FloatCC::OrderedNotEqual => 4 | 2,
166 FloatCC::UnorderedOrEqual => 8 | 1,
167 FloatCC::LessThan => 4,
168 FloatCC::LessThanOrEqual => 8 | 4,
169 FloatCC::GreaterThan => 2,
170 FloatCC::GreaterThanOrEqual => 8 | 2,
171 FloatCC::UnorderedOrLessThan => 4 | 1,
172 FloatCC::UnorderedOrLessThanOrEqual => 8 | 4 | 1,
173 FloatCC::UnorderedOrGreaterThan => 2 | 1,
174 FloatCC::UnorderedOrGreaterThanOrEqual => 8 | 2 | 1,
175 };
176 Cond { mask }
177 }
178
179 pub fn invert(self) -> Cond {
181 Cond {
182 mask: !self.mask & 15,
183 }
184 }
185
186 pub fn bits(self) -> u8 {
188 self.mask
189 }
190}
191
192impl PrettyPrint for MemArg {
193 fn pretty_print(&self, _: u8) -> String {
194 match self {
195 &MemArg::BXD12 {
196 base, index, disp, ..
197 } => {
198 if base != zero_reg() {
199 if index != zero_reg() {
200 format!(
201 "{}({},{})",
202 disp.pretty_print_default(),
203 show_reg(index),
204 show_reg(base),
205 )
206 } else {
207 format!("{}({})", disp.pretty_print_default(), show_reg(base))
208 }
209 } else {
210 if index != zero_reg() {
211 format!("{}({},)", disp.pretty_print_default(), show_reg(index))
212 } else {
213 format!("{}", disp.pretty_print_default())
214 }
215 }
216 }
217 &MemArg::BXD20 {
218 base, index, disp, ..
219 } => {
220 if base != zero_reg() {
221 if index != zero_reg() {
222 format!(
223 "{}({},{})",
224 disp.pretty_print_default(),
225 show_reg(index),
226 show_reg(base),
227 )
228 } else {
229 format!("{}({})", disp.pretty_print_default(), show_reg(base))
230 }
231 } else {
232 if index != zero_reg() {
233 format!("{}({},)", disp.pretty_print_default(), show_reg(index))
234 } else {
235 format!("{}", disp.pretty_print_default())
236 }
237 }
238 }
239 &MemArg::Label { target } => target.to_string(),
240 &MemArg::Symbol {
241 ref name, offset, ..
242 } => format!("{} + {}", name.display(None), offset),
243 &MemArg::InitialSPOffset { .. }
245 | &MemArg::NominalSPOffset { .. }
246 | &MemArg::SlotOffset { .. }
247 | &MemArg::RegOffset { .. } => {
248 panic!("Unexpected pseudo mem-arg mode (stack-offset or generic reg-offset)!")
249 }
250 }
251 }
252}
253
254impl PrettyPrint for Cond {
255 fn pretty_print(&self, _: u8) -> String {
256 let s = match self.mask {
257 1 => "o",
258 2 => "h",
259 3 => "nle",
260 4 => "l",
261 5 => "nhe",
262 6 => "lh",
263 7 => "ne",
264 8 => "e",
265 9 => "nlh",
266 10 => "he",
267 11 => "nl",
268 12 => "le",
269 13 => "nh",
270 14 => "no",
271 _ => unreachable!(),
272 };
273 s.to_string()
274 }
275}