1use wasmer_compiler::CallingConvention;
3use wasmer_types::Type;
4
5#[repr(u8)]
7#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
8pub(crate) enum GPR {
9 RAX,
11 RCX,
13 RDX,
15 RBX,
17 RSP,
19 RBP,
21 RSI,
23 RDI,
25 R8,
27 R9,
29 R10,
31 R11,
33 R12,
35 R13,
37 R14,
39 R15,
41}
42
43#[repr(u8)]
45#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
46#[allow(dead_code)]
47pub(crate) enum XMM {
48 XMM0,
50 XMM1,
52 XMM2,
54 XMM3,
56 XMM4,
58 XMM5,
60 XMM6,
62 XMM7,
64 XMM8,
66 XMM9,
68 XMM10,
70 XMM11,
72 XMM12,
74 XMM13,
76 XMM14,
78 XMM15,
80}
81
82#[derive(Copy, Clone, Debug, Eq, PartialEq)]
84pub(crate) enum X64Register {
85 GPR(GPR),
87 XMM(XMM),
89}
90
91impl X64Register {
92 pub(crate) fn _from_dwarf_regnum(x: u16) -> Option<X64Register> {
94 Some(match x {
95 0 => X64Register::GPR(GPR::RAX),
96 1 => X64Register::GPR(GPR::RDX),
97 2 => X64Register::GPR(GPR::RCX),
98 3 => X64Register::GPR(GPR::RBX),
99 4 => X64Register::GPR(GPR::RSI),
100 5 => X64Register::GPR(GPR::RDI),
101 6 => X64Register::GPR(GPR::RBP),
102 7 => X64Register::GPR(GPR::RSP),
103 8 => X64Register::GPR(GPR::R8),
104 9 => X64Register::GPR(GPR::R9),
105 10 => X64Register::GPR(GPR::R10),
106 11 => X64Register::GPR(GPR::R11),
107 12 => X64Register::GPR(GPR::R12),
108 13 => X64Register::GPR(GPR::R13),
109 14 => X64Register::GPR(GPR::R14),
110 15 => X64Register::GPR(GPR::R15),
111
112 17 => X64Register::XMM(XMM::XMM0),
113 18 => X64Register::XMM(XMM::XMM1),
114 19 => X64Register::XMM(XMM::XMM2),
115 20 => X64Register::XMM(XMM::XMM3),
116 21 => X64Register::XMM(XMM::XMM4),
117 22 => X64Register::XMM(XMM::XMM5),
118 23 => X64Register::XMM(XMM::XMM6),
119 24 => X64Register::XMM(XMM::XMM7),
120 _ => return None,
121 })
122 }
123
124 pub(crate) fn _prefix_mov_to_stack(&self) -> Option<&'static [u8]> {
129 Some(match *self {
130 X64Register::GPR(gpr) => match gpr {
131 GPR::RDI => &[0x48, 0x89, 0xbc, 0x24],
132 GPR::RSI => &[0x48, 0x89, 0xb4, 0x24],
133 GPR::RDX => &[0x48, 0x89, 0x94, 0x24],
134 GPR::RCX => &[0x48, 0x89, 0x8c, 0x24],
135 GPR::R8 => &[0x4c, 0x89, 0x84, 0x24],
136 GPR::R9 => &[0x4c, 0x89, 0x8c, 0x24],
137 _ => return None,
138 },
139 X64Register::XMM(xmm) => match xmm {
140 XMM::XMM0 => &[0x66, 0x0f, 0xd6, 0x84, 0x24],
141 XMM::XMM1 => &[0x66, 0x0f, 0xd6, 0x8c, 0x24],
142 XMM::XMM2 => &[0x66, 0x0f, 0xd6, 0x94, 0x24],
143 XMM::XMM3 => &[0x66, 0x0f, 0xd6, 0x9c, 0x24],
144 XMM::XMM4 => &[0x66, 0x0f, 0xd6, 0xa4, 0x24],
145 XMM::XMM5 => &[0x66, 0x0f, 0xd6, 0xac, 0x24],
146 XMM::XMM6 => &[0x66, 0x0f, 0xd6, 0xb4, 0x24],
147 XMM::XMM7 => &[0x66, 0x0f, 0xd6, 0xbc, 0x24],
148 _ => return None,
149 },
150 })
151 }
152}
153
154#[derive(Default)]
156pub(crate) struct ArgumentRegisterAllocator {
157 n_gprs: usize,
158 n_xmms: usize,
159}
160
161impl ArgumentRegisterAllocator {
162 pub(crate) fn next(
164 &mut self,
165 ty: Type,
166 calling_convention: CallingConvention,
167 ) -> Option<X64Register> {
168 match calling_convention {
169 CallingConvention::WindowsFastcall => {
170 static GPR_SEQ: &'static [GPR] = &[GPR::RCX, GPR::RDX, GPR::R8, GPR::R9];
171 static XMM_SEQ: &'static [XMM] = &[XMM::XMM0, XMM::XMM1, XMM::XMM2, XMM::XMM3];
172 let idx = self.n_gprs + self.n_xmms;
173 match ty {
174 Type::I32 | Type::I64 => {
175 if idx < 4 {
176 let gpr = GPR_SEQ[idx];
177 self.n_gprs += 1;
178 Some(X64Register::GPR(gpr))
179 } else {
180 None
181 }
182 }
183 Type::F32 | Type::F64 => {
184 if idx < 4 {
185 let xmm = XMM_SEQ[idx];
186 self.n_xmms += 1;
187 Some(X64Register::XMM(xmm))
188 } else {
189 None
190 }
191 }
192 _ => todo!(
193 "ArgumentRegisterAllocator::next: Unsupported type: {:?}",
194 ty
195 ),
196 }
197 }
198 _ => {
199 static GPR_SEQ: &'static [GPR] =
200 &[GPR::RDI, GPR::RSI, GPR::RDX, GPR::RCX, GPR::R8, GPR::R9];
201 static XMM_SEQ: &'static [XMM] = &[
202 XMM::XMM0,
203 XMM::XMM1,
204 XMM::XMM2,
205 XMM::XMM3,
206 XMM::XMM4,
207 XMM::XMM5,
208 XMM::XMM6,
209 XMM::XMM7,
210 ];
211 match ty {
212 Type::I32 | Type::I64 => {
213 if self.n_gprs < GPR_SEQ.len() {
214 let gpr = GPR_SEQ[self.n_gprs];
215 self.n_gprs += 1;
216 Some(X64Register::GPR(gpr))
217 } else {
218 None
219 }
220 }
221 Type::F32 | Type::F64 => {
222 if self.n_xmms < XMM_SEQ.len() {
223 let xmm = XMM_SEQ[self.n_xmms];
224 self.n_xmms += 1;
225 Some(X64Register::XMM(xmm))
226 } else {
227 None
228 }
229 }
230 _ => todo!(
231 "ArgumentRegisterAllocator::next: Unsupported type: {:?}",
232 ty
233 ),
234 }
235 }
236 }
237 }
238}