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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [igen/] [gen-idecode.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
#include "misc.h"
22
#include "lf.h"
23
#include "table.h"
24
#include "filter.h"
25
#include "igen.h"
26
 
27
#include "ld-insn.h"
28
#include "ld-decode.h"
29
 
30
#include "gen.h"
31
 
32
#include "gen-idecode.h"
33
#include "gen-icache.h"
34
#include "gen-semantics.h"
35
 
36
 
37
 
38
static void
39
lf_print_opcodes (lf *file,
40
                  gen_entry *table)
41
{
42
  if (table != NULL)
43
    {
44
      while (1)
45
        {
46
          ASSERT (table->opcode != NULL);
47
          lf_printf (file, "_%d_%d",
48
                     table->opcode->first,
49
                     table->opcode->last);
50
          if (table->parent == NULL) break;
51
          lf_printf (file, "__%d", table->opcode_nr);
52
          table = table->parent;
53
        }
54
    }
55
}
56
 
57
 
58
 
59
 
60
static void
61
print_idecode_ifetch (lf *file,
62
                      int previous_nr_prefetched_words,
63
                      int current_nr_prefetched_words)
64
{
65
  int word_nr;
66
  for (word_nr = previous_nr_prefetched_words;
67
       word_nr < current_nr_prefetched_words;
68
       word_nr ++)
69
    {
70
      lf_printf (file, "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n",
71
                 word_nr, options.insn_bit_size, word_nr);
72
 
73
    }
74
}
75
 
76
 
77
 
78
/****************************************************************/
79
 
80
 
81
static void
82
lf_print_table_name (lf *file,
83
                     gen_entry *table)
84
{
85
  lf_printf (file, "idecode_table");
86
  lf_print_opcodes (file, table);
87
}
88
 
89
 
90
 
91
static void
92
print_idecode_table (lf *file,
93
                     gen_entry *entry,
94
                     const char *result)
95
{
96
  lf_printf (file, "/* prime the search */\n");
97
  lf_printf (file, "idecode_table_entry *table = ");
98
  lf_print_table_name (file, entry);
99
  lf_printf (file, ";\n");
100
  lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n",
101
             options.insn_bit_size,
102
             i2target (options.hi_bit_nr, entry->opcode->first),
103
             i2target (options.hi_bit_nr, entry->opcode->last));
104
  lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n");
105
 
106
  lf_printf (file, "\n");
107
  lf_printf (file, "/* iterate until a leaf */\n");
108
  lf_printf (file, "while (1) {\n");
109
  lf_printf (file, "  signed shift = table_entry->shift;\n");
110
  lf_printf (file, "if (shift == function_entry) break;\n");
111
  lf_printf (file, "  if (shift >= 0) {\n");
112
  lf_printf (file, "    table = ((idecode_table_entry*)\n");
113
  lf_printf (file, "             table_entry->function_or_table);\n");
114
  lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
115
  lf_printf (file, "              >> shift);\n");
116
  lf_printf (file, "    table_entry = table + opcode;\n");
117
  lf_printf (file, "  }\n");
118
  lf_printf (file, "  else {\n");
119
  lf_printf (file, "    /* must be a boolean */\n");
120
  lf_printf (file, "    ASSERT(table_entry->shift == boolean_entry);\n");
121
  lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
122
  lf_printf (file, "              != table_entry->value);\n");
123
  lf_printf (file, "    table = ((idecode_table_entry*)\n");
124
  lf_printf (file, "             table_entry->function_or_table);\n");
125
  lf_printf (file, "    table_entry = table + opcode;\n");
126
  lf_printf (file, "  }\n");
127
  lf_printf (file, "}\n");
128
 
129
  lf_printf (file, "\n");
130
  lf_printf (file, "/* call the leaf code */\n");
131
  if (options.gen.code == generate_jumps)
132
    {
133
      lf_printf (file, "goto *table_entry->function_or_table;\n");
134
    }
135
  else
136
    {
137
      lf_printf (file, "%s ", result);
138
      if (options.gen.icache)
139
        {
140
          lf_printf (file, "(((idecode_icache*)table_entry->function_or_table)\n");
141
          lf_printf (file, "  (");
142
          print_icache_function_actual (file, 1);
143
          lf_printf (file, "));\n");
144
        }
145
      else
146
        {
147
          lf_printf (file, "((idecode_semantic*)table_entry->function_or_table)\n");
148
          lf_printf (file, "  (");
149
          print_semantic_function_actual (file, 1);
150
          lf_printf (file, ");\n");
151
        }
152
    }
153
}
154
 
155
 
156
static void
157
print_idecode_table_start (lf *file,
158
                           gen_entry *table,
159
                           int depth,
160
                           void *data)
161
{
162
  ASSERT (depth == 0);
163
  /* start of the table */
164
  if (table->opcode_rule->gen == array_gen)
165
    {
166
      lf_printf (file, "\n");
167
      lf_printf (file, "static idecode_table_entry ");
168
      lf_print_table_name (file, table);
169
      lf_printf (file, "[] = {\n");
170
    }
171
}
172
 
173
static void
174
print_idecode_table_leaf (lf *file,
175
                          gen_entry *entry,
176
                          int depth,
177
                          void *data)
178
{
179
  gen_entry *master_entry;
180
  ASSERT (entry->parent != NULL);
181
  ASSERT (depth == 0);
182
  if (entry->combined_parent == NULL)
183
    master_entry = entry;
184
  else
185
    master_entry = entry->combined_parent;
186
 
187
  /* add an entry to the table */
188
  if (entry->parent->opcode_rule->gen == array_gen)
189
    {
190
      lf_printf (file, "  /*%d*/ { ", entry->opcode_nr);
191
      if (entry->opcode == NULL)
192
        {
193
          ASSERT (entry->nr_insns == 1);
194
          /* table leaf entry */
195
          lf_printf (file, "function_entry, 0, 0, ");
196
          if (options.gen.code == generate_jumps)
197
            {
198
              lf_printf (file, "&&");
199
            }
200
          print_function_name (file,
201
                               entry->insns->insn->name,
202
                               entry->insns->insn->format_name,
203
                               NULL,
204
                               master_entry->expanded_bits,
205
                               (options.gen.icache
206
                                ? function_name_prefix_icache
207
                                : function_name_prefix_semantics));
208
        }
209
      else if (entry->opcode_rule->gen == switch_gen
210
               || entry->opcode_rule->gen == goto_switch_gen
211
               || entry->opcode_rule->gen == padded_switch_gen)
212
        {
213
          /* table calling switch statement */
214
          lf_printf (file, "function_entry, 0, 0, ");
215
          if (options.gen.code == generate_jumps)
216
            {
217
              lf_printf (file, "&&");
218
            }
219
          lf_print_table_name (file, entry);
220
        }
221
      else if (entry->opcode->is_boolean)
222
        {
223
          /* table `calling' boolean table */
224
          lf_printf (file, "boolean_entry, ");
225
          lf_printf (file, "MASK32(%d, %d), ",
226
                     i2target (options.hi_bit_nr, entry->opcode->first),
227
                     i2target (options.hi_bit_nr, entry->opcode->last));
228
          lf_printf (file, "INSERTED32(%d, %d, %d), ",
229
                     entry->opcode->boolean_constant,
230
                     i2target (options.hi_bit_nr, entry->opcode->first),
231
                     i2target (options.hi_bit_nr, entry->opcode->last));
232
          lf_print_table_name (file, entry);
233
        }
234
      else
235
        {
236
          /* table `calling' another table */
237
          lf_printf (file, "%d, ", options.insn_bit_size - entry->opcode->last - 1);
238
          lf_printf (file, "MASK%d(%d,%d), ",
239
                     options.insn_bit_size,
240
                     i2target (options.hi_bit_nr, entry->opcode->first),
241
                     i2target (options.hi_bit_nr, entry->opcode->last));
242
          lf_printf (file, "0, ");
243
          lf_print_table_name (file, entry);
244
        }
245
      lf_printf (file, " },\n");
246
    }
247
}
248
 
249
static void
250
print_idecode_table_end (lf *file,
251
                         gen_entry *table,
252
                         int depth,
253
                         void *data)
254
{
255
  ASSERT (depth == 0);
256
  if (table->opcode_rule->gen == array_gen) {
257
    lf_printf (file, "};\n");
258
  }
259
}
260
 
261
/****************************************************************/
262
 
263
 
264
static void
265
print_goto_switch_name (lf *file,
266
                        gen_entry *entry)
267
{
268
  lf_printf (file, "case_");
269
  if (entry->opcode == NULL)
270
    {
271
      print_function_name (file,
272
                           entry->insns->insn->name,
273
                           entry->insns->insn->format_name,
274
                           NULL,
275
                           entry->expanded_bits,
276
                           (options.gen.icache
277
                            ? function_name_prefix_icache
278
                            : function_name_prefix_semantics));
279
    }
280
  else
281
    {
282
      lf_print_table_name(file, entry);
283
    }
284
}
285
 
286
static void
287
print_goto_switch_table_leaf (lf *file,
288
                              gen_entry *entry,
289
                              int depth,
290
                              void *data)
291
{
292
  ASSERT (entry->parent != NULL);
293
  ASSERT (depth == 0);
294
  ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen);
295
  ASSERT (entry->parent->opcode);
296
 
297
  lf_printf (file, "/* %d */ &&", entry->opcode_nr);
298
  if (entry->combined_parent != NULL)
299
    print_goto_switch_name (file, entry->combined_parent);
300
  else
301
    print_goto_switch_name (file, entry);
302
  lf_printf (file, ",\n");
303
}
304
 
305
static void
306
print_goto_switch_break (lf *file,
307
                         gen_entry *entry)
308
{
309
  lf_printf (file, "goto break_");
310
  lf_print_table_name (file, entry->parent);
311
  lf_printf (file, ";\n");
312
}
313
 
314
 
315
static void
316
print_goto_switch_table (lf *file,
317
                         gen_entry *table)
318
{
319
  lf_printf (file, "const static void *");
320
  lf_print_table_name (file, table);
321
  lf_printf (file, "[] = {\n");
322
  lf_indent (file, +2);
323
  gen_entry_traverse_tree (file, table,
324
                           0,
325
                           NULL/*start*/,
326
                           print_goto_switch_table_leaf,
327
                           NULL/*end*/,
328
                           NULL/*data*/);
329
  lf_indent (file, -2);
330
  lf_printf (file, "};\n");
331
}
332
 
333
 
334
void print_idecode_switch
335
(lf *file,
336
 gen_entry *table,
337
 const char *result);
338
 
339
static void
340
print_idecode_switch_start (lf *file,
341
                            gen_entry *table,
342
                            int depth,
343
                            void *data)
344
{
345
  /* const char *result = data; */
346
  ASSERT (depth == 0);
347
  ASSERT (table->opcode_rule->gen == switch_gen
348
          || table->opcode_rule->gen == goto_switch_gen
349
          || table->opcode_rule->gen == padded_switch_gen);
350
 
351
  if (table->opcode->is_boolean
352
      || table->opcode_rule->gen == switch_gen
353
      || table->opcode_rule->gen == padded_switch_gen)
354
    {
355
      lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n",
356
                 options.insn_bit_size,
357
                 table->opcode_rule->word_nr,
358
                 i2target (options.hi_bit_nr, table->opcode->first),
359
                 i2target (options.hi_bit_nr, table->opcode->last));
360
      lf_indent (file, +2);
361
      lf_printf (file, "{\n");
362
    }
363
  else if (table->opcode_rule->gen == goto_switch_gen)
364
    {
365
      if (table->parent != NULL
366
          && (table->parent->opcode_rule->gen == switch_gen
367
              || table->parent->opcode_rule->gen == goto_switch_gen
368
              || table->parent->opcode_rule->gen == padded_switch_gen))
369
        {
370
          lf_printf (file, "{\n");
371
          lf_indent (file, +2);
372
        }
373
      print_goto_switch_table (file, table);
374
      lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n",
375
                 options.insn_bit_size,
376
                 table->opcode->word_nr,
377
                 i2target (options.hi_bit_nr, table->opcode->first),
378
                 i2target (options.hi_bit_nr, table->opcode->last));
379
      lf_printf (file, "        < (sizeof (");
380
      lf_print_table_name (file, table);
381
      lf_printf (file, ") / sizeof(void*)));\n");
382
      lf_printf (file, "goto *");
383
      lf_print_table_name (file, table);
384
      lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n",
385
                 options.insn_bit_size,
386
                 table->opcode->word_nr,
387
                 i2target (options.hi_bit_nr, table->opcode->first),
388
                 i2target (options.hi_bit_nr, table->opcode->last));
389
    }
390
  else
391
    {
392
      ASSERT("bad switch" == NULL);
393
    }
394
}
395
 
396
 
397
static void
398
print_idecode_switch_leaf (lf *file,
399
                           gen_entry *entry,
400
                           int depth,
401
                           void *data)
402
{
403
  const char *result = data;
404
  ASSERT (entry->parent != NULL);
405
  ASSERT (depth == 0);
406
  ASSERT (entry->parent->opcode_rule->gen == switch_gen
407
          || entry->parent->opcode_rule->gen == goto_switch_gen
408
          || entry->parent->opcode_rule->gen == padded_switch_gen);
409
  ASSERT (entry->parent->opcode);
410
 
411
  /* skip over any instructions combined into another entry */
412
  if (entry->combined_parent != NULL)
413
    return;
414
 
415
  if (entry->parent->opcode->is_boolean
416
           && entry->opcode_nr == 0)
417
    {
418
      /* case: boolean false target */
419
      lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant);
420
    }
421
  else if (entry->parent->opcode->is_boolean
422
           && entry->opcode_nr != 0)
423
    {
424
      /* case: boolean true case */
425
      lf_printf (file, "default:\n");
426
    }
427
  else if (entry->parent->opcode_rule->gen == switch_gen
428
           || entry->parent->opcode_rule->gen == padded_switch_gen)
429
    {
430
      /* case: <opcode-nr> - switch */
431
      gen_entry *cob;
432
      for (cob = entry; cob != NULL; cob = cob->combined_next)
433
        lf_printf (file, "case %d:\n", cob->opcode_nr);
434
    }
435
  else if (entry->parent->opcode_rule->gen == goto_switch_gen)
436
    {
437
      /* case: <opcode-nr> - goto-switch */
438
      print_goto_switch_name (file, entry);
439
      lf_printf (file, ":\n");
440
    }
441
  else
442
    {
443
      ERROR ("bad switch");
444
    }
445
  lf_printf (file, "  {\n");
446
  lf_indent (file, +4);
447
  {
448
    if (entry->opcode == NULL)
449
      {
450
        /* switch calling leaf */
451
        ASSERT (entry->nr_insns == 1);
452
        print_idecode_ifetch (file, entry->nr_prefetched_words,
453
                              entry->insns->semantic->nr_prefetched_words);
454
        switch (options.gen.code)
455
          {
456
          case generate_jumps:
457
            lf_printf (file, "goto ");
458
            break;
459
          case generate_calls:
460
            lf_printf (file, "%s", result);
461
            break;
462
          }
463
        print_function_name (file,
464
                             entry->insns->insn->name,
465
                             entry->insns->insn->format_name,
466
                             NULL,
467
                             entry->expanded_bits,
468
                             (options.gen.icache
469
                              ? function_name_prefix_icache
470
                              : function_name_prefix_semantics));
471
        if (options.gen.code == generate_calls)
472
          {
473
            lf_printf (file, " (");
474
            print_semantic_function_actual (file, entry->insns->semantic->nr_prefetched_words);
475
            lf_printf (file, ")");
476
          }
477
        lf_printf (file, ";\n");
478
      }
479
    else if (entry->opcode_rule->gen == switch_gen
480
             || entry->opcode_rule->gen == goto_switch_gen
481
             || entry->opcode_rule->gen == padded_switch_gen)
482
      {
483
        /* switch calling switch */
484
        lf_printf (file, "{\n");
485
        lf_indent (file, +2);
486
        print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
487
                              entry->nr_prefetched_words);
488
        print_idecode_switch (file, entry, result);
489
        lf_indent (file, -2);
490
        lf_printf (file, "}\n");
491
      }
492
    else
493
      {
494
        /* switch looking up a table */
495
        lf_printf (file, "{\n");
496
        lf_indent (file, +2);
497
        print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
498
                              entry->nr_prefetched_words);
499
        print_idecode_table (file, entry, result);
500
        lf_indent (file, -2);
501
        lf_printf (file, "}\n");
502
      }
503
    if (entry->parent->opcode->is_boolean
504
        || entry->parent->opcode_rule->gen == switch_gen
505
        || entry->parent->opcode_rule->gen == padded_switch_gen)
506
      {
507
        lf_printf (file, "break;\n");
508
      }
509
    else if (entry->parent->opcode_rule->gen == goto_switch_gen)
510
      {
511
        print_goto_switch_break(file, entry);
512
      }
513
    else
514
      {
515
        ERROR ("bad switch");
516
      }
517
  }
518
  lf_indent (file, -4);
519
  lf_printf (file, "  }\n");
520
}
521
 
522
 
523
static void
524
print_idecode_switch_illegal (lf *file,
525
                              const char *result)
526
{
527
  lf_indent (file, +2);
528
  print_idecode_invalid (file, result, invalid_illegal);
529
  lf_printf (file, "break;\n");
530
  lf_indent (file, -2);
531
}
532
 
533
static void
534
print_idecode_switch_end (lf *file,
535
                          gen_entry *table,
536
                          int depth,
537
                          void *data)
538
{
539
  const char *result = data;
540
  ASSERT (depth == 0);
541
  ASSERT (table->opcode_rule->gen == switch_gen
542
          || table->opcode_rule->gen == goto_switch_gen
543
          || table->opcode_rule->gen == padded_switch_gen);
544
  ASSERT (table->opcode);
545
 
546
  if (table->opcode->is_boolean)
547
    {
548
      lf_printf (file, "}\n");
549
      lf_indent (file, -2);
550
    }
551
  else if (table->opcode_rule->gen == switch_gen
552
           || table->opcode_rule->gen == padded_switch_gen)
553
    {
554
      lf_printf (file, "default:\n");
555
      lf_indent (file, +2);
556
      if (table->nr_entries == table->opcode->nr_opcodes)
557
        {
558
          print_sim_engine_abort (file, "Internal error - bad switch generated");
559
          lf_printf (file, "%sNULL_CIA;\n", result);
560
          lf_printf (file, "break;\n");
561
        }
562
      else
563
        {
564
          print_idecode_switch_illegal (file, result);
565
        }
566
      lf_indent (file, -2);
567
      lf_printf (file, "}\n");
568
      lf_indent (file, -2);
569
    }
570
  else if (table->opcode_rule->gen == goto_switch_gen)
571
    {
572
      lf_printf (file, "illegal_");
573
      lf_print_table_name (file, table);
574
      lf_printf (file, ":\n");
575
      print_idecode_invalid (file, result, invalid_illegal);
576
      lf_printf (file, "break_");
577
      lf_print_table_name(file, table);
578
      lf_printf (file, ":;\n");
579
      if (table->parent != NULL
580
          && (table->parent->opcode_rule->gen == switch_gen
581
              || table->parent->opcode_rule->gen == goto_switch_gen
582
              || table->parent->opcode_rule->gen == padded_switch_gen))
583
        {
584
          lf_indent (file, -2);
585
          lf_printf (file, "}\n");
586
        }
587
    }
588
  else
589
    {
590
      ERROR ("bad switch");
591
    }
592
}
593
 
594
 
595
void
596
print_idecode_switch (lf *file,
597
                      gen_entry *table,
598
                      const char *result)
599
{
600
  gen_entry_traverse_tree (file, table,
601
                           0,
602
                           print_idecode_switch_start,
603
                           print_idecode_switch_leaf,
604
                           print_idecode_switch_end,
605
                           (void*)result);
606
}
607
 
608
 
609
static void
610
print_idecode_switch_function_header (lf *file,
611
                                      gen_entry *table,
612
                                      int is_function_definition,
613
                                      int nr_prefetched_words)
614
{
615
  lf_printf (file, "\n");
616
  if (options.gen.code == generate_calls)
617
    {
618
      lf_printf (file, "static ");
619
      if (options.gen.icache)
620
        {
621
          lf_printf (file, "idecode_semantic *");
622
        }
623
      else
624
        {
625
          lf_printf (file, "unsigned_word");
626
        }
627
      if (is_function_definition)
628
        {
629
          lf_printf (file, "\n");
630
        }
631
      else
632
        {
633
          lf_printf (file, " ");
634
        }
635
      lf_print_table_name (file, table);
636
      lf_printf (file, "\n(");
637
      print_icache_function_formal (file, nr_prefetched_words);
638
      lf_printf (file, ")");
639
      if (!is_function_definition)
640
        {
641
          lf_printf (file, ";");
642
        }
643
      lf_printf (file, "\n");
644
    }
645
  if (options.gen.code == generate_jumps && is_function_definition)
646
    {
647
      lf_indent (file, -1);
648
      lf_print_table_name (file, table);
649
      lf_printf (file, ":\n");
650
      lf_indent (file, +1);
651
    }
652
}
653
 
654
 
655
static void
656
idecode_declare_if_switch (lf *file,
657
                           gen_entry *table,
658
                           int depth,
659
                           void *data)
660
{
661
  if ((table->opcode_rule->gen == switch_gen
662
       || table->opcode_rule->gen == goto_switch_gen
663
       || table->opcode_rule->gen == padded_switch_gen)
664
      && table->parent != NULL /* don't declare the top one yet */
665
      && table->parent->opcode_rule->gen == array_gen)
666
    {
667
      print_idecode_switch_function_header (file,
668
                                            table,
669
                                            0/*isnt function definition*/,
670
                                            0);
671
    }
672
}
673
 
674
 
675
static void
676
idecode_expand_if_switch (lf *file,
677
                          gen_entry *table,
678
                          int depth,
679
                          void *data)
680
{
681
  if ((table->opcode_rule->gen == switch_gen
682
       || table->opcode_rule->gen == goto_switch_gen
683
       || table->opcode_rule->gen == padded_switch_gen)
684
      && table->parent != NULL /* don't expand the top one yet */
685
      && table->parent->opcode_rule->gen == array_gen)
686
    {
687
      print_idecode_switch_function_header(file,
688
                                           table,
689
                                           1/*is function definition*/,
690
                                           0);
691
      if (options.gen.code == generate_calls)
692
        {
693
          lf_printf (file, "{\n");
694
          lf_indent (file, +2);
695
        }
696
      print_idecode_switch(file, table, "return");
697
      if (options.gen.code == generate_calls)
698
        {
699
          lf_indent (file, -2);
700
          lf_printf (file, "}\n");
701
        }
702
    }
703
}
704
 
705
 
706
/****************************************************************/
707
 
708
 
709
void
710
print_idecode_lookups (lf *file,
711
                       gen_entry *table,
712
                       cache_entry *cache_rules)
713
{
714
  int depth;
715
 
716
  /* output switch function declarations where needed by tables */
717
  gen_entry_traverse_tree (file, table,
718
                           1,
719
                           idecode_declare_if_switch, /* START */
720
                           NULL, NULL,
721
                           NULL);
722
 
723
  /* output tables where needed */
724
  for (depth = gen_entry_depth (table);
725
       depth > 0;
726
       depth--)
727
    {
728
      gen_entry_traverse_tree (file, table,
729
                               1-depth,
730
                               print_idecode_table_start,
731
                               print_idecode_table_leaf,
732
                               print_idecode_table_end,
733
                               NULL);
734
    }
735
 
736
  /* output switch functions where needed */
737
  gen_entry_traverse_tree (file, table,
738
                            1,
739
                            idecode_expand_if_switch, /* START */
740
                            NULL, NULL,
741
                            NULL);
742
}
743
 
744
 
745
void
746
print_idecode_body (lf *file,
747
                    gen_entry *table,
748
                    const char *result)
749
{
750
  if (table->opcode_rule->gen == switch_gen
751
      || table->opcode_rule->gen == goto_switch_gen
752
      || table->opcode_rule->gen == padded_switch_gen)
753
    {
754
      print_idecode_switch (file, table, result);
755
    }
756
  else
757
    {
758
      print_idecode_table (file, table, result);
759
    }
760
}
761
 
762
 
763
/****************************************************************/
764
 
765
#if 0
766
static void
767
print_jump (lf *file,
768
            int is_tail)
769
{
770
  if (is_tail)
771
    {
772
      lf_putstr (file, "if (keep_running != NULL && !*keep_running)\n");
773
      lf_putstr (file, "  cpu_halt(cpu, nia, was_continuing, 0/*na*/);\n");
774
    }
775
 
776
  if (!options.generate_smp)
777
    {
778
      lf_putstr (file, "if (WITH_EVENTS) {\n");
779
      lf_putstr (file, "  if (event_queue_tick(events)) {\n");
780
      lf_putstr (file, "    cpu_set_program_counter(cpu, nia);\n");
781
      lf_putstr (file, "    event_queue_process(events);\n");
782
      lf_putstr (file, "    nia = cpu_get_program_counter(cpu);\n");
783
      lf_putstr (file, "  }\n");
784
      lf_putstr (file, "}\n");
785
    }
786
 
787
  if (options.generate_smp)
788
    {
789
      if (is_tail)
790
        {
791
          lf_putstr (file, "cpu_set_program_counter(cpu, nia);\n");
792
        }
793
      lf_putstr (file, "if (WITH_EVENTS) {\n");
794
      lf_putstr (file, "  current_cpu += 1;\n");
795
      lf_putstr (file, "  if (current_cpu >= nr_cpus) {\n");
796
      lf_putstr (file, "    if (event_queue_tick(events)) {\n");
797
      lf_putstr (file, "      event_queue_process(events);\n");
798
      lf_putstr (file, "    }\n");
799
      lf_putstr (file, "    current_cpu = 0;\n");
800
      lf_putstr (file, "  }\n");
801
      lf_putstr (file, "}\n");
802
      lf_putstr (file, "else {\n");
803
      lf_putstr (file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
804
      lf_putstr (file, "}\n");
805
      lf_putstr (file, "cpu = cpus[current_cpu];\n");
806
      lf_putstr (file, "nia = cpu_get_program_counter(cpu);\n");
807
    }
808
 
809
  if (options.gen.icache)
810
    {
811
      lf_putstr (file, "cache_entry = cpu_icache_entry(cpu, nia);\n");
812
      lf_putstr (file, "if (cache_entry->address == nia) {\n");
813
      lf_putstr (file, "  /* cache hit */\n");
814
      lf_putstr (file, "  goto *cache_entry->semantic;\n");
815
      lf_putstr (file, "}\n");
816
      if (is_tail)
817
        {
818
          lf_putstr (file, "goto cache_miss;\n");
819
        }
820
    }
821
 
822
  if (!options.gen.icache && is_tail)
823
    {
824
      lf_printf (file, "goto idecode;\n");
825
    }
826
 
827
}
828
#endif
829
 
830
 
831
 
832
#if 0
833
static void
834
print_jump_insn (lf *file,
835
                 insn_entry *instruction,
836
                 insn_bits *expanded_bits,
837
                 opcode_field *opcodes,
838
                 cache_entry *cache_rules)
839
{
840
 
841
  /* what we are for the moment */
842
  lf_printf (file, "\n");
843
  print_my_defines (file, expanded_bits, instruction->name);
844
 
845
  /* output the icache entry */
846
  if (options.gen.icache)
847
    {
848
      lf_printf (file, "\n");
849
      lf_indent (file, -1);
850
      print_function_name (file,
851
                           instruction->name,
852
                           expanded_bits,
853
                           function_name_prefix_icache);
854
      lf_printf (file, ":\n");
855
      lf_indent (file, +1);
856
      lf_printf (file, "{\n");
857
      lf_indent (file, +2);
858
      lf_putstr (file, "const unsigned_word cia = nia;\n");
859
      print_itrace (file, instruction, 1/*putting-value-in-cache*/);
860
      print_idecode_validate (file, instruction, opcodes);
861
      lf_printf (file, "\n");
862
      lf_printf (file, "{\n");
863
      lf_indent (file, +2);
864
      print_icache_body (file,
865
                         instruction,
866
                         expanded_bits,
867
                         cache_rules,
868
                         0, /*use_defines*/
869
                         put_values_in_icache);
870
      lf_printf (file, "cache_entry->address = nia;\n");
871
      lf_printf (file, "cache_entry->semantic = &&");
872
      print_function_name (file,
873
                           instruction->name,
874
                           expanded_bits,
875
                           function_name_prefix_semantics);
876
      lf_printf (file, ";\n");
877
      if (options.gen.semantic_icache)
878
        {
879
          print_semantic_body (file,
880
                               instruction,
881
                               expanded_bits,
882
                               opcodes);
883
          print_jump (file, 1/*is-tail*/);
884
        }
885
      else
886
        {
887
          lf_printf (file, "/* goto ");
888
          print_function_name (file,
889
                               instruction->name,
890
                               expanded_bits,
891
                               function_name_prefix_semantics);
892
          lf_printf (file, "; */\n");
893
        }
894
      lf_indent (file, -2);
895
      lf_putstr (file, "}\n");
896
      lf_indent (file, -2);
897
      lf_printf (file, "}\n");
898
    }
899
 
900
  /* print the semantics */
901
  lf_printf (file, "\n");
902
  lf_indent (file, -1);
903
  print_function_name (file,
904
                       instruction->name,
905
                       expanded_bits,
906
                       function_name_prefix_semantics);
907
  lf_printf (file, ":\n");
908
  lf_indent (file, +1);
909
  lf_printf (file, "{\n");
910
  lf_indent (file, +2);
911
  lf_putstr (file, "const unsigned_word cia = nia;\n");
912
  print_icache_body (file,
913
                     instruction,
914
                     expanded_bits,
915
                     cache_rules,
916
                     (options.gen.direct_access
917
                      ? define_variables
918
                      : declare_variables),
919
                     (options.gen.icache
920
                      ? get_values_from_icache
921
                      : do_not_use_icache));
922
  print_semantic_body (file,
923
                       instruction,
924
                       expanded_bits,
925
                       opcodes);
926
  if (options.gen.direct_access)
927
    print_icache_body (file,
928
                       instruction,
929
                       expanded_bits,
930
                       cache_rules,
931
                       undef_variables,
932
                       (options.gen.icache
933
                        ? get_values_from_icache
934
                        : do_not_use_icache));
935
  print_jump (file, 1/*is tail*/);
936
  lf_indent (file, -2);
937
  lf_printf (file, "}\n");
938
}
939
#endif
940
 
941
 
942
#if 0
943
static void
944
print_jump_definition (lf *file,
945
                       gen_entry *entry,
946
                       insn_entry *insn,
947
                       int depth,
948
                       void *data)
949
{
950
  cache_entry *cache_rules = (cache_entry*)data;
951
  if (options.generate_expanded_instructions)
952
    {
953
      ASSERT (entry->nr_insns == 1
954
              && entry->opcode == NULL
955
              && entry->parent != NULL
956
              && entry->parent->opcode != NULL);
957
      ASSERT (entry->nr_insns == 1
958
              && entry->opcode == NULL
959
              && entry->parent != NULL
960
              && entry->parent->opcode != NULL
961
              && entry->parent->opcode_rule != NULL);
962
      print_jump_insn (file,
963
                       entry->insns->words[0]->insn,
964
                       entry->expanded_bits,
965
                       entry->opcode,
966
                       cache_rules);
967
    }
968
  else
969
    {
970
      print_jump_insn (file,
971
                       instruction->words[0]->insn,
972
                       NULL,
973
                       NULL,
974
                       cache_rules);
975
    }
976
}
977
#endif
978
 
979
#if 0
980
static void
981
print_jump_internal_function (lf *file,
982
                              gen_entry *table,
983
                              function_entry *function,
984
                              void *data)
985
{
986
  if (function->is_internal)
987
    {
988
      lf_printf (file, "\n");
989
      lf_print__line_ref (file, function->line);
990
      lf_indent (file, -1);
991
      print_function_name (file,
992
                           function->name,
993
                           NULL,
994
                           (options.gen.icache
995
                            ? function_name_prefix_icache
996
                            : function_name_prefix_semantics));
997
      lf_printf (file, ":\n");
998
      lf_indent (file, +1);
999
      lf_printf (file, "{\n");
1000
      lf_indent (file, +2);
1001
      lf_printf (file, "const unsigned_word cia = nia;\n");
1002
      table_print_code (file, function->code);
1003
      lf_print__internal_ref (file);
1004
      print_sim_engine_abort (file, "Internal function must longjump");
1005
      lf_indent (file, -2);
1006
      lf_printf (file, "}\n");
1007
    }
1008
}
1009
#endif
1010
 
1011
 
1012
 
1013
#if 0
1014
static void
1015
print_jump_until_stop_body(lf *file,
1016
                           insn_table *table,
1017
                           cache_table *cache_rules)
1018
{
1019
  lf_printf (file, "{\n");
1020
  lf_indent (file, +2);
1021
  lf_putstr (file, "jmp_buf halt;\n");
1022
  lf_putstr (file, "jmp_buf restart;\n");
1023
  lf_putstr (file, "sim_cpu *cpu = NULL;\n");
1024
  lf_putstr (file, "unsigned_word nia = -1;\n");
1025
  lf_putstr (file, "instruction_word instruction = 0;\n");
1026
  if ((code & generate_with_icache)) {
1027
    lf_putstr (file, "idecode_cache *cache_entry = NULL;\n");
1028
  }
1029
  if (generate_smp) {
1030
    lf_putstr (file, "int current_cpu = -1;\n");
1031
  }
1032
 
1033
  /* all the switches and tables - they know about jumping */
1034
  print_idecode_lookups(file, table, cache_rules);
1035
 
1036
  /* start the simulation up */
1037
  if ((code & generate_with_icache)) {
1038
    lf_putstr (file, "\n");
1039
    lf_putstr (file, "{\n");
1040
    lf_putstr (file, "  int cpu_nr;\n");
1041
    lf_putstr (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
1042
    lf_putstr (file, "    cpu_flush_icache(cpus[cpu_nr]);\n");
1043
    lf_putstr (file, "}\n");
1044
  }
1045
 
1046
  lf_putstr (file, "\n");
1047
  lf_putstr (file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
1048
 
1049
  lf_putstr (file, "\n");
1050
  lf_putstr (file, "if (setjmp(halt))\n");
1051
  lf_putstr (file, "  return;\n");
1052
 
1053
  lf_putstr (file, "\n");
1054
  lf_putstr (file, "setjmp(restart);\n");
1055
 
1056
  lf_putstr (file, "\n");
1057
  if (!generate_smp) {
1058
    lf_putstr (file, "cpu = cpus[0];\n");
1059
    lf_putstr (file, "nia = cpu_get_program_counter(cpu);\n");
1060
  }
1061
  else {
1062
    lf_putstr (file, "current_cpu = psim_last_cpu(system);\n");
1063
  }
1064
 
1065
  if (!(code & generate_with_icache)) {
1066
    lf_printf (file, "\n");
1067
    lf_indent (file, -1);
1068
    lf_printf (file, "idecode:\n");
1069
    lf_indent (file, +1);
1070
  }
1071
 
1072
  print_jump(file, 0/*is_tail*/);
1073
 
1074
  if ((code & generate_with_icache)) {
1075
    lf_indent (file, -1);
1076
    lf_printf (file, "cache_miss:\n");
1077
    lf_indent (file, +1);
1078
  }
1079
 
1080
  lf_putstr (file, "instruction\n");
1081
  lf_putstr (file, "  = vm_instruction_map_read(cpu_instruction_map(cpu),\n");
1082
  lf_putstr (file, "                            cpu, nia);\n");
1083
  print_idecode_body(file, table, "/*IGORE*/");
1084
 
1085
  /* print out a table of all the internals functions */
1086
  insn_table_traverse_function(table,
1087
                               file, NULL,
1088
                               print_jump_internal_function);
1089
 
1090
 /* print out a table of all the instructions */
1091
  if (generate_expanded_instructions)
1092
    insn_table_traverse_tree(table,
1093
                             file, cache_rules,
1094
                             1,
1095
                             NULL, /* start */
1096
                             print_jump_definition, /* leaf */
1097
                             NULL, /* end */
1098
                             NULL); /* padding */
1099
  else
1100
    insn_table_traverse_insn(table,
1101
                             file, cache_rules,
1102
                             print_jump_definition);
1103
  lf_indent (file, -2);
1104
  lf_printf (file, "}\n");
1105
}
1106
#endif
1107
 
1108
/****************************************************************/
1109
 
1110
 
1111
 
1112
/* Output code to do any final checks on the decoded instruction.
1113
   This includes things like verifying any on decoded fields have the
1114
   correct value and checking that (for floating point) floating point
1115
   hardware isn't disabled */
1116
 
1117
void
1118
print_idecode_validate (lf *file,
1119
                        insn_entry *instruction,
1120
                        insn_opcodes *opcode_paths)
1121
{
1122
  /* Validate: unchecked instruction fields
1123
 
1124
     If any constant fields in the instruction were not checked by the
1125
     idecode tables, output code to check that they have the correct
1126
     value here */
1127
  {
1128
    int nr_checks = 0;
1129
    int word_nr;
1130
    lf_printf (file, "\n");
1131
    lf_indent_suppress (file);
1132
    lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n");
1133
    lf_printf (file, "/* validate: ");
1134
    print_insn_words (file, instruction);
1135
    lf_printf (file, " */\n");
1136
    for (word_nr = 0; word_nr < instruction->nr_words; word_nr++)
1137
      {
1138
        insn_uint check_mask = 0;
1139
        insn_uint check_val = 0;
1140
        insn_word_entry *word = instruction->word[word_nr];
1141
        int bit_nr;
1142
 
1143
        /* form check_mask/check_val containing what needs to be checked
1144
           in the instruction */
1145
        for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
1146
          {
1147
            insn_bit_entry *bit = word->bit[bit_nr];
1148
            insn_field_entry *field = bit->field;
1149
 
1150
            /* Make space for the next bit */
1151
            check_mask <<= 1;
1152
            check_val <<= 1;
1153
 
1154
            /* Only need to validate constant (and reserved)
1155
               bits. Skip any others */
1156
            if (field->type != insn_field_int
1157
                && field->type != insn_field_reserved)
1158
              continue;
1159
 
1160
            /* Look through the list of opcode paths that lead to this
1161
               instruction.  See if any have failed to check the
1162
               relevant bit */
1163
            if (opcode_paths != NULL)
1164
              {
1165
                insn_opcodes *entry;
1166
                for (entry = opcode_paths;
1167
                     entry != NULL;
1168
                     entry = entry->next)
1169
                  {
1170
                    opcode_field *opcode;
1171
                    for (opcode = entry->opcode;
1172
                         opcode != NULL;
1173
                         opcode = opcode->parent)
1174
                      {
1175
                        if (opcode->word_nr == word_nr
1176
                            && opcode->first <= bit_nr
1177
                            && opcode->last >= bit_nr)
1178
                          /* we've decoded on this bit */
1179
                          break;
1180
                      }
1181
                    if (opcode == NULL)
1182
                      /* the bit wasn't decoded on */
1183
                      break;
1184
                  }
1185
                if (entry == NULL)
1186
                  /* all the opcode paths decoded on BIT_NR, no need
1187
                     to check it */
1188
                  continue;
1189
              }
1190
 
1191
            check_mask |= 1;
1192
            check_val |= bit->value;
1193
          }
1194
 
1195
        /* if any bits not checked by opcode tables, output code to check them */
1196
        if (check_mask)
1197
          {
1198
            if (nr_checks == 0)
1199
              {
1200
                lf_printf (file, "if (WITH_RESERVED_BITS)\n");
1201
                lf_printf (file, "  {\n");
1202
                lf_indent (file, +4);
1203
              }
1204
            nr_checks ++;
1205
            if (options.insn_bit_size > 32)
1206
              {
1207
                lf_printf (file, "if ((instruction_%d\n", word_nr);
1208
                lf_printf (file, "     & UNSIGNED64 (0x%08lx%08lx))\n",
1209
                           (unsigned long)(check_mask >> 32),
1210
                           (unsigned long)(check_mask));
1211
                lf_printf (file, "    != UNSIGNED64 (0x%08lx%08lx))\n",
1212
                           (unsigned long)(check_val >> 32),
1213
                           (unsigned long)(check_val));
1214
              }
1215
            else
1216
              {
1217
                lf_printf (file, "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n",
1218
                           word_nr,
1219
                           (unsigned long)(check_mask),
1220
                           (unsigned long)(check_val));
1221
              }
1222
            lf_indent (file, +2);
1223
            print_idecode_invalid (file, "return", invalid_illegal);
1224
            lf_indent (file, -2);
1225
          }
1226
      }
1227
    if (nr_checks > 0)
1228
      {
1229
        lf_indent (file, -4);
1230
        lf_printf (file, "  }\n");
1231
      }
1232
    lf_indent_suppress(file);
1233
    lf_printf (file, "#endif\n");
1234
  }
1235
 
1236
  /* Validate: Floating Point hardware
1237
 
1238
     If the simulator is being built with out floating point hardware
1239
     (different to it being disabled in the MSR) then floating point
1240
     instructions are invalid */
1241
  {
1242
    if (filter_is_member (instruction->flags, "f"))
1243
      {
1244
        lf_printf (file, "\n");
1245
        lf_indent_suppress (file);
1246
        lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\n");
1247
        lf_printf (file, "/* Validate: FP hardware exists */\n");
1248
        lf_printf (file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT) {\n");
1249
        lf_indent (file, +2);
1250
        print_idecode_invalid (file, "return", invalid_illegal);
1251
        lf_indent (file, -2);
1252
        lf_printf (file, "}\n");
1253
        lf_indent_suppress (file);
1254
        lf_printf (file, "#endif\n");
1255
      }
1256
  }
1257
 
1258
  /* Validate: Floating Point available
1259
 
1260
     If floating point is not available, we enter a floating point
1261
     unavailable interrupt into the cache instead of the instruction
1262
     proper.
1263
 
1264
     The PowerPC spec requires a CSI after MSR[FP] is changed and when
1265
     ever a CSI occures we flush the instruction cache. */
1266
 
1267
  {
1268
    if (filter_is_member (instruction->flags, "f"))
1269
      {
1270
        lf_printf (file, "\n");
1271
        lf_indent_suppress (file);
1272
        lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n");
1273
        lf_printf (file, "/* Validate: FP available according to cpu */\n");
1274
        lf_printf (file, "if (!IS_FP_AVAILABLE) {\n");
1275
        lf_indent (file, +2);
1276
        print_idecode_invalid (file, "return",  invalid_fp_unavailable);
1277
        lf_indent (file, -2);
1278
        lf_printf (file, "}\n");
1279
        lf_indent_suppress (file);
1280
        lf_printf (file, "#endif\n");
1281
      }
1282
  }
1283
 
1284
  /* Validate: Validate Instruction in correct slot
1285
 
1286
     Some architectures place restrictions on the slot that an
1287
     instruction can be issued in */
1288
 
1289
  {
1290
    if (filter_is_member (instruction->options, "s")
1291
        || options.gen.slot_verification)
1292
      {
1293
        lf_printf (file, "\n");
1294
        lf_indent_suppress (file);
1295
        lf_printf (file, "#if defined(IS_WRONG_SLOT)\n");
1296
        lf_printf (file, "/* Validate: Instruction issued in correct slot */\n");
1297
        lf_printf (file, "if (IS_WRONG_SLOT) {\n");
1298
        lf_indent (file, +2);
1299
        print_idecode_invalid (file, "return", invalid_wrong_slot);
1300
        lf_indent (file, -2);
1301
        lf_printf (file, "}\n");
1302
        lf_indent_suppress (file);
1303
        lf_printf (file, "#endif\n");
1304
      }
1305
  }
1306
 
1307
}
1308
 
1309
 
1310
/****************************************************************/
1311
 
1312
 
1313
void
1314
print_idecode_issue_function_header (lf *file,
1315
                                     const char *processor,
1316
                                     function_decl_type decl_type,
1317
                                     int nr_prefetched_words)
1318
{
1319
  int indent;
1320
  lf_printf (file, "\n");
1321
  switch (decl_type)
1322
    {
1323
    case is_function_declaration:
1324
      lf_print__function_type_function (file, print_semantic_function_type,
1325
                                        "INLINE_IDECODE",
1326
                                        " ");
1327
      break;
1328
    case is_function_definition:
1329
      lf_print__function_type_function (file, print_semantic_function_type,
1330
                                        "INLINE_IDECODE",
1331
                                        "\n");
1332
      break;
1333
    case is_function_variable:
1334
      print_semantic_function_type (file);
1335
      lf_printf (file, " (*");
1336
      break;
1337
    }
1338
  indent = print_function_name (file,
1339
                                "issue",
1340
                                NULL,
1341
                                processor,
1342
                                NULL,
1343
                                function_name_prefix_idecode);
1344
  switch (decl_type)
1345
    {
1346
    case is_function_definition:
1347
      indent += lf_printf (file, " (");
1348
      break;
1349
    case is_function_declaration:
1350
      lf_putstr (file, "\n(");
1351
      indent = 1;
1352
      break;
1353
    case is_function_variable:
1354
      lf_putstr (file, ")\n(");
1355
      indent = 1;
1356
      break;
1357
    }
1358
  lf_indent (file, +indent);
1359
  print_semantic_function_formal (file, nr_prefetched_words);
1360
  lf_putstr (file, ")");
1361
  lf_indent (file, -indent);
1362
  switch (decl_type)
1363
    {
1364
    case is_function_definition:
1365
      lf_printf (file, "\n");
1366
      break;
1367
    case is_function_declaration:
1368
    case is_function_variable:
1369
      lf_putstr (file, ";\n");
1370
      break;
1371
    }
1372
}
1373
 
1374
 
1375
 
1376
void
1377
print_idecode_globals (lf *file)
1378
{
1379
  lf_printf (file, "enum {\n");
1380
  lf_printf (file, "  /* greater or equal to zero => table */\n");
1381
  lf_printf (file, "  function_entry = -1,\n");
1382
  lf_printf (file, "  boolean_entry = -2,\n");
1383
  lf_printf (file, "};\n");
1384
  lf_printf (file, "\n");
1385
  lf_printf (file, "typedef struct _idecode_table_entry {\n");
1386
  lf_printf (file, "  int shift;\n");
1387
  lf_printf (file, "  unsigned%d mask;\n", options.insn_bit_size);
1388
  lf_printf (file, "  unsigned%d value;\n", options.insn_bit_size);
1389
  lf_printf (file, "  void *function_or_table;\n");
1390
  lf_printf (file, "} idecode_table_entry;\n");
1391
}

powered by: WebSVN 2.1.0

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