Skip to content

Commit 5d764f7

Browse files
sse orpd implementation
assembler integration with isle format add clippy reason, reorder avx priority in isle bless tests for orpd create separate xmm module validate function rewrite sse condition add quote from manual for sse prefix format changes move Xmm bits under Reg
1 parent 4a430a6 commit 5d764f7

20 files changed

Lines changed: 551 additions & 68 deletions

File tree

cranelift/assembler-x64/meta/src/dsl/encoding.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,11 @@ impl Rex {
194194

195195
if self.opcodes.prefix.contains_66() {
196196
assert!(
197-
operands
198-
.iter()
199-
.all(|&op| matches!(op.location.kind(), OperandKind::Imm(_) | OperandKind::FixedReg(_))
200-
|| op.location.bits() == 16),
197+
operands.iter().all(|&op| matches!(
198+
op.location.kind(),
199+
OperandKind::Imm(_) | OperandKind::FixedReg(_)
200+
) || op.location.bits() == 16
201+
|| op.location.bits() == 128),
201202
"when we encode the 66 prefix, we expect all operands to be 16-bit wide"
202203
);
203204
}
@@ -366,12 +367,15 @@ impl From<[u8; 4]> for Opcodes {
366367
pub enum LegacyPrefix {
367368
/// No prefix bytes.
368369
NoPrefix,
369-
/// An operand size override typically denoting "16-bit operation". But the
370+
/// An operand size override typically denoting "16-bit operation" or "SSE instructions". But the
370371
/// reference manual is more nuanced:
371372
///
372373
/// > The operand-size override prefix allows a program to switch between
373374
/// > 16- and 32-bit operand sizes. Either size can be the default; use of
374375
/// > the prefix selects the non-default.
376+
/// > Some SSE2/SSE3/SSSE3/SSE4 instructions and instructions using a three-byte
377+
/// > sequence of primary opcode bytes may use 66H as a mandatory prefix to express
378+
/// > distinct functionality.
375379
_66,
376380
/// The lock prefix.
377381
_F0,

cranelift/assembler-x64/meta/src/dsl/format.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,13 @@ pub enum Location {
212212
r32,
213213
r64,
214214

215+
xmm,
216+
215217
rm8,
216218
rm16,
217219
rm32,
218220
rm64,
221+
rm128,
219222
}
220223

221224
impl Location {
@@ -228,6 +231,7 @@ impl Location {
228231
ax | imm16 | r16 | rm16 => 16,
229232
eax | imm32 | r32 | rm32 => 32,
230233
rax | r64 | rm64 => 64,
234+
xmm | rm128 => 128,
231235
}
232236
}
233237

@@ -242,8 +246,8 @@ impl Location {
242246
pub fn uses_memory(&self) -> bool {
243247
use Location::*;
244248
match self {
245-
al | cl | ax | eax | rax | imm8 | imm16 | imm32 | r8 | r16 | r32 | r64 => false,
246-
rm8 | rm16 | rm32 | rm64 => true,
249+
al | cl | ax | eax | rax | imm8 | imm16 | imm32 | r8 | r16 | r32 | r64 | xmm => false,
250+
rm8 | rm16 | rm32 | rm64 | rm128 => true,
247251
}
248252
}
249253

@@ -254,7 +258,7 @@ impl Location {
254258
use Location::*;
255259
match self {
256260
al | ax | eax | rax | cl | imm8 | imm16 | imm32 => false,
257-
r8 | r16 | r32 | r64 | rm8 | rm16 | rm32 | rm64 => true,
261+
r8 | r16 | r32 | r64 | xmm | rm8 | rm16 | rm32 | rm64 | rm128 => true,
258262
}
259263
}
260264

@@ -265,8 +269,8 @@ impl Location {
265269
match self {
266270
al | ax | eax | rax | cl => OperandKind::FixedReg(*self),
267271
imm8 | imm16 | imm32 => OperandKind::Imm(*self),
268-
r8 | r16 | r32 | r64 => OperandKind::Reg(*self),
269-
rm8 | rm16 | rm32 | rm64 => OperandKind::RegMem(*self),
272+
r8 | r16 | r32 | r64 | xmm => OperandKind::Reg(*self),
273+
rm8 | rm16 | rm32 | rm64 | rm128 => OperandKind::RegMem(*self),
270274
}
271275
}
272276
}
@@ -291,10 +295,13 @@ impl core::fmt::Display for Location {
291295
r32 => write!(f, "r32"),
292296
r64 => write!(f, "r64"),
293297

298+
xmm => write!(f, "xmm"),
299+
294300
rm8 => write!(f, "rm8"),
295301
rm16 => write!(f, "rm16"),
296302
rm32 => write!(f, "rm32"),
297303
rm64 => write!(f, "rm64"),
304+
rm128 => write!(f, "rm128"),
298305
}
299306
}
300307
}

cranelift/assembler-x64/meta/src/generate.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ pub fn isle_macro(f: &mut Formatter, insts: &[dsl::Inst]) {
4141
fmtln!(f, "() => {{");
4242
f.indent(|f| {
4343
for inst in insts {
44-
inst.generate_isle_macro(f, "Gpr", "PairedGpr");
44+
if inst.format.operands.iter().any(|op| op.location.bits() == 128) {
45+
inst.generate_isle_macro(f, "Xmm", "PairedXmm");
46+
} else {
47+
inst.generate_isle_macro(f, "Gpr", "PairedGpr");
48+
}
4549
}
4650
});
4751
fmtln!(f, "}};");
@@ -63,6 +67,10 @@ pub fn isle_definitions(f: &mut Formatter, insts: &[dsl::Inst]) {
6367
f.line("(type AssemblerReadGprMem extern (enum))", None);
6468
f.line("(type AssemblerReadWriteGprMem extern (enum))", None);
6569
f.line("(type AssemblerInst extern (enum))", None);
70+
f.line("(type AssemblerReadXmm extern (enum))", None);
71+
f.line("(type AssemblerReadWriteXmm extern (enum))", None);
72+
f.line("(type AssemblerReadXmmMem extern (enum))", None);
73+
f.line("(type AssemblerReadWriteXmmMem extern (enum))", None);
6674
f.empty_line();
6775
for inst in insts {
6876
inst.generate_isle_definition(f);

cranelift/assembler-x64/meta/src/generate/format.rs

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,16 @@ impl dsl::Format {
108108
fmtln!(f, "let {dst} = self.{dst}.enc();");
109109
fmtln!(f, "match &self.{src} {{");
110110
f.indent(|f| {
111-
fmtln!(f, "GprMem::Gpr({src}) => rex.emit_two_op(buf, {dst}, {src}.enc()),");
112-
fmtln!(f, "GprMem::Mem({src}) => {src}.emit_rex_prefix(rex, {dst}, buf),");
111+
match dst.bits() {
112+
128 => {
113+
fmtln!(f, "XmmMem::Xmm({src}) => rex.emit_two_op(buf, {dst}, {src}.enc()),");
114+
fmtln!(f, "XmmMem::Mem({src}) => {src}.emit_rex_prefix(rex, {dst}, buf),");
115+
}
116+
_ => {
117+
fmtln!(f, "GprMem::Gpr({src}) => rex.emit_two_op(buf, {dst}, {src}.enc()),");
118+
fmtln!(f, "GprMem::Mem({src}) => {src}.emit_rex_prefix(rex, {dst}, buf),");
119+
}
120+
};
113121
});
114122
fmtln!(f, "}}");
115123
}
@@ -118,9 +126,15 @@ impl dsl::Format {
118126
| [RegMem(dst), Reg(src), FixedReg(_)] => {
119127
fmtln!(f, "let {src} = self.{src}.enc();");
120128
fmtln!(f, "match &self.{dst} {{");
121-
f.indent(|f| {
122-
fmtln!(f, "GprMem::Gpr({dst}) => rex.emit_two_op(buf, {src}, {dst}.enc()),");
123-
fmtln!(f, "GprMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, {src}, buf),");
129+
f.indent(|f| match src.bits() {
130+
128 => {
131+
fmtln!(f, "XmmMem::Xmm({dst}) => rex.emit_two_op(buf, {src}, {dst}.enc()),");
132+
fmtln!(f, "XmmMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, {src}, buf),");
133+
}
134+
_ => {
135+
fmtln!(f, "GprMem::Gpr({dst}) => rex.emit_two_op(buf, {src}, {dst}.enc()),");
136+
fmtln!(f, "GprMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, {src}, buf),");
137+
}
124138
});
125139
fmtln!(f, "}}");
126140
}
@@ -159,8 +173,22 @@ impl dsl::Format {
159173
fmtln!(f, "let {dst} = self.{dst}.enc();");
160174
fmtln!(f, "match &self.{src} {{");
161175
f.indent(|f| {
162-
fmtln!(f, "GprMem::Gpr({src}) => emit_modrm(buf, {dst}, {src}.enc()),");
163-
fmtln!(f, "GprMem::Mem({src}) => emit_modrm_sib_disp(buf, off, {dst}, {src}, 0, None),");
176+
match dst.bits() {
177+
128 => {
178+
fmtln!(f, "XmmMem::Xmm({src}) => emit_modrm(buf, {dst}, {src}.enc()),");
179+
fmtln!(
180+
f,
181+
"XmmMem::Mem({src}) => emit_modrm_sib_disp(buf, off, {dst}, {src}, 0, None),"
182+
);
183+
}
184+
_ => {
185+
fmtln!(f, "GprMem::Gpr({src}) => emit_modrm(buf, {dst}, {src}.enc()),");
186+
fmtln!(
187+
f,
188+
"GprMem::Mem({src}) => emit_modrm_sib_disp(buf, off, {dst}, {src}, 0, None),"
189+
);
190+
}
191+
};
164192
});
165193
fmtln!(f, "}}");
166194
}
@@ -170,12 +198,25 @@ impl dsl::Format {
170198
fmtln!(f, "let {src} = self.{src}.enc();");
171199
fmtln!(f, "match &self.{dst} {{");
172200
f.indent(|f| {
173-
fmtln!(f, "GprMem::Gpr({dst}) => emit_modrm(buf, {src}, {dst}.enc()),");
174-
fmtln!(f, "GprMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, {src}, {dst}, 0, None),");
201+
match src.bits() {
202+
128 => {
203+
fmtln!(f, "XmmMem::Xmm({dst}) => emit_modrm(buf, {src}, {dst}.enc()),");
204+
fmtln!(
205+
f,
206+
"XmmMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, {src}, {dst}, 0, None),"
207+
);
208+
}
209+
_ => {
210+
fmtln!(f, "GprMem::Gpr({dst}) => emit_modrm(buf, {src}, {dst}.enc()),");
211+
fmtln!(
212+
f,
213+
"GprMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, {src}, {dst}, 0, None),"
214+
);
215+
}
216+
};
175217
});
176218
fmtln!(f, "}}");
177219
}
178-
179220
unknown => unimplemented!("unknown pattern: {unknown:?}"),
180221
}
181222
}

cranelift/assembler-x64/meta/src/generate/inst.rs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,14 @@ impl dsl::Inst {
106106
if let Some(op) = self.format.uses_memory() {
107107
f.empty_line();
108108
f.comment("Emit trap.");
109-
fmtln!(f, "if let GprMem::Mem({op}) = &self.{op} {{");
109+
match op {
110+
crate::dsl::Location::rm128 => {
111+
fmtln!(f, "if let XmmMem::Mem({op}) = &self.{op} {{");
112+
}
113+
_ => {
114+
fmtln!(f, "if let GprMem::Mem({op}) = &self.{op} {{");
115+
}
116+
}
110117
f.indent(|f| {
111118
fmtln!(f, "if let Some(trap_code) = {op}.trap_code() {{");
112119
f.indent(|f| {
@@ -150,19 +157,42 @@ impl dsl::Inst {
150157
fmtln!(f, "visitor.fixed_{call}(&R::{ty}Gpr::new({fixed}));");
151158
}
152159
Reg(reg) => {
153-
let call = o.mutability.generate_regalloc_call();
154-
fmtln!(f, "visitor.{call}(self.{reg}.as_mut());");
160+
match reg.bits() {
161+
128 => {
162+
let call = o.mutability.generate_xmm_regalloc_call();
163+
fmtln!(f, "visitor.{call}(self.{reg}.as_mut());");
164+
}
165+
_ => {
166+
let call = o.mutability.generate_regalloc_call();
167+
fmtln!(f, "visitor.{call}(self.{reg}.as_mut());");
168+
}
169+
};
155170
}
156171
RegMem(rm) => {
157-
let call = o.mutability.generate_regalloc_call();
158-
fmtln!(f, "match &mut self.{rm} {{");
159-
f.indent(|f| {
160-
fmtln!(f, "GprMem::Gpr(r) => visitor.{call}(r),");
161-
fmtln!(
162-
f,
163-
"GprMem::Mem(m) => m.registers_mut().iter_mut().for_each(|r| visitor.read(r)),"
164-
);
165-
});
172+
match rm.bits() {
173+
128 => {
174+
let call = o.mutability.generate_xmm_regalloc_call();
175+
fmtln!(f, "match &mut self.{rm} {{");
176+
f.indent(|f| {
177+
fmtln!(f, "XmmMem::Xmm(r) => visitor.{call}(r),");
178+
fmtln!(
179+
f,
180+
"XmmMem::Mem(m) => m.registers_mut().iter_mut().for_each(|r| visitor.read(r)),"
181+
);
182+
});
183+
}
184+
_ => {
185+
let call = o.mutability.generate_regalloc_call();
186+
fmtln!(f, "match &mut self.{rm} {{");
187+
f.indent(|f| {
188+
fmtln!(f, "GprMem::Gpr(r) => visitor.{call}(r),");
189+
fmtln!(
190+
f,
191+
"GprMem::Mem(m) => m.registers_mut().iter_mut().for_each(|r| visitor.read(r)),"
192+
);
193+
});
194+
}
195+
};
166196
fmtln!(f, "}}");
167197
}
168198
}
@@ -239,8 +269,15 @@ impl dsl::Inst {
239269
.collect::<Vec<_>>();
240270
let ret_ty = match self.format.operands.first().unwrap().location.kind() {
241271
Imm(_) => unreachable!(),
242-
Reg(_) | FixedReg(_) => format!("cranelift_assembler_x64::Gpr<{read_write_ty}>"),
243-
RegMem(_) => format!("cranelift_assembler_x64::GprMem<{read_write_ty}, {read_ty}>"),
272+
FixedReg(_) => format!("cranelift_assembler_x64::Gpr<{read_write_ty}>"),
273+
Reg(r) => match r.bits() {
274+
128 => format!("cranelift_assembler_x64::Xmm<{read_write_ty}>"),
275+
_ => format!("cranelift_assembler_x64::Gpr<{read_write_ty}>"),
276+
},
277+
RegMem(rm) => match rm.bits() {
278+
128 => format!("cranelift_assembler_x64::XmmMem<{read_write_ty}, {read_ty}>"),
279+
_ => format!("cranelift_assembler_x64::GprMem<{read_write_ty}, {read_ty}>"),
280+
},
244281
};
245282
let ret_val = match self.format.operands.first().unwrap().location.kind() {
246283
Imm(_) => unreachable!(),
@@ -289,15 +326,28 @@ impl dsl::Inst {
289326
Some(format!("AssemblerImm{bits}"))
290327
}
291328
}
292-
Reg(_) => Some(format!("Assembler{}Gpr", o.mutability.generate_type())),
293-
RegMem(_) => Some(format!("Assembler{}GprMem", o.mutability.generate_type())),
329+
Reg(r) => match r.bits() {
330+
128 => Some(format!("Assembler{}Xmm", o.mutability.generate_type())),
331+
_ => Some(format!("Assembler{}Gpr", o.mutability.generate_type())),
332+
},
333+
RegMem(rm) => match rm.bits() {
334+
128 => Some(format!("Assembler{}XmmMem", o.mutability.generate_type())),
335+
_ => Some(format!("Assembler{}GprMem", o.mutability.generate_type())),
336+
},
294337
})
295338
.collect::<Vec<_>>()
296339
.join(" ");
297340
let ret = match self.format.operands.first().unwrap().location.kind() {
298341
Imm(_) => unreachable!(),
299-
FixedReg(_) | Reg(_) => "AssemblerReadWriteGpr",
300-
RegMem(_) => "AssemblerReadWriteGprMem",
342+
FixedReg(_) => "AssemblerReadWriteGpr",
343+
Reg(r) => match r.bits() {
344+
128 => "AssemblerReadWriteXmm",
345+
_ => "AssemblerReadWriteGpr",
346+
},
347+
RegMem(rm) => match rm.bits() {
348+
128 => "AssemblerReadWriteXmmMem",
349+
_ => "AssemblerReadWriteGprMem",
350+
},
301351
};
302352

303353
f.line(format!("(decl {rule_name} ({params}) {ret})"), None);

0 commit comments

Comments
 (0)