aboutsummaryrefslogtreecommitdiff
path: root/arm.risu
blob: 2c8be1178e7c3dd36db2be5cb3bdc39124231434 (plain)
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
###############################################################################
# Copyright (c) 2010 Linaro Limited
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
#     Peter Maydell (Linaro) - initial implementation
###############################################################################

# Input file for risugen defining ARM instructions

# The format here is:
# insnname encodingname bitfield ... [ { eval-block } ]
# (and we'll have a trailing bit for specifying constraints later)
# where each bitfield is either:
#  var:sz  specifying a variable field of size sz (sz == 0 if :sz omitted)
#  [01]*   specifying fixed bits
# Field names beginning 'r' are special as they are assumed to be general
# purpose registers. They get an automatic "cannot be 13 or 15" (sp/pc)
# constraint.
# The optional eval-block at the end of the line (which must be
# enclosed in braces) is a perl statement to be evaluated and which
# must return true if the generated statement is OK, false if the
# generator should retry with a fresh random number. It is evaluated
# in a context where variables with the same names as the defined
# variable fields are initialised. The intention is that odd cases
# where you need to apply some sort of constraint to the generated
# instruction can be handled via this mechanism.
# NB that there is no sanity checking that you don't do bad things
# in the eval block, although there is a basic check for syntax
# errors and and we bail out if the constraint returns failure too often.

# Some random patterns
#ADD A1 cond:4 0000 100 s rn:4 rd:4 imm:5 type:2 0 rm:4
#RBIT A1 cond:4 0110 1111 1111 rd:4 1111 0011 rm:4
#VADD A2 cond:4 11100 d 11 vn:4 vd:4 101 sz n 0 m 0 vm:4

# Some patterns for testing basic VFP arithmetic, not
# because we expect these to be wrong but so we can check
# that they work when we fiddle with the FPSCR.
VADD A2 cond:4 11100 d 11 vn:4 vd:4 101 sz n 0 m 0 vm:4
VSUB A2 cond:4 11100 d 11 vn:4 vd:4 101 sz n 1 m 0 vm:4
VMUL A2 cond:4 11100 d 10 vn:4 vd:4 101 sz n 0 m 0 vm:4
VDIV A1 cond:4 11101 d 00 vn:4 vd:4 101 sz n 0 m 0 vm:4

########### VCVT #########################################
# These patterns should cover all the VCVT* instructions
# in their ARM encodings. NB that the patterns for half
# precision conversions are commented out and untested.
##########################################################

# VCVT between fp and int: split in two because opc2 must be 000 or 10x (A8.6.295)
VCVT_a A1 cond:4 11101 d 111 000 vd:4 101 sz op 1 m 0 vm:4
VCVT_b A1 cond:4 11101 d 111 10 x vd:4 101 sz op 1 m 0 vm:4

# VCVT between fp and fixed point (A.8.6.297)
# Ugh. UNPREDICTABLE unless the 32 bit int formed by imm4:i is at least
# 16 (if sx is 0) or 32 (if sx is 1). That is, if sx==0 then either
# bit 3 must be 0 or bits 2..0 and 5 must be 0.
# sx==1 case first:
VCVT_c A1 cond:4 11101 d 111 op 1 u vd:4 101 sf 1 1 i 0 imm:4
# sx==0, bit 3 == 0
VCVT_d A1 cond:4 11101 d 111 op 1 u vd:4 101 sf 0 1 i 0 0 imm:3
# sx==0, bit 3 == 1, bits 2..0 and 5 0
VCVT_e A1 cond:4 11101 d 111 op 1 u vd:4 101 sf 0 1 0 0 1000

# VCVT fp to integer, neon (A8.6.294)
# Split to not generate the Q=1 Vd<0> or Vm<0>=1 cases
# (they UNDEF but qemu gets this wrong for just about all neon)
VCVT_neon_q0 A1 1111 0011 1 d 11 10 11 vd:4 0 11 op:2 0 m 0 vm:4
VCVT_neon_q1 A1 1111 0011 1 d 11 10 11 vd:3 0 0 11 op:2 1 m 0 vm:3 0

# VCVT fp to fixed, neon (A8.6.296)
# split to avoid generating undef case for Q=1, Vd<0> or Vm<0>=1
VCVT_neon_b_q0 A1 1111 001 u 1 d 1 imm:5 vd:4 111 op 0 0 m 1 vm:4
VCVT_neon_b_q1 A1 1111 001 u 1 d 1 imm:5 vd:3 0 111 op 0 1 m 1 vm:3 0

# VCVT between double and single (A8.6.298)
VCVT_298 A1 cond:4 1110 1 d 11 0111 vd:4 101 sz 1 1 m 0 vm:4

# These three patterns deal with conversions to and from
# half-precision (16 bit) floats. A8 doesn't have these so
# the patterns are untested.

# we don't generate the sz!=01 UNDEF cases
# two patterns to avoid the op==1 Vd<0>==1 and op==0 Vm<0>==1 UNDEF cases
# VCVT_299_a A1 1111 0011 1 d 11 01 10 vd:4 011 0 0 0 m 0 vm:3 0
# VCVT_299_b A1 1111 0011 1 d 11 01 10 vd:3 0 011 1 0 0 m 0 vm:4
# VCVTB, VCVTT (A8.6.300)
# VCTV_B_TT A1 cond:4 1110 1 d 11 001 op vd:4 101 0 t 1 m 0 vm:4


########### VQSHL ########################################
# These patterns should cover all the VQSHL* instructions
# in their ARM encodings.
##########################################################

# VQSHL reg: two patterns to avoid the UNDEF case for
# Q==1 and lsbit of vd/vn/vm!=0
VQSHL_reg_a A1 1111 001 u 0 d sz:2 vn:4 vd:4 0100 n 0 m 1 vm:4
VQSHL_reg_b A1 1111 001 u 0 d sz:2 vn:3 0 vd:3 0 0100 n 1 m 1 vm:3 0

# VQSHLU: U==0 is UNDEF so don't generate it
# Q=1 case: Vd<0> or Vm<0> == 1 => UNDEF, so avoid
# L:imm6 == 0000xxx => some other insn (we use the custom constraint for this)
VQSHLU_imm_a A1 1111 001 1 1 d imm:6 vd:3 0 011 0 l 1 m 1 vm:3 0 { ($l == 1) || ($imm & 0xca != 0); }
VQSHLU_imm_b A1 1111 001 1 1 d imm:6 vd:4 011 0 l 0 m 1 vm:4 { ($l == 1) || ($imm & 0xca != 0); }
# VQSHL imm: undefs as for VQSHLU except that U==0 is OK
VQSHL_imm_a A1 1111 001 u 1 d imm:6 vd:3 0 011 1 l 1 m 1 vm:3 0 { ($l == 1) || ($imm & 0xca != 0); }
VQSHL_imm_b A1 1111 001 u 1 d imm:6 vd:4 011 1 l 0 m 1 vm:4 { ($l == 1) || ($imm & 0xca != 0); }

# Q=1: UNDEF if lsbit of vn/vd/vm is 1
VRSQRTS_a A1 1111 0010 0 d 1 0 vn:3 0 vd:3 0 1111 n 1 m 1 vm:3 0
VRSQRTS_b A1 1111 0010 0 d 1 0 vn:4 vd:4 1111 n 0 m 1 vm:4

# various 32x32->64 multiplies
# we omit the v5-and-below constraint that rn must not be rdhi or rdlo
UMAAL A1 cond:4 0000 0100 rdhi:4 rdlo:4 rm:4 1001 rn:4 { $rdhi != $rdlo; }
UMLAL A1 cond:4 0000 101 s rdhi:4 rdlo:4 rm:4 1001 rn:4 { $rdhi != $rdlo; }
UMULL A1 cond:4 0000 100 s rdhi:4 rdlo:4 rm:4 1001 rn:4 { $rdhi != $rdlo; }
SMLAL A1 cond:4 0000 111 s rdhi:4 rdlo:4 rm:4 1001 rn:4 { $rdhi != $rdlo; }
SMULL A1 cond:4 0000 110 s rdhi:4 rdlo:4 rm:4 1001 rn:4 { $rdhi != $rdlo; }

# 32x32->64 but result is high word only
SMMLA A1 cond:4 01110101 rd:4 ra:4 rm:4 00 r 1 rn:4
SMMLS A1 cond:4 01110101 rd:4 ra:4 rm:4 11 r 1 rn:4
# Note that this doesn't overlap with SMMLA because of the implicit
# constraints on registers fields (ie not 13 or 15)
SMMUL A1 cond:4 01110101 rd:4 1111 rm:4 00 r 1 rn:4

USAT A1   cond:4 0110111 satimm:5 rd:4 imm:5 sh 0 1 rn:4
SSAT A1   cond:4 0110101 satimm:5 rd:4 imm:5 sh 0 1 rn:4
SSAT16 A1 cond:4 01101010 satimm:4 rd:4 1111 0011 rn:4
USAT16 A1 cond:4 01101110 satimm:4 rd:4 1111 0011 rn:4

# VMLAL, VMLSL, VQDMLAL, VQDMLSL, VMULL, VQDMULL
# NB that enc A1 is actually VMLA/VMLS only, A2 is VMLAL/VMLSL only
VMLAL A2 1111 001 u 1 d sz:2 vn:4 vd:3 0 10 op 0 n 0 m 0 vm:4 { $sz != 3; }
# VQDMLAL and VQDMLSL (not scalar form)
VQDLAL A1 1111 0010 1 d sz:2 vn:4 vd:3 0 10 op 1 n 0 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# VMULL (excludes the polynomial case!)
VMULL A2 1111 001 u 1 d sz:2 vn:4 vd:3 0 11 0 0 n 0 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# VQDMULL (not scalar form)
VQDMULL A1 1111 0010 1 d sz:2 vn:4 vd:3 0 1101 n 0 m 0 vm:4 { ($sz != 3) && ($sz != 0); }

# Scalar forms, VMLAL, VMLSL, VQDMLAL, VQDMLSL, VMULL, VQDMULL
# VMLAL/VMLSL scalar
VMLAL_scalar A2 1111 001 u 1 d sz:2 vn:4 vd:3 0 0 op 1 0 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# VQDMLAL/VQDMLSL scalar
VQDMLAL_scalar A2 1111 0010 1 d sz:2 vn:4 vd:3 0 0 op 11 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# VMULL scalar
VMULL_scalar A2 1111 001 u 1 d sz:2 vn:4 vd:3 0 1010 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# VQDMULL scalar
VQDMULL_scalar A2 1111 0010 1 d sz:2 vn:4 vd:3 0 1011 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }

# Neon saturating add/sub
# VQADD VQSUB
# Q=1 case:
VQADD_a A1 1111 001 u 0 d sz:2 vn:3 0 vd:3 0 0000 n 1 m 1 vm:3 0
# Q=0:
VQADD_b A1 1111 001 u 0 d sz:2 vn:4 vd:4 0000 n 0 m 1 vm:4
# VQSUB
VQSUB_a A1 1111 001 u 0 d sz:2 vn:3 0 vd:3 0 0010 n 1 m 1 vm:3 0
VQSUB_b A1 1111 001 u 0 d sz:2 vn:4 vd:4 0010 n 0 m 1 vm:4

# VQ(R)DMULH: vector saturating (rounding) doubling multiply returning high half
# Q=1 case:
VQDMULH_a A1 1111 0010 0 d sz:2 vn:3 0 vd:3 0 1011 n 1 m 0 vm:3 0 { ($sz != 3) && ($sz != 0); }
# Q=0:
VQDMULH_b A1 1111 0010 0 d sz:2 vn:4 vd:4 1011 n 0 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# scalar form Q=1
VQDMULH_a A2 1111 001 1 1 d sz:2 vn:3 0 vd:3 0 1100 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# scalar, Q=0
VQDMULH_b A2 1111 001 0 1 d sz:2 vn:4 vd:4 1100 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }

VQRDMULH_a A1 1111 0011 0 d sz:2 vn:3 0 vd:3 0 1011 n 1 m 0 vm:3 0 { ($sz != 3) && ($sz != 0); }
# Q=0:
VQRDMULH_b A1 1111 0011 0 d sz:2 vn:4 vd:4 1011 n 0 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# scalar form Q=1
VQRDMULH_a A2 1111 001 1 1 d sz:2 vn:3 0 vd:3 0 1100 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }
# scalar, Q=0
VQRDMULH_b A2 1111 001 0 1 d sz:2 vn:4 vd:4 1101 n 1 m 0 vm:4 { ($sz != 3) && ($sz != 0); }

# various preload and hint instructions
# see table A5-24 for this unallocated hint insn block (must NOP on v7MP)
UNALLOC_HINT A1 11110 100 x 001 anything:20
UNALLOC_HINT_b A1 11110 110 x 001 anything:15 0 any:4
PLI_imm A1 1111 0100 u 101 rn:4 1111 imm:12
PLI_reg A1 1111 0110 u 101 rn:4 1111 imm:5 type:2 0 rm:4
PLD_imm A1 1111 0101 u 101 rn:4 1111 imm:12
PLD_reg A1 1111 0111 u 101 rn:4 1111 imm:5 type:2 0 rm:4
PLDW_imm A1 1111 0101 u 001 rn:4 1111 imm:12
PLDW_reg A1 1111 0111 u 001 rn:4 1111 imm:5 type:2 0 rm:4
# no overlap with PLD_imm because rn can't be 15
PLD_lit A1 1111 0101 u 101 1111 1111 imm:12