Skip to content

Commit dc78458

Browse files
committed
asm: add mul* instructions, vector and scalar
1 parent 18d875d commit dc78458

File tree

5 files changed

+75
-14
lines changed

5 files changed

+75
-14
lines changed

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ pub enum Location {
279279
ax,
280280
eax,
281281
rax,
282+
dx,
283+
edx,
284+
rdx,
282285
cl,
283286

284287
// Immediate values.
@@ -316,9 +319,9 @@ impl Location {
316319
use Location::*;
317320
match self {
318321
al | cl | imm8 | r8 | rm8 | m8 => 8,
319-
ax | imm16 | r16 | rm16 | m16 => 16,
320-
eax | imm32 | r32 | rm32 | m32 | xmm_m32 => 32,
321-
rax | r64 | rm64 | m64 | xmm_m64 => 64,
322+
ax | dx | imm16 | r16 | rm16 | m16 => 16,
323+
eax | edx | imm32 | r32 | rm32 | m32 | xmm_m32 => 32,
324+
rax | rdx | r64 | rm64 | m64 | xmm_m64 => 64,
322325
xmm | xmm_m128 => 128,
323326
}
324327
}
@@ -334,7 +337,8 @@ impl Location {
334337
pub fn uses_memory(&self) -> bool {
335338
use Location::*;
336339
match self {
337-
al | cl | ax | eax | rax | imm8 | imm16 | imm32 | r8 | r16 | r32 | r64 | xmm => false,
340+
al | ax | eax | rax | cl | dx | edx | rdx | imm8 | imm16 | imm32 | r8 | r16 | r32
341+
| r64 | xmm => false,
338342
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64 => true,
339343
}
340344
}
@@ -346,8 +350,8 @@ impl Location {
346350
use Location::*;
347351
match self {
348352
imm8 | imm16 | imm32 => false,
349-
al | ax | eax | rax | cl | r8 | r16 | r32 | r64 | rm8 | rm16 | rm32 | rm64 | xmm
350-
| xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64 => true,
353+
al | ax | eax | rax | cl | dx | edx | rdx | r8 | r16 | r32 | r64 | rm8 | rm16
354+
| rm32 | rm64 | xmm | xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64 => true,
351355
}
352356
}
353357

@@ -356,7 +360,7 @@ impl Location {
356360
pub fn kind(&self) -> OperandKind {
357361
use Location::*;
358362
match self {
359-
al | ax | eax | rax | cl => OperandKind::FixedReg(*self),
363+
al | ax | eax | rax | cl | dx | edx | rdx => OperandKind::FixedReg(*self),
360364
imm8 | imm16 | imm32 => OperandKind::Imm(*self),
361365
r8 | r16 | r32 | r64 | xmm => OperandKind::Reg(*self),
362366
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 => OperandKind::RegMem(*self),
@@ -373,9 +377,8 @@ impl Location {
373377
use Location::*;
374378
match self {
375379
imm8 | imm16 | imm32 | m8 | m16 | m32 | m64 => None,
376-
al | ax | eax | rax | cl | r8 | r16 | r32 | r64 | rm8 | rm16 | rm32 | rm64 => {
377-
Some(RegClass::Gpr)
378-
}
380+
al | ax | eax | rax | cl | dx | edx | rdx | r8 | r16 | r32 | r64 | rm8 | rm16
381+
| rm32 | rm64 => Some(RegClass::Gpr),
379382
xmm | xmm_m32 | xmm_m64 | xmm_m128 => Some(RegClass::Xmm),
380383
}
381384
}
@@ -394,6 +397,9 @@ impl core::fmt::Display for Location {
394397
eax => write!(f, "eax"),
395398
rax => write!(f, "rax"),
396399
cl => write!(f, "cl"),
400+
dx => write!(f, "dx"),
401+
edx => write!(f, "edx"),
402+
rdx => write!(f, "rdx"),
397403

398404
r8 => write!(f, "r8"),
399405
r16 => write!(f, "r16"),

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,17 @@ impl dsl::Format {
9292
fmtln!(f, "let dst = self.{dst}.enc();");
9393
fmtln!(f, "let rex = RexPrefix::two_op(digit, dst, {bits});");
9494
}
95+
[FixedReg(_), RegMem(mem)] | [FixedReg(_), FixedReg(_), RegMem(mem)] => {
96+
let digit = rex.digit.unwrap();
97+
fmtln!(f, "let digit = 0x{digit:x};");
98+
fmtln!(f, "let rex = self.{mem}.as_rex_prefix(digit, {bits});");
99+
}
95100
[Mem(dst), Imm(_)] | [RegMem(dst), Imm(_)] | [RegMem(dst)] => {
96101
let digit = rex.digit.unwrap();
97102
fmtln!(f, "let digit = 0x{digit:x};");
98103
fmtln!(f, "let rex = self.{dst}.as_rex_prefix(digit, {bits});");
99104
}
100-
[Reg(dst), RegMem(src)] => {
105+
[Reg(dst), RegMem(src)] | [Reg(dst), RegMem(src), Imm(_)] => {
101106
fmtln!(f, "let dst = self.{dst}.enc();");
102107
fmtln!(f, "let rex = self.{src}.as_rex_prefix(dst, {bits});");
103108
}
@@ -136,12 +141,17 @@ impl dsl::Format {
136141
fmtln!(f, "let digit = 0x{digit:x};");
137142
fmtln!(f, "self.{reg}.encode_modrm(buf, digit);");
138143
}
139-
[Mem(mem), Imm(_)] | [RegMem(mem), Imm(_)] | [RegMem(mem)] => {
144+
[Mem(mem), Imm(_)]
145+
| [RegMem(mem), Imm(_)]
146+
| [RegMem(mem)]
147+
| [FixedReg(_), RegMem(mem)]
148+
| [FixedReg(_), FixedReg(_), RegMem(mem)] => {
140149
let digit = rex.digit.unwrap();
141150
fmtln!(f, "let digit = 0x{digit:x};");
142151
fmtln!(f, "self.{mem}.encode_rex_suffixes(buf, off, digit, 0);");
143152
}
144153
[Reg(reg), RegMem(mem)]
154+
| [Reg(reg), RegMem(mem), Imm(_)]
145155
| [Mem(mem), Reg(reg)]
146156
| [RegMem(mem), Reg(reg)]
147157
| [RegMem(mem), Reg(reg), Imm(_)]

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ impl dsl::Operand {
1414
format!("Imm{bits}")
1515
}
1616
}
17-
al | ax | eax | rax | cl => {
17+
al | ax | eax | rax | cl | dx | edx | rdx => {
1818
let enc = match self.location {
1919
al | ax | eax | rax => "{ gpr::enc::RAX }",
2020
cl => "{ gpr::enc::RCX }",
21+
dx | edx | rdx => "{ gpr::enc::RDX }",
2122
_ => unreachable!(),
2223
};
2324
format!("Fixed<R::{mut_}Gpr, {enc}>")
@@ -44,6 +45,9 @@ impl dsl::Location {
4445
eax => "\"%eax\"".into(),
4546
rax => "\"%rax\"".into(),
4647
cl => "\"%cl\"".into(),
48+
dx => "\"%dx\"".into(),
49+
edx => "\"%edx\"".into(),
50+
rdx => "\"%rdx\"".into(),
4751
imm8 | imm16 | imm32 => {
4852
if extension.is_sign_extended() {
4953
let variant = extension.generate_variant();
@@ -67,7 +71,7 @@ impl dsl::Location {
6771
fn generate_size(&self) -> Option<&str> {
6872
use dsl::Location::*;
6973
match self {
70-
al | ax | eax | rax | cl | imm8 | imm16 | imm32 => None,
74+
al | ax | eax | rax | cl | dx | edx | rdx | imm8 | imm16 | imm32 => None,
7175
r8 | rm8 => Some("Size::Byte"),
7276
r16 | rm16 => Some("Size::Word"),
7377
r32 | rm32 => Some("Size::Doubleword"),

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
mod add;
44
mod and;
5+
mod mul;
56
mod neg;
67
mod or;
78
mod shift;
@@ -15,6 +16,7 @@ pub fn list() -> Vec<Inst> {
1516
let mut all = vec![];
1617
all.extend(add::list());
1718
all.extend(and::list());
19+
all.extend(mul::list());
1820
all.extend(neg::list());
1921
all.extend(or::list());
2022
all.extend(shift::list());
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use crate::dsl::{align, fmt, implicit, inst, r, rex, rw, sxl, sxq, sxw, w};
2+
use crate::dsl::{Feature::*, Inst, Location::*};
3+
4+
#[rustfmt::skip] // Keeps instructions on a single line.
5+
pub fn list() -> Vec<Inst> {
6+
vec![
7+
// Multiply unsigned; low bits in `rax`, high bits in `rdx`.
8+
inst("mulb", fmt("M", [rw(implicit(ax)), r(rm8)]), rex(0xF6).digit(4), _64b | compat),
9+
inst("mulw", fmt("M", [rw(implicit(ax)), w(implicit(dx)), r(rm16)]), rex([0x66, 0xF7]).digit(4), _64b | compat),
10+
inst("mull", fmt("M", [rw(implicit(eax)), w(implicit(edx)), r(rm32)]), rex(0xF7).digit(4), _64b | compat),
11+
inst("mulq", fmt("M", [rw(implicit(rax)), w(implicit(rdx)), r(rm64)]), rex(0xF7).w().digit(4), _64b),
12+
// Multiply signed; low bits in `rax`, high bits in `rdx`.
13+
inst("imulb", fmt("M", [rw(implicit(ax)), r(rm8)]), rex(0xF6).digit(5), _64b | compat),
14+
inst("imulw", fmt("M", [rw(implicit(ax)), w(implicit(dx)), r(rm16)]), rex([0x66, 0xF7]).digit(5), _64b | compat),
15+
inst("imull", fmt("M", [rw(implicit(eax)), w(implicit(edx)), r(rm32)]), rex(0xF7).digit(5), _64b | compat),
16+
inst("imulq", fmt("M", [rw(implicit(rax)), w(implicit(rdx)), r(rm64)]), rex(0xF7).w().digit(5), _64b),
17+
inst("imulw", fmt("RM", [rw(r16), r(rm16)]), rex([0x66, 0x0F, 0xAF]), _64b | compat),
18+
inst("imull", fmt("RM", [rw(r32), r(rm32)]), rex([0x0F, 0xAF]), _64b | compat),
19+
inst("imulq", fmt("RM", [rw(r64), r(rm64)]), rex([0x0F, 0xAF]).w(), _64b),
20+
inst("imulw", fmt("RMI_SXB", [w(r16), r(rm16), sxw(imm8)]), rex([0x66, 0x6B]).ib(), _64b | compat),
21+
inst("imull", fmt("RMI_SXB", [w(r32), r(rm32), sxl(imm8)]), rex(0x6B).ib(), _64b | compat),
22+
inst("imulq", fmt("RMI_SXB", [w(r64), r(rm64), sxq(imm8)]), rex(0x6B).w().ib(), _64b),
23+
inst("imulw", fmt("RMI", [w(r16), r(rm16), r(imm16)]), rex([0x66, 0x69]).iw(), _64b | compat),
24+
inst("imull", fmt("RMI", [w(r32), r(rm32), r(imm32)]), rex(0x69).id(), _64b | compat),
25+
inst("imulq", fmt("RMI_SXL", [w(r64), r(rm64), sxq(imm32)]), rex(0x69).w().id(), _64b),
26+
// Vector instructions.
27+
inst("mulss", fmt("A", [rw(xmm), r(xmm_m32)]), rex([0xF3, 0x0F, 0x59]).r(), _64b | compat | sse),
28+
inst("mulsd", fmt("A", [rw(xmm), r(xmm_m64)]), rex([0xF2, 0x0F, 0x59]).r(), _64b | compat | sse2),
29+
inst("mulps", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x0F, 0x59]).r(), _64b | compat | sse),
30+
inst("mulpd", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0x59]).r(), _64b | compat | sse2),
31+
inst("pmuldq", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0x38, 0x28]).r(), _64b | compat | sse41),
32+
inst("pmulhrsw", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0x38, 0x0B]).r(), _64b | compat | ssse3),
33+
inst("pmulhuw", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0xE4]).r(), _64b | compat | sse2),
34+
inst("pmulhw", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0xE5]).r(), _64b | compat | sse2),
35+
inst("pmulld", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0x38, 0x40]).r(), _64b | compat | sse41),
36+
inst("pmullw", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0xD5]).r(), _64b | compat | sse2),
37+
inst("pmuludq", fmt("A", [rw(xmm), r(align(xmm_m128))]), rex([0x66, 0x0F, 0xF4]).r(), _64b | compat | sse2),
38+
]
39+
}

0 commit comments

Comments
 (0)