1// -*- mode:c++ -*-
2
3// Copyright (c) 2010,2012-2013,2017-2018 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Copyright (c) 2007-2008 The Florida State University
16// All rights reserved.
17//
18// Redistribution and use in source and binary forms, with or without
19// modification, are permitted provided that the following conditions are
20// met: redistributions of source code must retain the above copyright
21// notice, this list of conditions and the following disclaimer;
22// redistributions in binary form must reproduce the above copyright
23// notice, this list of conditions and the following disclaimer in the
24// documentation and/or other materials provided with the distribution;
25// neither the name of the copyright holders nor the names of its
26// contributors may be used to endorse or promote products derived from
27// this software without specific prior written permission.
28//
29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40//
41// Authors: Stephen Hines
42
43////////////////////////////////////////////////////////////////////
44//
45// Control transfer instructions
46//
47
48def format ArmBBlxImm() {{
49    decode_block = '''
50        if (machInst.condCode == 0xF) {
51            int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) |
52                          (bits(machInst, 24) << 1);
53            return new BlxImm(machInst, imm, COND_UC);
54        } else {
55            return new B(machInst, sext<26>(bits(machInst, 23, 0) << 2),
56                         (ConditionCode)(uint32_t)machInst.condCode);
57        }
58    '''
59}};
60
61def format ArmBlBlxImm() {{
62    decode_block = '''
63        if (machInst.condCode == 0xF) {
64            int32_t imm = (sext<26>(bits(machInst, 23, 0) << 2)) |
65                          (bits(machInst, 24) << 1);
66            return new BlxImm(machInst, imm, COND_UC);
67        } else {
68            return new Bl(machInst, sext<26>(bits(machInst, 23, 0) << 2),
69                          (ConditionCode)(uint32_t)machInst.condCode);
70        }
71    '''
72}};
73
74def format ArmBxClz() {{
75    decode_block = '''
76    {
77        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
78        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
79        if (OPCODE == 0x9) {
80            return new BxReg(machInst, rm,
81                    (ConditionCode)(uint32_t)machInst.condCode);
82        } else if (OPCODE == 0xb) {
83            return new Clz(machInst, rd, rm);
84        } else {
85            return new Unknown(machInst);
86        }
87    }
88    '''
89}};
90
91def format ArmBlxReg() {{
92    decode_block = '''
93        return new BlxReg(machInst, (IntRegIndex)(uint32_t)bits(machInst, 3, 0),
94                          (ConditionCode)(uint32_t)machInst.condCode);
95    '''
96}};
97
98def format Thumb16CondBranchAndSvc() {{
99    decode_block = '''
100        if (bits(machInst, 11, 9) != 0x7) {
101            return new B(machInst, sext<9>(bits(machInst, 7, 0) << 1),
102                         (ConditionCode)(uint32_t)bits(machInst, 11, 8));
103        } else if (bits(machInst, 8)) {
104            return new Svc(machInst, bits(machInst, 7, 0));
105        } else {
106            // This space will not be allocated in the future.
107            return new Unknown(machInst);
108        }
109    '''
110}};
111
112def format Thumb16UncondBranch() {{
113    decode_block = '''
114        return new B(machInst, sext<12>(bits(machInst, 10, 0) << 1), COND_UC);
115    '''
116}};
117
118def format Thumb32BranchesAndMiscCtrl() {{
119    decode_block = '''
120    {
121        const uint32_t op = bits(machInst, 26, 20);
122        const uint32_t op1 = bits(machInst, 14, 12);
123        switch (op1 & 0x5) {
124          case 0x0:
125            if (op == 127) {
126                if (op1 & 0x2) {
127                    // Permanently undefined.
128                    return new Unknown(machInst);
129                } else {
130                    return new Smc(machInst);
131                }
132            } else if ((op & 0x38) != 0x38) {
133                const uint32_t s = bits(machInst, 26);
134                const uint32_t j1 = bits(machInst, 13);
135                const uint32_t j2 = bits(machInst, 11);
136                const uint32_t imm6 = bits(machInst, 21, 16);
137                const uint32_t imm11 = bits(machInst, 10, 0);
138                const int32_t imm = sext<21>((s << 20) |
139                                             (j2 << 19) | (j1 << 18) |
140                                             (imm6 << 12) | (imm11 << 1));
141                return new B(machInst, imm,
142                             (ConditionCode)(uint32_t)bits(machInst, 25, 22));
143            } else {
144                // HIGH: 12-11=10, LOW: 15-14=00, 12=0
145                switch (op) {
146                  case 0x38:
147                  case 0x39:
148                    {
149                        const IntRegIndex rn =
150                            (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
151                        const uint8_t byteMask = bits(machInst, 11, 8);
152                        const bool    r        = bits(machInst, 20);
153                        if (bits(machInst, 5)) {
154                            const uint8_t sysM = (bits(machInst, 4) << 4) |
155                                                  byteMask;
156                            return new MsrBankedReg(machInst, rn, sysM, r);
157                        } else {
158                            if (r) {
159                                return new MsrSpsrReg(machInst, rn, byteMask);
160                            } else {
161                                return new MsrCpsrReg(machInst, rn, byteMask);
162                            }
163                        }
164                    }
165                  case 0x3a:
166                    {
167                        const uint32_t op1 = bits(machInst, 10, 8);
168                        const uint32_t hint = bits(machInst, 7, 4);
169                        const uint32_t option = bits(machInst, 3, 0);
170                        if (op1 != 0) {
171                            const bool enable = bits(machInst, 10, 9) == 0x2;
172                            const uint32_t mods = bits(machInst, 8, 0) |
173                                                  ((enable ? 1 : 0) << 9);
174                            return new Cps(machInst, mods);
175                        } else if (hint == 0xf) {
176                            return new Dbg(machInst);
177                        } else {
178                            switch (hint) {
179                              case 0x0:
180                                switch (option) {
181                                  case 0x0:
182                                    return new NopInst(machInst);
183                                  case 0x1:
184                                    return new YieldInst(machInst);
185                                  case 0x2:
186                                    return new WfeInst(machInst);
187                                  case 0x3:
188                                    return new WfiInst(machInst);
189                                  case 0x4:
190                                    return new SevInst(machInst);
191                                  case 0x5:
192                                    return new WarnUnimplemented(
193                                            "sevl", machInst);
194                                }
195                                break;
196                              case 0x1:
197                                switch (option) {
198                                  case 0x0:
199                                    return new WarnUnimplemented(
200                                            "esb", machInst);
201                                  case 0x2:
202                                    return new WarnUnimplemented(
203                                            "tsb csync", machInst);
204                                  case 0x4:
205                                    return new WarnUnimplemented(
206                                            "csdb", machInst);
207                                }
208                                break;
209                            }
210                        }
211                        return new WarnUnimplemented(
212                                "unallocated_hint", machInst);
213                    }
214                  case 0x3b:
215                    {
216                        const uint32_t op = bits(machInst, 7, 4);
217                        switch (op) {
218                          case 0x0:
219                            return new Leavex(machInst);
220                          case 0x1:
221                            return new Enterx(machInst);
222                          case 0x2:
223                            return new Clrex(machInst);
224                          case 0x4:
225                            return new Dsb(machInst, 0);
226                          case 0x5:
227                            return new Dmb(machInst, 0);
228                          case 0x6:
229                            return new Isb(machInst, 0);
230                          default:
231                            break;
232                        }
233                        break;
234                    }
235                  case 0x3c:
236                    {
237                        return new BxjReg(machInst,
238                                 (IntRegIndex)(uint32_t)bits(machInst, 19, 16),
239                                 COND_UC);
240                    }
241                  case 0x3d:
242                    {
243                        const uint32_t imm32 = bits(machInst, 7, 0);
244                        if (imm32 == 0) {
245                            return new Eret(machInst);
246                        } else {
247                            return new SubsImmPclr(machInst, INTREG_PC,
248                                                   INTREG_LR, imm32, false);
249                        }
250                    }
251                  case 0x3e:
252                  case 0x3f:
253                    {
254
255                        const IntRegIndex rd =
256                            (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
257                        const bool    r        = bits(machInst, 20);
258                        if (bits(machInst, 5)) {
259                            const uint8_t sysM = (bits(machInst, 4) << 4) |
260                                                  bits(machInst, 11, 8);
261                            return new MrsBankedReg(machInst, rd, sysM, r);
262                        } else {
263                            if (r) {
264                                return new MrsSpsr(machInst, rd);
265                            } else {
266                                return new MrsCpsr(machInst, rd);
267                            }
268                        }
269                    }
270                  case 0x7e:
271                    {
272                        uint32_t imm16 = (bits(machInst, 19, 16) << 12) |
273                                         (bits(machInst, 11,  0) <<  0);
274                        return new Hvc(machInst, imm16);
275                    }
276                }
277                break;
278            }
279          case 0x1:
280            {
281                const uint32_t s = bits(machInst, 26);
282                const uint32_t i1 = !(bits(machInst, 13) ^ s);
283                const uint32_t i2 = !(bits(machInst, 11) ^ s);
284                const uint32_t imm10 = bits(machInst, 25, 16);
285                const uint32_t imm11 = bits(machInst, 10, 0);
286                const int32_t imm = sext<25>((s << 24) |
287                                             (i1 << 23) | (i2 << 22) |
288                                             (imm10 << 12) | (imm11 << 1));
289                return new B(machInst, imm, COND_UC);
290            }
291          case 0x4:
292            {
293                if (bits(machInst, 0) == 1) {
294                    return new Unknown(machInst);
295                }
296                const uint32_t s = bits(machInst, 26);
297                const uint32_t i1 = !(bits(machInst, 13) ^ s);
298                const uint32_t i2 = !(bits(machInst, 11) ^ s);
299                const uint32_t imm10h = bits(machInst, 25, 16);
300                const uint32_t imm10l = bits(machInst, 10, 1);
301                const int32_t imm = sext<25>((s << 24) |
302                                             (i1 << 23) | (i2 << 22) |
303                                             (imm10h << 12) | (imm10l << 2));
304                return new BlxImm(machInst, imm, COND_UC);
305            }
306          case 0x5:
307            {
308                const uint32_t s = bits(machInst, 26);
309                const uint32_t i1 = !(bits(machInst, 13) ^ s);
310                const uint32_t i2 = !(bits(machInst, 11) ^ s);
311                const uint32_t imm10 = bits(machInst, 25, 16);
312                const uint32_t imm11 = bits(machInst, 10, 0);
313                const int32_t imm = sext<25>((s << 24) |
314                                             (i1 << 23) | (i2 << 22) |
315                                             (imm10 << 12) | (imm11 << 1));
316                return new Bl(machInst, imm, COND_UC);
317            }
318          default:
319            break;
320        }
321        return new Unknown(machInst);
322    }
323    '''
324}};
325