aboutsummaryrefslogtreecommitdiff
path: root/target/arm/t16.decode
blob: 43b9a267a134a87b4e937d15e2d3c5afe07337b5 (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
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
# Thumb1 instructions
#
#  Copyright (c) 2019 Linaro, Ltd
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <http://www.gnu.org/licenses/>.

#
# This file is processed by scripts/decodetree.py
#

&empty           !extern
&s_rrr_shi       !extern s rd rn rm shim shty
&s_rrr_shr       !extern s rn rd rm rs shty
&s_rri_rot       !extern s rn rd imm rot
&s_rrrr          !extern s rd rn rm ra
&rrr_rot         !extern rd rn rm rot
&rr              !extern rd rm
&ri              !extern rd imm
&r               !extern rm
&i               !extern imm
&ldst_rr         !extern p w u rn rt rm shimm shtype
&ldst_ri         !extern p w u rn rt imm
&ldst_block      !extern rn i b u w list
&setend          !extern E
&cps             !extern mode imod M A I F
&ci              !extern cond imm

# Set S if the instruction is outside of an IT block.
%s               !function=t16_setflags

# Data-processing (two low registers)

%reg_0           0:3

@lll_noshr       ...... .... rm:3 rd:3 \
                 &s_rrr_shi %s rn=%reg_0 shim=0 shty=0
@xll_noshr       ...... .... rm:3 rn:3 \
                 &s_rrr_shi s=1 rd=0 shim=0 shty=0
@lxl_shr         ...... .... rs:3 rd:3 \
                 &s_rrr_shr %s rm=%reg_0 rn=0

AND_rrri         010000 0000 ... ...            @lll_noshr
EOR_rrri         010000 0001 ... ...            @lll_noshr
MOV_rxrr         010000 0010 ... ...            @lxl_shr shty=0  # LSL
MOV_rxrr         010000 0011 ... ...            @lxl_shr shty=1  # LSR
MOV_rxrr         010000 0100 ... ...            @lxl_shr shty=2  # ASR
ADC_rrri         010000 0101 ... ...            @lll_noshr
SBC_rrri         010000 0110 ... ...            @lll_noshr
MOV_rxrr         010000 0111 ... ...            @lxl_shr shty=3  # ROR
TST_xrri         010000 1000 ... ...            @xll_noshr
RSB_rri          010000 1001 rn:3 rd:3          &s_rri_rot %s imm=0 rot=0
CMP_xrri         010000 1010 ... ...            @xll_noshr
CMN_xrri         010000 1011 ... ...            @xll_noshr
ORR_rrri         010000 1100 ... ...            @lll_noshr
MUL              010000 1101 rn:3 rd:3          &s_rrrr %s rm=%reg_0 ra=0
BIC_rrri         010000 1110 ... ...            @lll_noshr
MVN_rxri         010000 1111 ... ...            @lll_noshr

# Load/store (register offset)

@ldst_rr         ....... rm:3 rn:3 rt:3 \
                 &ldst_rr p=1 w=0 u=1 shimm=0 shtype=0

STR_rr           0101 000 ... ... ...           @ldst_rr
STRH_rr          0101 001 ... ... ...           @ldst_rr
STRB_rr          0101 010 ... ... ...           @ldst_rr
LDRSB_rr         0101 011 ... ... ...           @ldst_rr
LDR_rr           0101 100 ... ... ...           @ldst_rr
LDRH_rr          0101 101 ... ... ...           @ldst_rr
LDRB_rr          0101 110 ... ... ...           @ldst_rr
LDRSH_rr         0101 111 ... ... ...           @ldst_rr

# Load/store word/byte (immediate offset)

%imm5_6x4       6:5 !function=times_4

@ldst_ri_1      ..... imm:5 rn:3 rt:3 \
                &ldst_ri p=1 w=0 u=1
@ldst_ri_4      ..... ..... rn:3 rt:3 \
                &ldst_ri p=1 w=0 u=1 imm=%imm5_6x4

STR_ri          01100 ..... ... ...             @ldst_ri_4
LDR_ri          01101 ..... ... ...             @ldst_ri_4
STRB_ri         01110 ..... ... ...             @ldst_ri_1
LDRB_ri         01111 ..... ... ...             @ldst_ri_1

# Load/store halfword (immediate offset)

%imm5_6x2       6:5 !function=times_2
@ldst_ri_2      ..... ..... rn:3 rt:3 \
                &ldst_ri p=1 w=0 u=1 imm=%imm5_6x2

STRH_ri         10000 ..... ... ...             @ldst_ri_2
LDRH_ri         10001 ..... ... ...             @ldst_ri_2

# Load/store (SP-relative)

%imm8_0x4       0:8 !function=times_4
@ldst_spec_i    ..... rt:3 ........ \
                &ldst_ri p=1 w=0 u=1 imm=%imm8_0x4

STR_ri          10010 ... ........              @ldst_spec_i rn=13
LDR_ri          10011 ... ........              @ldst_spec_i rn=13

# Load (PC-relative)

LDR_ri          01001 ... ........              @ldst_spec_i rn=15

# Add PC/SP (immediate)

ADR             10100 rd:3 ........             imm=%imm8_0x4
ADD_rri         10101 rd:3 ........ \
                &s_rri_rot rn=13 s=0 rot=0 imm=%imm8_0x4  # SP

# Load/store multiple

@ldstm          ..... rn:3 list:8               &ldst_block i=1 b=0 u=0 w=1

STM             11000 ... ........              @ldstm
LDM_t16         11001 ... ........              @ldstm

# Shift (immediate)

@shift_i        ..... shim:5 rm:3 rd:3          &s_rrr_shi %s rn=%reg_0

MOV_rxri        000 00 ..... ... ...            @shift_i shty=0  # LSL
MOV_rxri        000 01 ..... ... ...            @shift_i shty=1  # LSR
MOV_rxri        000 10 ..... ... ...            @shift_i shty=2  # ASR

# Add/subtract (three low registers)

@addsub_3       ....... rm:3 rn:3 rd:3 \
                &s_rrr_shi %s shim=0 shty=0

ADD_rrri        0001100 ... ... ...             @addsub_3
SUB_rrri        0001101 ... ... ...             @addsub_3

# Add/subtract (two low registers and immediate)

@addsub_2i      ....... imm:3 rn:3 rd:3 \
                &s_rri_rot %s rot=0

ADD_rri         0001 110 ... ... ...            @addsub_2i
SUB_rri         0001 111 ... ... ...            @addsub_2i

# Add, subtract, compare, move (one low register and immediate)

%reg_8          8:3
@arith_1i       ..... rd:3 imm:8 \
                &s_rri_rot rot=0 rn=%reg_8

MOV_rxi         00100 ... ........              @arith_1i %s
CMP_xri         00101 ... ........              @arith_1i s=1
ADD_rri         00110 ... ........              @arith_1i %s
SUB_rri         00111 ... ........              @arith_1i %s

# Add, compare, move (two high registers)

%reg_0_7        7:1 0:3
@addsub_2h      .... .... . rm:4 ... \
                &s_rrr_shi rd=%reg_0_7 rn=%reg_0_7 shim=0 shty=0

ADD_rrri        0100 0100 . .... ...            @addsub_2h s=0
CMP_xrri        0100 0101 . .... ...            @addsub_2h s=1
MOV_rxri        0100 0110 . .... ...            @addsub_2h s=0

# Adjust SP (immediate)

%imm7_0x4       0:7 !function=times_4
@addsub_sp_i    .... .... . ....... \
                &s_rri_rot s=0 rd=13 rn=13 rot=0 imm=%imm7_0x4

ADD_rri         1011 0000 0 .......             @addsub_sp_i
SUB_rri         1011 0000 1 .......             @addsub_sp_i

# Branch and exchange

@branchr        .... .... . rm:4 ...            &r

BX              0100 0111 0 .... 000            @branchr
BLX_r           0100 0111 1 .... 000            @branchr
BXNS            0100 0111 0 .... 100            @branchr
BLXNS           0100 0111 1 .... 100            @branchr

# Extend

@extend         .... .... .. rm:3 rd:3          &rrr_rot rn=15 rot=0

SXTAH           1011 0010 00 ... ...            @extend
SXTAB           1011 0010 01 ... ...            @extend
UXTAH           1011 0010 10 ... ...            @extend
UXTAB           1011 0010 11 ... ...            @extend

# Change processor state

%imod           4:1 !function=plus_2

SETEND          1011 0110 010 1 E:1 000         &setend
{
  CPS           1011 0110 011 . 0 A:1 I:1 F:1   &cps mode=0 M=0 %imod
  CPS_v7m       1011 0110 011 im:1 00 I:1 F:1
}

# Reverse bytes

@rdm            .... .... .. rm:3 rd:3          &rr

REV             1011 1010 00 ... ...            @rdm
REV16           1011 1010 01 ... ...            @rdm
REVSH           1011 1010 11 ... ...            @rdm

# Hints

{
  {
    YIELD       1011 1111 0001 0000
    WFE         1011 1111 0010 0000
    WFI         1011 1111 0011 0000

    # TODO: Implement SEV, SEVL; may help SMP performance.
    # SEV       1011 1111 0100 0000
    # SEVL      1011 1111 0101 0000

    # The canonical nop has the second nibble as 0000, but the whole of the
    # rest of the space is a reserved hint, behaves as nop.
    NOP         1011 1111 ---- 0000
  }
  IT            1011 1111 cond_mask:8
}

# Miscellaneous 16-bit instructions

%imm6_9_3       9:1 3:5 !function=times_2

HLT             1011 1010 10 imm:6              &i
BKPT            1011 1110 imm:8                 &i
CBZ             1011 nz:1 0.1 ..... rn:3        imm=%imm6_9_3

# Push and Pop

%push_list      0:9 !function=t16_push_list
%pop_list       0:9 !function=t16_pop_list

STM             1011 010 ......... \
                &ldst_block i=0 b=1 u=0 w=1 rn=13 list=%push_list
LDM_t16         1011 110 ......... \
                &ldst_block i=1 b=0 u=0 w=1 rn=13 list=%pop_list

# Conditional branches, Supervisor call

%imm8_0x2       0:s8 !function=times_2

{
  UDF           1101 1110 ---- ----
  SVC           1101 1111 imm:8                 &i
  B_cond_thumb  1101 cond:4 ........            &ci imm=%imm8_0x2
}

# Unconditional Branch

%imm11_0x2      0:s11 !function=times_2

B               11100 ...........               &i imm=%imm11_0x2

# thumb_insn_is_16bit() ensures we won't be decoding these as
# T16 instructions for a Thumb2 CPU, so these patterns must be
# a Thumb1 split BL/BLX.
BLX_suffix      11101 imm:11                    &i
BL_BLX_prefix   11110 imm:s11                   &i
BL_suffix       11111 imm:11                    &i