1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
"""Defining instruction set architectures."""
# The typing module is only required by mypy, and we don't use these imports
# outside type comments.
# noqa
# noqa
# noqa
# noqa
# noqa
# noqa
=
=
# Instruction specification for encodings. Allows for predicated
# instructions.
=
=
# A recipe predicate consisting of an ISA predicate and an instruction
# predicate.
=
pass
"""
A target instruction set architecture.
The `TargetISA` class collects everything known about a target ISA.
:param name: Short mnemonic name for the ISA.
:param instruction_groups: List of `InstructionGroup` instances that are
relevant for this ISA.
"""
# type: (str, Sequence[InstructionGroup]) -> None
=
= None # type: SettingGroup
=
= # type: List[CPUMode]
= # type: List[RegBank]
= # type: OrderedDict[XFormGroup, int] # noqa
# Unique copies of all predicates.
= # type: Dict[PredKey, PredNode]
assert is None,\
\
# type: () -> str
return
# type: () -> TargetISA
"""
Finish the definition of a target ISA after adding all CPU modes and
settings.
This computes some derived properties that are used in multiple
places.
:returns self:
"""
return
# type: () -> None
"""
Collect and number all encoding recipes in use.
"""
= # type: List[EncRecipe]
= # type: Set[EncRecipe]
=
assert is None
=
# Make sure ISA predicates are registered.
=
=
# type: () -> None
"""
Collect and number all predicates in use.
Ensures that all ISA predicates have an assigned bit number in
`self.settings`.
"""
= # type: OrderedDict[PredNode, int]
=
# assign predicate number starting from 0.
=
=
# All referenced ISA predicates must have a number in
# `self.settings`. This may cause some parent predicates to be
# replicated here, which is OK.
# type: () -> None
"""
Make sure all legalization transforms have been assigned a code.
"""
# type: (XFormGroup) -> int
"""
Get the legalization code for the transform group `xgrp`. Assign one if
necessary.
Each target ISA has its own list of legalization actions with
associated legalize codes that appear in the encoding tables.
This method is used to maintain the registry of legalization actions
and their table codes.
"""
=
=
=
return
# type: (PredNode) -> PredNode
"""
Get a unique predicate that is equivalent to `pred`.
"""
return
# TODO: We could actually perform some algebraic simplifications. It's
# not clear if it is worthwhile.
=
return
=
return
"""
A CPU mode determines which instruction encodings are active.
All instruction encodings are associated with exactly one `CPUMode`, and
all CPU modes are associated with exactly one `TargetISA`.
:param name: Short mnemonic name for the CPU mode.
:param target: Associated `TargetISA`.
"""
# type: (str, TargetISA) -> None
=
=
= # type: List[Encoding]
# Tables for configuring legalization actions when no valid encoding
# exists for an instruction.
= None # type: XFormGroup
= # type: OrderedDict[ValueType, XFormGroup] # noqa
# type: () -> str
return
# type: (*Any, **Any) -> None
"""
Add a new encoding to this CPU mode.
Arguments are the `Encoding constructor arguments, except for the first
`CPUMode argument which is implied.
"""
# type: (XFormGroup, **XFormGroup) -> None
"""
Configure the legalization action per controlling type variable.
Instructions that have a controlling type variable mentioned in one of
the arguments will be legalized according to the action specified here
instead of using the `legalize_default` action.
The keyword arguments are value type names:
mode.legalize_type(i8=widen, i16=widen, i32=expand)
The `default` argument specifies the action to take for controlling
type variables that don't have an explicitly configured action.
"""
=
=
=
# type: (XFormGroup) -> None
"""
Configure the legalization action to take for monomorphic instructions
which don't have a controlling type variable.
See also `legalize_type()` for polymorphic instructions.
"""
=
# type: (ValueType) -> XFormGroup
"""
Get the legalization action to use for `ty`.
"""
return
"""
A recipe for encoding instructions with a given format.
Many different instructions can be encoded by the same recipe, but they
must all have the same instruction format.
The `ins` and `outs` arguments are tuples specifying the register
allocation constraints for the value operands and results respectively. The
possible constraints for an operand are:
- A `RegClass` specifying the set of allowed registers.
- A `Register` specifying a fixed-register operand.
- An integer indicating that this result is tied to a value operand, so
they must use the same register.
- A `Stack` specifying a value in a stack slot.
The `branch_range` argument must be provided for recipes that can encode
branch instructions. It is an `(origin, bits)` tuple describing the exact
range that can be encoded in a branch instruction.
For ISAs that use CPU flags in `iflags` and `fflags` value types, the
`clobbers_flags` is used to indicate instruction encodings that clobbers
the CPU flags, so they can't be used where a flag value is live.
:param name: Short mnemonic name for this recipe.
:param format: All encoded instructions must have this
:py:class:`InstructionFormat`.
:param base_size: Base number of bytes in the binary encoded instruction.
:param compute_size: Function name to use when computing actual size.
:param ins: Tuple of register constraints for value operands.
:param outs: Tuple of register constraints for results.
:param branch_range: `(origin, bits)` range for branches.
:param clobbers_flags: This instruction clobbers `iflags` and `fflags`.
:param instp: Instruction predicate.
:param isap: ISA predicate.
:param emit: Rust code for binary emission.
"""
# type: (...) -> None
=
=
assert >= 0
=
=
=
=
=
=
=
assert ==
= None # type: int
=
assert ==
=
# type: () -> str
return
# type: (ConstraintSeq) -> Sequence[OperandConstraint]
=
# An integer constraint is bound to a value operand.
# Check that it is in range.
assert >= 0 and <
assert
return
# type: () -> Tuple[Dict[int, int], Dict[int, int]]
"""
Return two dictionaries representing the tied operands.
The first maps input number to tied output number, the second maps
output number to tied input number.
"""
= # type: Dict[int, int]
= # type: Dict[int, int]
=
=
return
# type: () -> Tuple[Set[Register], Set[Register]]
"""
Return two sets of registers representing the fixed input and output
operands.
"""
=
=
return
# type: () -> RecipePred
"""
Get the combined recipe predicate which includes both the ISA predicate
and the instruction predicate.
Return `None` if this recipe has neither predicate.
"""
return None
return
"""
Encoding for a concrete instruction.
An `Encoding` object ties an instruction opcode with concrete type
variables together with and encoding recipe and encoding bits.
The concrete instruction can be in three different forms:
1. A naked opcode: `trap` for non-polymorphic instructions.
2. With bound type variables: `iadd.i32` for polymorphic instructions.
3. With operands providing constraints: `icmp.i32(intcc.eq, x, y)`.
If the instruction is polymorphic, all type variables must be provided.
:param cpumode: The CPU mode where the encoding is active.
:param inst: The :py:class:`Instruction` or :py:class:`BoundInstruction`
being encoded.
:param recipe: The :py:class:`EncRecipe` to use.
:param encbits: Additional encoding bits to be interpreted by `recipe`.
:param instp: Instruction predicate, or `None`.
:param isap: ISA predicate, or `None`.
"""
# type: (CPUMode, InstSpec, EncRecipe, int, PredNode, PredNode) -> None # noqa
assert
assert
# Check for possible instruction predicates in `inst`.
=
=
=
, =
# Add secondary type variables to the instruction predicate.
# This is already included by Apply.inst_predicate() above.
# A None tv is an 'any' wild card: `ishl.i32.any`.
continue
=
=
=
assert == ,
assert ,
=
=
# Record specific predicates. Note that the recipe also has predicates.
=
=
# type: () -> str
return
# type: () -> ValueType
"""
Get the controlling type variable for this encoding or `None`.
"""
return
return None