data.isa revision 7154
1// Copyright (c) 2010 ARM Limited
2// All rights reserved
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder.  You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Gabe Black
37
38def format ArmDataProcReg() {{
39    instDecode = '''
40          case %(opcode)#x:
41            if (immShift) {
42                if (setCc) {
43                    return new %(className)sRegCc(machInst, %(dest)s, %(op1)s,
44                                                   rm, imm5, type);
45                } else {
46                    return new %(className)sReg(machInst, %(dest)s, %(op1)s,
47                                                 rm, imm5, type);
48                }
49            } else {
50                if (setCc) {
51                    return new %(className)sRegRegCc(machInst, %(dest)s,
52                                                      %(op1)s, rm, rs, type);
53                } else {
54                    return new %(className)sRegReg(machInst, %(dest)s,
55                                                    %(op1)s, rm, rs, type);
56                }
57            }
58            break;
59    '''
60
61    def instCode(opcode, mnem, dest="rd", op1="rn"):
62        global instDecode
63        return instDecode % { "className": mnem.capitalize(),
64                              "opcode": opcode,
65                              "dest": dest,
66                              "op1": op1 }
67
68    decode_block = '''
69    {
70        const bool immShift = (bits(machInst, 4) == 0);
71        const bool setCc = (bits(machInst, 20) == 1);
72        const uint32_t imm5 = bits(machInst, 11, 7);
73        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
74        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
75        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
76        const IntRegIndex rm = (IntRegIndex)(uint32_t)RM;
77        const IntRegIndex rs = (IntRegIndex)(uint32_t)RS;
78        switch (OPCODE) {
79    '''
80    decode_block += instCode(0x0, "and")
81    decode_block += instCode(0x1, "eor")
82    decode_block += instCode(0x2, "sub")
83    decode_block += instCode(0x3, "rsb")
84    decode_block += instCode(0x4, "add")
85    decode_block += instCode(0x5, "adc")
86    decode_block += instCode(0x6, "sbc")
87    decode_block += instCode(0x7, "rsc")
88    decode_block += instCode(0x8, "tst", dest="INTREG_ZERO")
89    decode_block += instCode(0x9, "teq", dest="INTREG_ZERO")
90    decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO")
91    decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO")
92    decode_block += instCode(0xc, "orr")
93    decode_block += instCode(0xd, "mov", op1="INTREG_ZERO")
94    decode_block += instCode(0xe, "bic")
95    decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO")
96    decode_block += '''
97          default:
98            return new Unknown(machInst);
99        }
100    }
101    '''
102}};
103
104def format ArmDataProcImm() {{
105    instDecode = '''
106          case %(opcode)#x:
107            if (setCc) {
108                return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
109                                               imm, rotC);
110            } else {
111                return new %(className)sImm(machInst, %(dest)s, %(op1)s,
112                                             imm, rotC);
113            }
114            break;
115    '''
116
117    def instCode(opcode, mnem, dest="rd", op1="rn"):
118        global instDecode
119        return instDecode % { "className": mnem.capitalize(),
120                              "opcode": opcode,
121                              "dest": dest,
122                              "op1": op1 }
123
124    decode_block = '''
125    {
126        const bool setCc = (bits(machInst, 20) == 1);
127        const uint32_t unrotated = bits(machInst, 7, 0);
128        const uint32_t rotation = (bits(machInst, 11, 8) << 1);
129        const bool rotC = (rotation != 0);
130        const uint32_t imm = rotate_imm(unrotated, rotation);
131        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
132        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
133        switch (OPCODE) {
134    '''
135    decode_block += instCode(0x0, "and")
136    decode_block += instCode(0x1, "eor")
137    decode_block += instCode(0x2, "sub")
138    decode_block += instCode(0x3, "rsb")
139    decode_block += instCode(0x4, "add")
140    decode_block += instCode(0x5, "adc")
141    decode_block += instCode(0x6, "sbc")
142    decode_block += instCode(0x7, "rsc")
143    decode_block += instCode(0x8, "tst", dest="INTREG_ZERO")
144    decode_block += instCode(0x9, "teq", dest="INTREG_ZERO")
145    decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO")
146    decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO")
147    decode_block += instCode(0xc, "orr")
148    decode_block += instCode(0xd, "mov", op1="INTREG_ZERO")
149    decode_block += instCode(0xe, "bic")
150    decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO")
151    decode_block += '''
152          default:
153            return new Unknown(machInst);
154        }
155    }
156    '''
157}};
158
159def format Thumb16ShiftAddSubMoveCmp() {{
160    decode_block = '''
161    {
162        const uint32_t imm5 = bits(machInst, 10, 6);
163        const uint32_t imm3 = bits(machInst, 8, 6);
164        const uint32_t imm8 = bits(machInst, 7, 0);
165        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
166        const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
167        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
168        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
169        switch (bits(machInst, 13, 11)) {
170          case 0x0: // lsl
171            return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
172          case 0x1: // lsr
173            return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
174          case 0x2: // asr
175            return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
176          case 0x3:
177            switch (bits(machInst, 10, 9)) {
178              case 0x0:
179                return new AddReg(machInst, rd, rn, rm, 0, LSL);
180              case 0x1:
181                return new SubReg(machInst, rd, rn, rm, 0, LSL);
182              case 0x2:
183                return new AddImm(machInst, rd, rn, imm3, true);
184              case 0x3:
185                return new SubImm(machInst, rd, rn, imm3, true);
186            }
187          case 0x4:
188            return new MovImm(machInst, rd8, INTREG_ZERO, imm8, true);
189          case 0x5:
190            return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
191          case 0x6:
192            return new AddImm(machInst, rd8, rd8, imm8, true);
193          case 0x7:
194            return new SubImm(machInst, rd8, rd8, imm8, true);
195        }
196    }
197    '''
198}};
199
200def format Thumb16DataProcessing() {{
201    decode_block = '''
202    {
203        const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
204        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
205        switch (bits(machInst, 9, 6)) {
206          case 0x0:
207            return new AndReg(machInst, rdn, rdn, rm, 0, LSL);
208          case 0x1:
209            return new EorReg(machInst, rdn, rdn, rm, 0, LSL);
210          case 0x2: //lsl
211            return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
212          case 0x3: //lsr
213            return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
214          case 0x4: //asr
215            return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
216          case 0x5:
217            return new AdcReg(machInst, rdn, rdn, rm, 0, LSL);
218          case 0x6:
219            return new SbcReg(machInst, rdn, rdn, rm, 0, LSL);
220          case 0x7: // ror
221            return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
222          case 0x8:
223            return new TstReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
224          case 0x9:
225            return new RsbImm(machInst, rdn, rm, 0, true);
226          case 0xa:
227            return new CmpReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
228          case 0xb:
229            return new CmnReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
230          case 0xc:
231            return new OrrReg(machInst, rdn, rdn, rm, 0, LSL);
232          case 0xd:
233            //XXX Implement me!
234            return new WarnUnimplemented("mul", machInst);
235          case 0xe:
236            return new BicReg(machInst, rdn, rdn, rm, 0, LSL);
237          case 0xf:
238            return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
239        }
240    }
241    '''
242}};
243
244def format Thumb16SpecDataAndBx() {{
245    decode_block = '''
246    {
247        const IntRegIndex rdn =
248            (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
249                                    (bits(machInst, 7) << 3));
250        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
251        switch (bits(machInst, 9, 8)) {
252          case 0x0:
253            return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
254          case 0x1:
255            return new CmpReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
256          case 0x2:
257            return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
258          case 0x3:
259            if (bits(machInst, 7) == 0) {
260                return new BxReg(machInst,
261                                 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
262                                 COND_UC);
263            } else {
264                return new BlxReg(machInst,
265                                  (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
266                                  COND_UC);
267            }
268        }
269    }
270    '''
271}};
272
273def format Thumb16Adr() {{
274    decode_block = '''
275    {
276        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
277        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
278        return new AddImm(machInst, rd, INTREG_PC, imm8, true);
279    }
280    '''
281}};
282
283def format Thumb16AddSp() {{
284    decode_block = '''
285    {
286        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
287        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
288        return new AddImm(machInst, rd, INTREG_SP, imm8, true);
289    }
290    '''
291}};
292
293def format Thumb16Misc() {{
294    decode_block = '''
295    {
296        switch (bits(machInst, 11, 8)) {
297          case 0x0:
298            if (bits(machInst, 7)) {
299                return new SubImm(machInst, INTREG_SP, INTREG_SP,
300                                   bits(machInst, 6, 0) << 2, true);
301            } else {
302                return new AddImm(machInst, INTREG_SP, INTREG_SP,
303                                   bits(machInst, 6, 0) << 2, true);
304            }
305          case 0x1:
306            return new Cbz(machInst,
307                           (bits(machInst, 9) << 6) |
308                           (bits(machInst, 7, 3) << 1),
309                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
310          case 0x2:
311            switch (bits(machInst, 7, 6)) {
312              case 0x0:
313                return new WarnUnimplemented("sxth", machInst);
314              case 0x1:
315                return new WarnUnimplemented("sxtb", machInst);
316              case 0x2:
317                return new WarnUnimplemented("uxth", machInst);
318              case 0x3:
319                return new WarnUnimplemented("uxtb", machInst);
320            }
321          case 0x3:
322            return new Cbz(machInst,
323                           (bits(machInst, 9) << 6) |
324                           (bits(machInst, 7, 3) << 1),
325                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
326          case 0x4:
327          case 0x5:
328            return new WarnUnimplemented("push", machInst);
329          case 0x6:
330            {
331                const uint32_t opBits = bits(machInst, 7, 5);
332                if (opBits == 2) {
333                    return new WarnUnimplemented("setend", machInst);
334                } else if (opBits == 3) {
335                    return new WarnUnimplemented("cps", machInst);
336                }
337            }
338          case 0x9:
339            return new Cbnz(machInst,
340                            (bits(machInst, 9) << 6) |
341                            (bits(machInst, 7, 3) << 1),
342                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
343          case 0xa:
344            switch (bits(machInst, 7, 5)) {
345              case 0x0:
346                return new WarnUnimplemented("rev", machInst);
347              case 0x1:
348                return new WarnUnimplemented("rev16", machInst);
349              case 0x3:
350                return new WarnUnimplemented("revsh", machInst);
351              default:
352                break;
353            }
354            break;
355          case 0xb:
356            return new Cbnz(machInst,
357                            (bits(machInst, 9) << 6) |
358                            (bits(machInst, 7, 3) << 1),
359                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
360          case 0xc:
361          case 0xd:
362            return new WarnUnimplemented("pop", machInst);
363          case 0xe:
364            return new WarnUnimplemented("bkpt", machInst);
365          case 0xf:
366            if (bits(machInst, 3, 0) != 0)
367                return new WarnUnimplemented("it", machInst);
368            switch (bits(machInst, 7, 4)) {
369              case 0x0:
370                return new WarnUnimplemented("nop", machInst);
371              case 0x1:
372                return new WarnUnimplemented("yield", machInst);
373              case 0x2:
374                return new WarnUnimplemented("wfe", machInst);
375              case 0x3:
376                return new WarnUnimplemented("wfi", machInst);
377              case 0x4:
378                return new WarnUnimplemented("sev", machInst);
379              default:
380                return new WarnUnimplemented("unallocated_hint", machInst);
381            }
382          default:
383            break;
384        }
385        return new Unknown(machInst);
386    }
387    '''
388}};
389
390def format Thumb32DataProcModImm() {{
391
392    def decInst(mnem, dest="rd", op1="rn"):
393        return '''
394            if (s) {
395                return new %(mnem)sImmCc(machInst, %(dest)s,
396                                          %(op1)s, imm, true);
397            } else {
398                return new %(mnem)sImm(machInst, %(dest)s,
399                                        %(op1)s, imm, true);
400            }
401        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
402
403    decode_block = '''
404    {
405        const uint32_t op = bits(machInst, 24, 21);
406        const bool s = (bits(machInst, 20) == 1);
407        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
408        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
409        const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
410                                 bits(machInst, 14, 12);
411        const uint32_t dataImm = bits(machInst, 7, 0);
412        const uint32_t imm = modified_imm(ctrlImm, dataImm);
413        switch (op) {
414          case 0x0:
415            if (rd == INTREG_PC) {
416                %(tst)s
417            } else {
418                %(and)s
419            }
420          case 0x1:
421            %(bic)s
422          case 0x2:
423            if (rn == INTREG_PC) {
424                %(mov)s
425            } else {
426                %(orr)s
427            }
428          case 0x3:
429            if (rn == INTREG_PC) {
430                %(mvn)s
431            } else {
432                %(orn)s
433            }
434          case 0x4:
435            if (rd == INTREG_PC) {
436                %(teq)s
437            } else {
438                %(eor)s
439            }
440          case 0x8:
441            if (rd == INTREG_PC) {
442                %(cmn)s
443            } else {
444                %(add)s
445            }
446          case 0xa:
447            %(adc)s
448          case 0xb:
449            %(sbc)s
450          case 0xd:
451            if (rd == INTREG_PC) {
452                %(cmp)s
453            } else {
454                %(sub)s
455            }
456          case 0xe:
457            %(rsb)s
458          default:
459            return new Unknown(machInst);
460        }
461    }
462    ''' % {
463        "tst" : decInst("Tst", "INTREG_ZERO"),
464        "and" : decInst("And"),
465        "bic" : decInst("Bic"),
466        "mov" : decInst("Mov", op1="INTREG_ZERO"),
467        "orr" : decInst("Orr"),
468        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
469        "orn" : decInst("Orn"),
470        "teq" : decInst("Teq", dest="INTREG_ZERO"),
471        "eor" : decInst("Eor"),
472        "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
473        "add" : decInst("Add"),
474        "adc" : decInst("Adc"),
475        "sbc" : decInst("Sbc"),
476        "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
477        "sub" : decInst("Sub"),
478        "rsb" : decInst("Rsb")
479    }
480}};
481
482def format Thumb32DataProcShiftReg() {{
483
484    def decInst(mnem, dest="rd", op1="rn"):
485        return '''
486            if (s) {
487                return new %(mnem)sRegCc(machInst, %(dest)s,
488                                          %(op1)s, rm, amt, type);
489            } else {
490                return new %(mnem)sReg(machInst, %(dest)s,
491                                        %(op1)s, rm, amt, type);
492            }
493        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
494
495    decode_block = '''
496    {
497        const uint32_t op = bits(machInst, 24, 21);
498        const bool s = (bits(machInst, 20) == 1);
499        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
500        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
501        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
502        const uint32_t amt = (bits(machInst, 14, 12) << 2) |
503                              bits(machInst, 7, 6);
504        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
505        switch (op) {
506          case 0x0:
507            if (rd == INTREG_PC) {
508                %(tst)s
509            } else {
510                %(and)s
511            }
512          case 0x1:
513            %(bic)s
514          case 0x2:
515            if (rn == INTREG_PC) {
516                %(mov)s
517            } else {
518                %(orr)s
519            }
520          case 0x3:
521            if (rn == INTREG_PC) {
522                %(mvn)s
523            } else {
524                %(orn)s
525            }
526          case 0x4:
527            if (rd == INTREG_PC) {
528                %(teq)s
529            } else {
530                %(eor)s
531            }
532          case 0x6:
533            return new WarnUnimplemented("pkh", machInst);
534          case 0x8:
535            if (rd == INTREG_PC) {
536                %(cmn)s
537            } else {
538                %(add)s
539            }
540          case 0xa:
541            %(adc)s
542          case 0xb:
543            %(sbc)s
544          case 0xd:
545            if (rd == INTREG_PC) {
546                %(cmp)s
547            } else {
548                %(sub)s
549            }
550          case 0xe:
551            %(rsb)s
552          default:
553            return new Unknown(machInst);
554        }
555    }
556    ''' % {
557        "tst" : decInst("Tst", "INTREG_ZERO"),
558        "and" : decInst("And"),
559        "bic" : decInst("Bic"),
560        "mov" : decInst("Mov", op1="INTREG_ZERO"),
561        "orr" : decInst("Orr"),
562        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
563        "orn" : decInst("Orn"),
564        "teq" : decInst("Teq", "INTREG_ZERO"),
565        "eor" : decInst("Eor"),
566        "cmn" : decInst("Cmn", "INTREG_ZERO"),
567        "add" : decInst("Add"),
568        "adc" : decInst("Adc"),
569        "sbc" : decInst("Sbc"),
570        "cmp" : decInst("Cmp", "INTREG_ZERO"),
571        "sub" : decInst("Sub"),
572        "rsb" : decInst("Rsb")
573    }
574}};
575