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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [arm/] [thumbemu.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
      valid = t_branch;         /* in-case we don't have the 2nd half */
515
      tinstr = next_instr;      /* move the instruction down */
516
      pc += 2;                  /* point the pc at the 2nd half */
517
      if (((tinstr & 0xF800) >> 11) != 31)
518
        {
519
          if (((tinstr & 0xF800) >> 11) == 29)
520
            {
521
              ARMword tmp = (pc + 2);
522
 
523
              /* Bit one of the destination address comes from bit one of the
524
                 address of the first (H == 10) half of the instruction, not
525
                 from the offset in the instruction.  */
526
              state->Reg[15] = ((state->Reg[14]
527
                                 + ((tinstr & 0x07FE) << 1)
528
                                 + ((pc - 2) & 2))
529
                                & 0xFFFFFFFC);
530
              CLEART;
531
              state->Reg[14] = (tmp | 1);
532
              valid = t_branch;
533
              FLUSHPIPE;
534
            }
535
          else
536
            /* Exit, since not correct instruction. */
537
            pc -= 2;
538
          break;
539
        }
540
      /* else we fall through to process the second half of the BL */
541
    case 31:                    /* BL instruction 2 */
542
      /* Format 19 */
543
      /* There is no single ARM instruction equivalent for this
544
         instruction. Also, it should only ever be matched with the
545
         fmt19 "BL instruction 1" instruction. However, we do allow
546
         the simulation of it on its own, with undefined results if
547
         r14 is not suitably initialised.  */
548
      {
549
        ARMword tmp = (pc + 2);
550
        state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1));
551
        state->Reg[14] = (tmp | 1);
552
        valid = t_branch;
553
        FLUSHPIPE;
554
      }
555
      break;
556
    }
557
 
558
  return valid;
559
}

powered by: WebSVN 2.1.0

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