OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [arm/] [thumbemu.c] - Blame information for rev 299

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.