0aa0f61fed08b88d5051dc5a810d2feea70dbc16
[external/binutils.git] / sim / arm / thumbemu.c
1 /*  thumbemu.c -- Thumb instruction emulation.
2     Copyright (C) 1996, Cygnus Software Technologies Ltd.
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8  
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13  
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17
18 /* We can provide simple Thumb simulation by decoding the Thumb
19 instruction into its corresponding ARM instruction, and using the
20 existing ARM simulator.  */
21
22 #ifndef MODET                   /* required for the Thumb instruction support */
23 #if 1
24 #error "MODET needs to be defined for the Thumb world to work"
25 #else
26 #define MODET (1)
27 #endif
28 #endif
29
30 #include "armdefs.h"
31 #include "armemu.h"
32 #include "armos.h"
33
34 /* Decode a 16bit Thumb instruction.  The instruction is in the low
35    16-bits of the tinstr field, with the following Thumb instruction
36    held in the high 16-bits.  Passing in two Thumb instructions allows
37    easier simulation of the special dual BL instruction.  */
38
39 tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
40      ARMul_State *
41        state;
42      ARMword
43        pc;
44      ARMword
45        tinstr;
46      ARMword *
47        ainstr;
48 {
49   tdstate valid = t_decoded;    /* default assumes a valid instruction */
50   ARMword next_instr;
51
52   if (state->bigendSig)
53     {
54       next_instr = tinstr & 0xFFFF;
55       tinstr >>= 16;
56     }
57   else
58     {
59       next_instr = tinstr >> 16;
60       tinstr &= 0xFFFF;
61     }
62
63 #if 1                           /* debugging to catch non updates */
64   *ainstr = 0xDEADC0DE;
65 #endif
66
67   switch ((tinstr & 0xF800) >> 11)
68     {
69     case 0:                     /* LSL */
70     case 1:                     /* LSR */
71     case 2:                     /* ASR */
72       /* Format 1 */
73       *ainstr = 0xE1B00000      /* base opcode */
74         | ((tinstr & 0x1800) >> (11 - 5))       /* shift type */
75         | ((tinstr & 0x07C0) << (7 - 6))        /* imm5 */
76         | ((tinstr & 0x0038) >> 3)      /* Rs */
77         | ((tinstr & 0x0007) << 12);    /* Rd */
78       break;
79     case 3:                     /* ADD/SUB */
80       /* Format 2 */
81       {
82         ARMword subset[4] = {
83           0xE0900000,           /* ADDS Rd,Rs,Rn    */
84           0xE0500000,           /* SUBS Rd,Rs,Rn    */
85           0xE2900000,           /* ADDS Rd,Rs,#imm3 */
86           0xE2500000            /* SUBS Rd,Rs,#imm3 */
87         };
88         /* It is quicker indexing into a table, than performing switch
89            or conditionals: */
90         *ainstr = subset[(tinstr & 0x0600) >> 9]        /* base opcode */
91           | ((tinstr & 0x01C0) >> 6)    /* Rn or imm3 */
92           | ((tinstr & 0x0038) << (16 - 3))     /* Rs */
93           | ((tinstr & 0x0007) << (12 - 0));    /* Rd */
94       }
95       break;
96     case 4:                     /* MOV */
97     case 5:                     /* CMP */
98     case 6:                     /* ADD */
99     case 7:                     /* SUB */
100       /* Format 3 */
101       {
102         ARMword subset[4] = {
103           0xE3B00000,           /* MOVS Rd,#imm8    */
104           0xE3500000,           /* CMP  Rd,#imm8    */
105           0xE2900000,           /* ADDS Rd,Rd,#imm8 */
106           0xE2500000,           /* SUBS Rd,Rd,#imm8 */
107         };
108         *ainstr = subset[(tinstr & 0x1800) >> 11]       /* base opcode */
109           | ((tinstr & 0x00FF) >> 0)    /* imm8 */
110           | ((tinstr & 0x0700) << (16 - 8))     /* Rn */
111           | ((tinstr & 0x0700) << (12 - 8));    /* Rd */
112       }
113       break;
114     case 8:                     /* Arithmetic and high register transfers */
115       /* TODO: Since the subsets for both Format 4 and Format 5
116          instructions are made up of different ARM encodings, we could
117          save the following conditional, and just have one large
118          subset. */
119       if ((tinstr & (1 << 10)) == 0)
120         {
121           /* Format 4 */
122           struct
123           {
124             ARMword opcode;
125             enum
126             { t_norm, t_shift, t_neg, t_mul }
127             otype;
128           }
129           subset[16] =
130           {
131             { 0xE0100000, t_norm},                      /* ANDS Rd,Rd,Rs     */
132             { 0xE0300000, t_norm},                      /* EORS Rd,Rd,Rs     */
133             { 0xE1B00010, t_shift},                     /* MOVS Rd,Rd,LSL Rs */
134             { 0xE1B00030, t_shift},                     /* MOVS Rd,Rd,LSR Rs */
135             { 0xE1B00050, t_shift},                     /* MOVS Rd,Rd,ASR Rs */
136             { 0xE0B00000, t_norm},                      /* ADCS Rd,Rd,Rs     */
137             { 0xE0D00000, t_norm},                      /* SBCS Rd,Rd,Rs     */
138             { 0xE1B00070, t_shift},                     /* MOVS Rd,Rd,ROR Rs */
139             { 0xE1100000, t_norm},                      /* TST  Rd,Rs        */
140             { 0xE2700000, t_neg},                       /* RSBS Rd,Rs,#0     */
141             { 0xE1500000, t_norm},                      /* CMP  Rd,Rs        */
142             { 0xE1700000, t_norm},                      /* CMN  Rd,Rs        */
143             { 0xE1900000, t_norm},                      /* ORRS Rd,Rd,Rs     */
144             { 0xE0100090, t_mul} ,                      /* MULS Rd,Rd,Rs     */
145             { 0xE1D00000, t_norm},                      /* BICS Rd,Rd,Rs     */
146             { 0xE1F00000, t_norm}       /* MVNS Rd,Rs        */
147           };
148           *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;      /* base */
149           switch (subset[(tinstr & 0x03C0) >> 6].otype)
150             {
151             case t_norm:
152               *ainstr |= ((tinstr & 0x0007) << 16)      /* Rn */
153                 | ((tinstr & 0x0007) << 12)     /* Rd */
154                 | ((tinstr & 0x0038) >> 3);     /* Rs */
155               break;
156             case t_shift:
157               *ainstr |= ((tinstr & 0x0007) << 12)      /* Rd */
158                 | ((tinstr & 0x0007) >> 0)      /* Rm */
159                 | ((tinstr & 0x0038) << (8 - 3));       /* Rs */
160               break;
161             case t_neg:
162               *ainstr |= ((tinstr & 0x0007) << 12)      /* Rd */
163                 | ((tinstr & 0x0038) << (16 - 3));      /* Rn */
164               break;
165             case t_mul:
166               *ainstr |= ((tinstr & 0x0007) << 16)      /* Rd */
167                 | ((tinstr & 0x0007) << 8)      /* Rs */
168                 | ((tinstr & 0x0038) >> 3);     /* Rm */
169               break;
170             }
171         }
172       else
173         {
174           /* Format 5 */
175           ARMword Rd = ((tinstr & 0x0007) >> 0);
176           ARMword Rs = ((tinstr & 0x0038) >> 3);
177           if (tinstr & (1 << 7))
178             Rd += 8;
179           if (tinstr & (1 << 6))
180             Rs += 8;
181           switch ((tinstr & 0x03C0) >> 6)
182             {
183             case 0x1:           /* ADD Rd,Rd,Hs */
184             case 0x2:           /* ADD Hd,Hd,Rs */
185             case 0x3:           /* ADD Hd,Hd,Hs */
186               *ainstr = 0xE0800000      /* base */
187                 | (Rd << 16)    /* Rn */
188                 | (Rd << 12)    /* Rd */
189                 | (Rs << 0);    /* Rm */
190               break;
191             case 0x5:           /* CMP Rd,Hs */
192             case 0x6:           /* CMP Hd,Rs */
193             case 0x7:           /* CMP Hd,Hs */
194               *ainstr = 0xE1500000      /* base */
195                 | (Rd << 16)    /* Rn */
196                 | (Rd << 12)    /* Rd */
197                 | (Rs << 0);    /* Rm */
198               break;
199             case 0x9:           /* MOV Rd,Hs */
200             case 0xA:           /* MOV Hd,Rs */
201             case 0xB:           /* MOV Hd,Hs */
202               *ainstr = 0xE1A00000      /* base */
203                 | (Rd << 16)    /* Rn */
204                 | (Rd << 12)    /* Rd */
205                 | (Rs << 0);    /* Rm */
206               break;
207             case 0xC:           /* BX Rs */
208             case 0xD:           /* BX Hs */
209               *ainstr = 0xE12FFF10      /* base */
210                 | ((tinstr & 0x0078) >> 3);     /* Rd */
211               break;
212             case 0xE:           /* UNDEFINED */
213             case 0xF:           /* UNDEFINED */
214               if (state->is_v5)
215                 {
216                   /* BLX Rs; BLX Hs */
217                   *ainstr = 0xE12FFF30  /* base */
218                     | ((tinstr & 0x0078) >> 3); /* Rd */
219                   break;
220                 }
221               /* Drop through.  */
222             case 0x0:           /* UNDEFINED */
223             case 0x4:           /* UNDEFINED */
224             case 0x8:           /* UNDEFINED */
225               valid = t_undefined;
226               break;
227             }
228         }
229       break;
230     case 9:                     /* LDR Rd,[PC,#imm8] */
231       /* Format 6 */
232       *ainstr = 0xE59F0000      /* base */
233         | ((tinstr & 0x0700) << (12 - 8))       /* Rd */
234         | ((tinstr & 0x00FF) << (2 - 0));       /* off8 */
235       break;
236     case 10:
237     case 11:
238       /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
239          the following could be merged into a single subset, saving on
240          the following boolean: */
241       if ((tinstr & (1 << 9)) == 0)
242         {
243           /* Format 7 */
244           ARMword subset[4] = {
245             0xE7800000,         /* STR  Rd,[Rb,Ro] */
246             0xE7C00000,         /* STRB Rd,[Rb,Ro] */
247             0xE7900000,         /* LDR  Rd,[Rb,Ro] */
248             0xE7D00000          /* LDRB Rd,[Rb,Ro] */
249           };
250           *ainstr = subset[(tinstr & 0x0C00) >> 10]     /* base */
251             | ((tinstr & 0x0007) << (12 - 0))   /* Rd */
252             | ((tinstr & 0x0038) << (16 - 3))   /* Rb */
253             | ((tinstr & 0x01C0) >> 6); /* Ro */
254         }
255       else
256         {
257           /* Format 8 */
258           ARMword subset[4] = {
259             0xE18000B0,         /* STRH  Rd,[Rb,Ro] */
260             0xE19000D0,         /* LDRSB Rd,[Rb,Ro] */
261             0xE19000B0,         /* LDRH  Rd,[Rb,Ro] */
262             0xE19000F0          /* LDRSH Rd,[Rb,Ro] */
263           };
264           *ainstr = subset[(tinstr & 0x0C00) >> 10]     /* base */
265             | ((tinstr & 0x0007) << (12 - 0))   /* Rd */
266             | ((tinstr & 0x0038) << (16 - 3))   /* Rb */
267             | ((tinstr & 0x01C0) >> 6); /* Ro */
268         }
269       break;
270     case 12:                    /* STR Rd,[Rb,#imm5] */
271     case 13:                    /* LDR Rd,[Rb,#imm5] */
272     case 14:                    /* STRB Rd,[Rb,#imm5] */
273     case 15:                    /* LDRB Rd,[Rb,#imm5] */
274       /* Format 9 */
275       {
276         ARMword subset[4] = {
277           0xE5800000,           /* STR  Rd,[Rb,#imm5] */
278           0xE5900000,           /* LDR  Rd,[Rb,#imm5] */
279           0xE5C00000,           /* STRB Rd,[Rb,#imm5] */
280           0xE5D00000            /* LDRB Rd,[Rb,#imm5] */
281         };
282         /* The offset range defends on whether we are transferring a
283            byte or word value: */
284         *ainstr = subset[(tinstr & 0x1800) >> 11]       /* base */
285           | ((tinstr & 0x0007) << (12 - 0))     /* Rd */
286           | ((tinstr & 0x0038) << (16 - 3))     /* Rb */
287           | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2)));        /* off5 */
288       }
289       break;
290     case 16:                    /* STRH Rd,[Rb,#imm5] */
291     case 17:                    /* LDRH Rd,[Rb,#imm5] */
292       /* Format 10 */
293       *ainstr = ((tinstr & (1 << 11))   /* base */
294                  ? 0xE1D000B0   /* LDRH */
295                  : 0xE1C000B0)  /* STRH */
296         | ((tinstr & 0x0007) << (12 - 0))       /* Rd */
297         | ((tinstr & 0x0038) << (16 - 3))       /* Rb */
298         | ((tinstr & 0x01C0) >> (6 - 1))        /* off5, low nibble */
299         | ((tinstr & 0x0600) >> (9 - 8));       /* off5, high nibble */
300       break;
301     case 18:                    /* STR Rd,[SP,#imm8] */
302     case 19:                    /* LDR Rd,[SP,#imm8] */
303       /* Format 11 */
304       *ainstr = ((tinstr & (1 << 11))   /* base */
305                  ? 0xE59D0000   /* LDR */
306                  : 0xE58D0000)  /* STR */
307         | ((tinstr & 0x0700) << (12 - 8))       /* Rd */
308         | ((tinstr & 0x00FF) << 2);     /* off8 */
309       break;
310     case 20:                    /* ADD Rd,PC,#imm8 */
311     case 21:                    /* ADD Rd,SP,#imm8 */
312       /* Format 12 */
313       if ((tinstr & (1 << 11)) == 0)
314         {
315           /* NOTE: The PC value used here should by word aligned */
316           /* We encode shift-left-by-2 in the rotate immediate field,
317              so no shift of off8 is needed.  */
318           *ainstr = 0xE28F0F00  /* base */
319             | ((tinstr & 0x0700) << (12 - 8))   /* Rd */
320             | (tinstr & 0x00FF);        /* off8 */
321         }
322       else
323         {
324           /* We encode shift-left-by-2 in the rotate immediate field,
325              so no shift of off8 is needed.  */
326           *ainstr = 0xE28D0F00  /* base */
327             | ((tinstr & 0x0700) << (12 - 8))   /* Rd */
328             | (tinstr & 0x00FF);        /* off8 */
329         }
330       break;
331     case 22:
332     case 23:
333       switch (tinstr & 0x0F00)
334         {
335         case 0x0000:
336           /* Format 13 */
337           /* NOTE: The instruction contains a shift left of 2
338              equivalent (implemented as ROR #30):  */
339           *ainstr = ((tinstr & (1 << 7))        /* base */
340                      ? 0xE24DDF00       /* SUB */
341                      : 0xE28DDF00)      /* ADD */
342             | (tinstr & 0x007F);        /* off7 */
343           break;
344         case 0x0400:
345           /* Format 14 - Push */
346           * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
347           break;
348         case 0x0500:
349           /* Format 14 - Push + LR */
350           * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
351           break;
352         case 0x0c00:
353           /* Format 14 - Pop */
354           * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
355           break;
356         case 0x0d00:
357           /* Format 14 - Pop + PC */
358           * ainstr = 0xE8BD8000 | (tinstr & 0x00FF);
359           break;
360         case 0x0e00:
361           if (state->is_v5)
362             {
363               /* This is normally an undefined instruction.  The v5t architecture 
364                  defines this particular pattern as a BKPT instruction, for
365                  hardware assisted debugging.  We map onto the arm BKPT
366                  instruction.  */
367               * ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
368               break;
369             }
370           /* Drop through.  */
371         default:
372           /* Everything else is an undefined instruction.  */
373           valid = t_undefined;
374           break;
375         }
376       break;
377     case 24:                    /* STMIA */
378     case 25:                    /* LDMIA */
379       /* Format 15 */
380       *ainstr = ((tinstr & (1 << 11))   /* base */
381                  ? 0xE8B00000   /* LDMIA */
382                  : 0xE8A00000)  /* STMIA */
383         | ((tinstr & 0x0700) << (16 - 8))       /* Rb */
384         | (tinstr & 0x00FF);    /* mask8 */
385       break;
386     case 26:                    /* Bcc */
387     case 27:                    /* Bcc/SWI */
388       if ((tinstr & 0x0F00) == 0x0F00)
389         {
390           /* Format 17 : SWI */
391           *ainstr = 0xEF000000;
392           /* Breakpoint must be handled specially.  */
393           if ((tinstr & 0x00FF) == 0x18)
394             *ainstr |= ((tinstr & 0x00FF) << 16);
395           /* New breakpoint value.  See gdb/arm-tdep.c  */
396           else if ((tinstr & 0x00FF) == 0xFE)
397             *ainstr |= SWI_Breakpoint;
398           else
399             *ainstr |= (tinstr & 0x00FF);
400         }
401       else if ((tinstr & 0x0F00) != 0x0E00)
402         {
403           /* Format 16 */
404           int doit = FALSE;
405           /* TODO: Since we are doing a switch here, we could just add
406              the SWI and undefined instruction checks into this
407              switch to same on a couple of conditionals: */
408           switch ((tinstr & 0x0F00) >> 8)
409             {
410             case EQ:
411               doit = ZFLAG;
412               break;
413             case NE:
414               doit = !ZFLAG;
415               break;
416             case VS:
417               doit = VFLAG;
418               break;
419             case VC:
420               doit = !VFLAG;
421               break;
422             case MI:
423               doit = NFLAG;
424               break;
425             case PL:
426               doit = !NFLAG;
427               break;
428             case CS:
429               doit = CFLAG;
430               break;
431             case CC:
432               doit = !CFLAG;
433               break;
434             case HI:
435               doit = (CFLAG && !ZFLAG);
436               break;
437             case LS:
438               doit = (!CFLAG || ZFLAG);
439               break;
440             case GE:
441               doit = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
442               break;
443             case LT:
444               doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
445               break;
446             case GT:
447               doit = ((!NFLAG && !VFLAG && !ZFLAG)
448                       || (NFLAG && VFLAG && !ZFLAG));
449               break;
450             case LE:
451               doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
452               break;
453             }
454           if (doit)
455             {
456               state->Reg[15] = (pc + 4
457                                 + (((tinstr & 0x7F) << 1)
458                                    | ((tinstr & (1 << 7)) ? 0xFFFFFF00 : 0)));
459               FLUSHPIPE;
460             }
461           valid = t_branch;
462         }
463       else                      /* UNDEFINED : cc=1110(AL) uses different format */
464         valid = t_undefined;
465       break;
466     case 28:                    /* B */
467       /* Format 18 */
468       state->Reg[15] = (pc + 4
469                         + (((tinstr & 0x3FF) << 1)
470                            | ((tinstr & (1 << 10)) ? 0xFFFFF800 : 0)));
471       FLUSHPIPE;
472       valid = t_branch;
473       break;
474     case 29:                    /* UNDEFINED */
475       if (state->is_v5)
476         {
477           if (tinstr & 1)
478             {
479               valid = t_undefined;
480               break;
481             }
482           /* Drop through.  */
483           
484           /* Format 19 */
485           /* There is no single ARM instruction equivalent for this
486              instruction. Also, it should only ever be matched with the
487              fmt19 "BL/BLX instruction 1" instruction.  However, we do
488              allow the simulation of it on its own, with undefined results
489              if r14 is not suitably initialised.  */
490           {
491             ARMword tmp = (pc + 2);
492
493             state->Reg[15] = ((state->Reg[14] + ((tinstr & 0x07FF) << 1))
494                               & 0xFFFFFFFC);
495             CLEART;
496             state->Reg[14] = (tmp | 1);
497             valid = t_branch;
498             FLUSHPIPE;
499             break;
500           }
501         }
502       valid = t_undefined;
503       break;
504     case 30:                    /* BL instruction 1 */
505       /* Format 19 */
506       /* There is no single ARM instruction equivalent for this Thumb
507          instruction. To keep the simulation simple (from the user
508          perspective) we check if the following instruction is the
509          second half of this BL, and if it is we simulate it
510          immediately.  */
511       state->Reg[14] = state->Reg[15] \
512         + (((tinstr & 0x07FF) << 12) \
513            | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
514
515       valid = t_branch;         /* in-case we don't have the 2nd half */
516       tinstr = next_instr;      /* move the instruction down */
517       pc += 2;                  /* point the pc at the 2nd half */
518       if (((tinstr & 0xF800) >> 11) != 31)
519         {
520           if (((tinstr & 0xF800) >> 11) == 29)
521             {
522               ARMword tmp = (pc + 2);
523
524               state->Reg[15] = ((state->Reg[14]
525                                  + ((tinstr & 0x07FE) << 1))
526                                 & 0xFFFFFFFC);
527               CLEART;
528               state->Reg[14] = (tmp | 1);
529               valid = t_branch;
530               FLUSHPIPE;
531             }
532           else
533             /* Exit, since not correct instruction. */
534             pc -= 2;
535           break;
536         }
537       /* else we fall through to process the second half of the BL */
538       pc += 2;                  /* point the pc at the 2nd half */
539     case 31:                    /* BL instruction 2 */
540       /* Format 19 */
541       /* There is no single ARM instruction equivalent for this
542          instruction. Also, it should only ever be matched with the
543          fmt19 "BL instruction 1" instruction. However, we do allow
544          the simulation of it on its own, with undefined results if
545          r14 is not suitably initialised.  */
546       {
547         ARMword tmp = pc;
548
549         state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1));
550         state->Reg[14] = (tmp | 1);
551         valid = t_branch;
552         FLUSHPIPE;
553       }
554       break;
555     }
556
557   return valid;
558 }