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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [ppc/] [gen-idecode.c] - Blame information for rev 309

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

Line No. Rev Author Line
1 227 jeremybenn
/*  This file is part of the program psim.
2
 
3
    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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
 
25
#include "filter.h"
26
 
27
#include "ld-decode.h"
28
#include "ld-cache.h"
29
#include "ld-insn.h"
30
 
31
#include "igen.h"
32
 
33
#include "gen-idecode.h"
34
#include "gen-icache.h"
35
#include "gen-semantics.h"
36
 
37
 
38
 
39
static void
40
lf_print_opcodes(lf *file,
41
                 insn_table *table)
42
{
43
  if (table != NULL) {
44
    while (1) {
45
      ASSERT(table->opcode != NULL);
46
      lf_printf(file, "_%d_%d",
47
                table->opcode->first,
48
                table->opcode->last);
49
      if (table->parent == NULL) break;
50
      lf_printf(file, "__%d", table->opcode_nr);
51
      table = table->parent;
52
    }
53
  }
54
}
55
 
56
/****************************************************************/
57
 
58
 
59
static void
60
lf_print_table_name(lf *file,
61
                    insn_table *table)
62
{
63
  lf_printf(file, "idecode_table");
64
  lf_print_opcodes(file, table);
65
}
66
 
67
 
68
 
69
static void
70
print_idecode_table(lf *file,
71
                    insn_table *entry,
72
                    const char *result)
73
{
74
  lf_printf(file, "/* prime the search */\n");
75
  lf_printf(file, "idecode_table_entry *table = ");
76
  lf_print_table_name(file, entry);
77
  lf_printf(file, ";\n");
78
  lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
79
            i2target(hi_bit_nr, entry->opcode->first),
80
            i2target(hi_bit_nr, entry->opcode->last));
81
  lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
82
 
83
  lf_printf(file, "\n");
84
  lf_printf(file, "/* iterate until a leaf */\n");
85
  lf_printf(file, "while (1) {\n");
86
  lf_printf(file, "  signed shift = table_entry->shift;\n");
87
  lf_printf(file, "if (shift == function_entry) break;\n");
88
  lf_printf(file, "  if (shift >= 0) {\n");
89
  lf_printf(file, "    table = ((idecode_table_entry*)\n");
90
  lf_printf(file, "             table_entry->function_or_table);\n");
91
  lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
92
  lf_printf(file, "              >> shift);\n");
93
  lf_printf(file, "    table_entry = table + opcode;\n");
94
  lf_printf(file, "  }\n");
95
  lf_printf(file, "  else {\n");
96
  lf_printf(file, "    /* must be a boolean */\n");
97
  lf_printf(file, "    ASSERT(table_entry->shift == boolean_entry);\n");
98
  lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
99
  lf_printf(file, "              != table_entry->value);\n");
100
  lf_printf(file, "    table = ((idecode_table_entry*)\n");
101
  lf_printf(file, "             table_entry->function_or_table);\n");
102
  lf_printf(file, "    table_entry = table + opcode;\n");
103
  lf_printf(file, "  }\n");
104
  lf_printf(file, "}\n");
105
 
106
  lf_printf(file, "\n");
107
  lf_printf(file, "/* call the leaf code */\n");
108
  if ((code & generate_jumps)) {
109
    lf_printf(file, "goto *table_entry->function_or_table;\n");
110
  }
111
  else {
112
    lf_printf(file, "%s ", result);
113
    if ((code & generate_with_icache)) {
114
      lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
115
      lf_printf(file, "  (%s));\n", ICACHE_FUNCTION_ACTUAL);
116
    }
117
    else {
118
      lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
119
      lf_printf(file, "  (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
120
    }
121
  }
122
}
123
 
124
 
125
static void
126
print_idecode_table_start(insn_table *table,
127
                          lf *file,
128
                          void *data,
129
                          int depth)
130
{
131
  ASSERT(depth == 0);
132
  /* start of the table */
133
  if (table->opcode_rule->gen == array_gen) {
134
    lf_printf(file, "\n");
135
    lf_printf(file, "static idecode_table_entry ");
136
    lf_print_table_name(file, table);
137
    lf_printf(file, "[] = {\n");
138
  }
139
}
140
 
141
static void
142
print_idecode_table_leaf(insn_table *entry,
143
                         lf *file,
144
                         void *data,
145
                         insn *instruction,
146
                         int depth)
147
{
148
  ASSERT(entry->parent != NULL);
149
  ASSERT(depth == 0);
150
 
151
  /* add an entry to the table */
152
  if (entry->parent->opcode_rule->gen == array_gen) {
153
    lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
154
    if (entry->opcode == NULL) {
155
      /* table leaf entry */
156
      lf_printf(file, "function_entry, 0, 0, ");
157
      if ((code & generate_jumps))
158
        lf_printf(file, "&&");
159
      print_function_name(file,
160
                          entry->insns->file_entry->fields[insn_name],
161
                          entry->expanded_bits,
162
                          ((code & generate_with_icache)
163
                           ? function_name_prefix_icache
164
                           : function_name_prefix_semantics));
165
    }
166
    else if (entry->opcode_rule->gen == switch_gen
167
             || entry->opcode_rule->gen == goto_switch_gen
168
             || entry->opcode_rule->gen == padded_switch_gen) {
169
      /* table calling switch statement */
170
      lf_printf(file, "function_entry, 0, 0, ");
171
      if ((code & generate_jumps))
172
        lf_printf(file, "&&");
173
      lf_print_table_name(file, entry);
174
    }
175
    else if (entry->opcode->is_boolean) {
176
      /* table `calling' boolean table */
177
      lf_printf(file, "boolean_entry, ");
178
      lf_printf(file, "MASK32(%d, %d), ",
179
                i2target(hi_bit_nr, entry->opcode->first),
180
                i2target(hi_bit_nr, entry->opcode->last));
181
      lf_printf(file, "INSERTED32(%d, %d, %d), ",
182
                entry->opcode->boolean_constant,
183
                i2target(hi_bit_nr, entry->opcode->first),
184
                i2target(hi_bit_nr, entry->opcode->last));
185
      lf_print_table_name(file, entry);
186
    }
187
    else {
188
      /* table `calling' another table */
189
      lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1);
190
      lf_printf(file, "MASK32(%d,%d), ",
191
                i2target(hi_bit_nr, entry->opcode->first),
192
                i2target(hi_bit_nr, entry->opcode->last));
193
      lf_printf(file, "0, ");
194
      lf_print_table_name(file, entry);
195
    }
196
    lf_printf(file, " },\n");
197
  }
198
}
199
 
200
static void
201
print_idecode_table_end(insn_table *table,
202
                        lf *file,
203
                        void *data,
204
                        int depth)
205
{
206
  ASSERT(depth == 0);
207
  if (table->opcode_rule->gen == array_gen) {
208
    lf_printf(file, "};\n");
209
  }
210
}
211
 
212
static void
213
print_idecode_table_padding(insn_table *table,
214
                            lf *file,
215
                            void *data,
216
                            int depth,
217
                            int opcode_nr)
218
{
219
  ASSERT(depth == 0);
220
  if (table->opcode_rule->gen == array_gen) {
221
    lf_printf(file, "  /*%d*/ { function_entry, 0, 0, ", opcode_nr);
222
    if ((code & generate_jumps))
223
      lf_printf(file, "&&");
224
    lf_printf(file, "%s_illegal },\n",
225
              ((code & generate_with_icache) ? "icache" : "semantic"));
226
  }
227
}
228
 
229
 
230
/****************************************************************/
231
 
232
 
233
static void
234
print_goto_switch_name(lf *file,
235
                       insn_table *entry)
236
{
237
  lf_printf(file, "case_");
238
  if (entry->opcode == NULL)
239
    print_function_name(file,
240
                        entry->insns->file_entry->fields[insn_name],
241
                        entry->expanded_bits,
242
                        ((code & generate_with_icache)
243
                         ? function_name_prefix_icache
244
                         : function_name_prefix_semantics));
245
  else
246
    lf_print_table_name(file, entry);
247
}
248
 
249
static void
250
print_goto_switch_table_leaf(insn_table *entry,
251
                             lf *file,
252
                             void *data,
253
                             insn *instruction,
254
                             int depth)
255
{
256
  ASSERT(entry->parent != NULL);
257
  ASSERT(depth == 0);
258
  ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
259
  ASSERT(entry->parent->opcode);
260
 
261
  lf_printf(file, "&&");
262
  print_goto_switch_name(file, entry);
263
  lf_printf(file, ",\n");
264
}
265
 
266
static void
267
print_goto_switch_table_padding(insn_table *table,
268
                                lf *file,
269
                                void *data,
270
                                int depth,
271
                                int opcode_nr)
272
{
273
  ASSERT(depth == 0);
274
  ASSERT(table->opcode_rule->gen == goto_switch_gen);
275
 
276
  lf_printf(file, "&&illegal_");
277
  lf_print_table_name(file, table);
278
  lf_printf(file, ",\n");
279
}
280
 
281
static void
282
print_goto_switch_break(lf *file,
283
                        insn_table *entry)
284
{
285
  lf_printf(file, "goto break_");
286
  lf_print_table_name(file, entry->parent);
287
  lf_printf(file, ";\n");
288
}
289
 
290
 
291
static void
292
print_goto_switch_table(lf *file,
293
                        insn_table *table)
294
{
295
  lf_printf(file, "const static void *");
296
  lf_print_table_name(file, table);
297
  lf_printf(file, "[] = {\n");
298
  lf_indent(file, +2);
299
  insn_table_traverse_tree(table,
300
                           file, NULL/*data*/,
301
                           0,
302
                           NULL/*start*/,
303
                           print_goto_switch_table_leaf,
304
                           NULL/*end*/,
305
                           print_goto_switch_table_padding);
306
  lf_indent(file, -2);
307
  lf_printf(file, "};\n");
308
}
309
 
310
 
311
void print_idecode_switch
312
(lf *file,
313
 insn_table *table,
314
 const char *result);
315
 
316
static void
317
idecode_switch_start(insn_table *table,
318
                     lf *file,
319
                     void *data,
320
                     int depth)
321
{
322
  /* const char *result = data; */
323
  ASSERT(depth == 0);
324
  ASSERT(table->opcode_rule->gen == switch_gen
325
         || table->opcode_rule->gen == goto_switch_gen
326
         || table->opcode_rule->gen == padded_switch_gen);
327
 
328
  if (table->opcode->is_boolean
329
      || table->opcode_rule->gen == switch_gen
330
         || table->opcode_rule->gen == padded_switch_gen) {
331
    lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
332
              i2target(hi_bit_nr, table->opcode->first),
333
              i2target(hi_bit_nr, table->opcode->last));
334
  }
335
  else if (table->opcode_rule->gen == goto_switch_gen) {
336
    if (table->parent != NULL
337
        && (table->parent->opcode_rule->gen == switch_gen
338
            || table->parent->opcode_rule->gen == goto_switch_gen
339
            || table->parent->opcode_rule->gen == padded_switch_gen)) {
340
      lf_printf(file, "{\n");
341
      lf_indent(file, +2);
342
    }
343
    print_goto_switch_table(file, table);
344
    lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
345
              i2target(hi_bit_nr, table->opcode->first),
346
              i2target(hi_bit_nr, table->opcode->last));
347
    lf_printf(file, "       < (sizeof(");
348
    lf_print_table_name(file, table);
349
    lf_printf(file, ") / sizeof(void*)));\n");
350
    lf_printf(file, "goto *");
351
    lf_print_table_name(file, table);
352
    lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
353
              i2target(hi_bit_nr, table->opcode->first),
354
              i2target(hi_bit_nr, table->opcode->last));
355
  }
356
  else {
357
    ASSERT("bad switch" == NULL);
358
  }
359
}
360
 
361
 
362
static void
363
idecode_switch_leaf(insn_table *entry,
364
                    lf *file,
365
                    void *data,
366
                    insn *instruction,
367
                    int depth)
368
{
369
  const char *result = data;
370
  ASSERT(entry->parent != NULL);
371
  ASSERT(depth == 0);
372
  ASSERT(entry->parent->opcode_rule->gen == switch_gen
373
         || entry->parent->opcode_rule->gen == goto_switch_gen
374
         || entry->parent->opcode_rule->gen == padded_switch_gen);
375
  ASSERT(entry->parent->opcode);
376
 
377
  if (entry->parent->opcode->is_boolean
378
      && entry->opcode_nr == 0) {
379
    /* boolean false target */
380
    lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
381
  }
382
  else if (entry->parent->opcode->is_boolean
383
           && entry->opcode_nr != 0) {
384
    /* boolean true case */
385
    lf_printf(file, "default:\n");
386
  }
387
  else if (entry->parent->opcode_rule->gen == switch_gen
388
           || entry->parent->opcode_rule->gen == padded_switch_gen) {
389
    /* normal goto */
390
    lf_printf(file, "case %d:\n", entry->opcode_nr);
391
  }
392
  else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
393
    /* lf_indent(file, -1); */
394
    print_goto_switch_name(file, entry);
395
    lf_printf(file, ":\n");
396
    /* lf_indent(file, +1); */
397
  }
398
  else {
399
    ASSERT("bad switch" == NULL);
400
  }
401
  lf_indent(file, +2);
402
  {
403
    if (entry->opcode == NULL) {
404
      /* switch calling leaf */
405
      if ((code & generate_jumps))
406
        lf_printf(file, "goto ");
407
      if ((code & generate_calls))
408
        lf_printf(file, "%s ", result);
409
      print_function_name(file,
410
                          entry->insns->file_entry->fields[insn_name],
411
                          entry->expanded_bits,
412
                          ((code & generate_with_icache)
413
                           ? function_name_prefix_icache
414
                           : function_name_prefix_semantics));
415
      if ((code & generate_calls))
416
        lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL);
417
      lf_printf(file, ";\n");
418
    }
419
    else if (entry->opcode_rule->gen == switch_gen
420
             || entry->opcode_rule->gen == goto_switch_gen
421
             || entry->opcode_rule->gen == padded_switch_gen) {
422
      /* switch calling switch */
423
      print_idecode_switch(file, entry, result);
424
    }
425
    else {
426
      /* switch looking up a table */
427
      lf_printf(file, "{\n");
428
      lf_indent(file, -2);
429
      print_idecode_table(file, entry, result);
430
      lf_indent(file, -2);
431
      lf_printf(file, "}\n");
432
    }
433
    if (entry->parent->opcode->is_boolean
434
        || entry->parent->opcode_rule->gen == switch_gen
435
        || entry->parent->opcode_rule->gen == padded_switch_gen) {
436
      lf_printf(file, "break;\n");
437
    }
438
    else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
439
      print_goto_switch_break(file, entry);
440
    }
441
    else {
442
      ASSERT("bad switch" == NULL);
443
    }
444
  }
445
  lf_indent(file, -2);
446
}
447
 
448
 
449
static void
450
print_idecode_switch_illegal(lf *file,
451
                             const char *result)
452
{
453
  lf_indent(file, +2);
454
  print_idecode_illegal(file, result);
455
  lf_printf(file, "break;\n");
456
  lf_indent(file, -2);
457
}
458
 
459
static void
460
idecode_switch_end(insn_table *table,
461
                   lf *file,
462
                   void *data,
463
                   int depth)
464
{
465
  const char *result = data;
466
  ASSERT(depth == 0);
467
  ASSERT(table->opcode_rule->gen == switch_gen
468
         || table->opcode_rule->gen == goto_switch_gen
469
         || table->opcode_rule->gen == padded_switch_gen);
470
  ASSERT(table->opcode);
471
 
472
  if (table->opcode->is_boolean) {
473
    lf_printf(file, "}\n");
474
  }
475
  else if (table->opcode_rule->gen == switch_gen
476
           || table->opcode_rule->gen == padded_switch_gen) {
477
    lf_printf(file, "default:\n");
478
    switch (table->opcode_rule->gen) {
479
    case switch_gen:
480
      print_idecode_switch_illegal(file, result);
481
      break;
482
    case padded_switch_gen:
483
      lf_printf(file, "  error(\"Internal error - bad switch generated\\n\");\n");
484
      lf_printf(file, "  break;\n");
485
      break;
486
    default:
487
      ASSERT("bad switch" == NULL);
488
    }
489
    lf_printf(file, "}\n");
490
  }
491
  else if (table->opcode_rule->gen == goto_switch_gen) {
492
    lf_printf(file, "illegal_");
493
    lf_print_table_name(file, table);
494
    lf_printf(file, ":\n");
495
    print_idecode_illegal(file, result);
496
    lf_printf(file, "break_");
497
    lf_print_table_name(file, table);
498
    lf_printf(file, ":;\n");
499
    if (table->parent != NULL
500
        && (table->parent->opcode_rule->gen == switch_gen
501
            || table->parent->opcode_rule->gen == goto_switch_gen
502
            || table->parent->opcode_rule->gen == padded_switch_gen)) {
503
      lf_indent(file, -2);
504
      lf_printf(file, "}\n");
505
    }
506
  }
507
  else {
508
    ASSERT("bad switch" == NULL);
509
  }
510
}
511
 
512
static void
513
idecode_switch_padding(insn_table *table,
514
                       lf *file,
515
                       void *data,
516
                       int depth,
517
                       int opcode_nr)
518
{
519
  const char *result = data;
520
  ASSERT(depth == 0);
521
  ASSERT(table->opcode_rule->gen == switch_gen
522
         || table->opcode_rule->gen == goto_switch_gen
523
         || table->opcode_rule->gen == padded_switch_gen);
524
 
525
  switch (table->opcode_rule->gen) {
526
  case switch_gen:
527
    break;
528
  case padded_switch_gen:
529
    lf_printf(file, "case %d:\n", opcode_nr);
530
    print_idecode_switch_illegal(file, result);
531
    break;
532
  case goto_switch_gen:
533
    /* no padding needed */
534
    break;
535
  default:
536
    ASSERT("bad switch" != NULL);
537
  }
538
}
539
 
540
 
541
void
542
print_idecode_switch(lf *file,
543
                     insn_table *table,
544
                     const char *result)
545
{
546
  insn_table_traverse_tree(table,
547
                           file, (void*)result,
548
                           0,
549
                           idecode_switch_start,
550
                           idecode_switch_leaf,
551
                           idecode_switch_end,
552
                           idecode_switch_padding);
553
}
554
 
555
 
556
static void
557
print_idecode_switch_function_header(lf *file,
558
                                     insn_table *table,
559
                                     int is_function_definition)
560
{
561
  lf_printf(file, "\n");
562
  if ((code & generate_calls)) {
563
    lf_printf(file, "static ");
564
    if ((code & generate_with_icache))
565
      lf_printf(file, "idecode_semantic *");
566
    else
567
      lf_printf(file, "unsigned_word");
568
    if (is_function_definition)
569
      lf_printf(file, "\n");
570
    else
571
      lf_printf(file, " ");
572
    lf_print_table_name(file, table);
573
    lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
574
    if (!is_function_definition)
575
      lf_printf(file, ";");
576
    lf_printf(file, "\n");
577
  }
578
  if ((code & generate_jumps) && is_function_definition) {
579
    lf_indent(file, -1);
580
    lf_print_table_name(file, table);
581
    lf_printf(file, ":\n");
582
    lf_indent(file, +1);
583
  }
584
}
585
 
586
 
587
static void
588
idecode_declare_if_switch(insn_table *table,
589
                          lf *file,
590
                          void *data,
591
                          int depth)
592
{
593
  if ((table->opcode_rule->gen == switch_gen
594
       || table->opcode_rule->gen == goto_switch_gen
595
       || table->opcode_rule->gen == padded_switch_gen)
596
      && table->parent != NULL /* don't declare the top one yet */
597
      && table->parent->opcode_rule->gen == array_gen) {
598
    print_idecode_switch_function_header(file,
599
                                         table,
600
                                         0/*isnt function definition*/);
601
  }
602
}
603
 
604
 
605
static void
606
idecode_expand_if_switch(insn_table *table,
607
                         lf *file,
608
                         void *data,
609
                         int depth)
610
{
611
  if ((table->opcode_rule->gen == switch_gen
612
       || table->opcode_rule->gen == goto_switch_gen
613
       || table->opcode_rule->gen == padded_switch_gen)
614
      && table->parent != NULL /* don't expand the top one yet */
615
      && table->parent->opcode_rule->gen == array_gen) {
616
    print_idecode_switch_function_header(file,
617
                                            table,
618
                                            1/*is function definition*/);
619
    if ((code & generate_calls)) {
620
      lf_printf(file, "{\n");
621
      lf_indent(file, +2);
622
    }
623
    print_idecode_switch(file, table, "return");
624
    if ((code & generate_calls)) {
625
      lf_indent(file, -2);
626
      lf_printf(file, "}\n");
627
    }
628
  }
629
}
630
 
631
 
632
/****************************************************************/
633
 
634
 
635
static void
636
print_idecode_lookups(lf *file,
637
                      insn_table *table,
638
                      cache_table *cache_rules)
639
{
640
  int depth;
641
 
642
  /* output switch function declarations where needed by tables */
643
  insn_table_traverse_tree(table,
644
                           file, NULL,
645
                           1,
646
                           idecode_declare_if_switch, /* START */
647
                           NULL, NULL, NULL);
648
 
649
  /* output tables where needed */
650
  for (depth = insn_table_depth(table);
651
       depth > 0;
652
       depth--) {
653
    insn_table_traverse_tree(table,
654
                             file, NULL,
655
                             1-depth,
656
                             print_idecode_table_start,
657
                             print_idecode_table_leaf,
658
                             print_idecode_table_end,
659
                             print_idecode_table_padding);
660
  }
661
 
662
  /* output switch functions where needed */
663
  insn_table_traverse_tree(table,
664
                           file, NULL,
665
                           1,
666
                           idecode_expand_if_switch, /* START */
667
                           NULL, NULL, NULL);
668
}
669
 
670
 
671
static void
672
print_idecode_body(lf *file,
673
                   insn_table *table,
674
                   const char *result)
675
{
676
  if (table->opcode_rule->gen == switch_gen
677
      || table->opcode_rule->gen == goto_switch_gen
678
      || table->opcode_rule->gen == padded_switch_gen)
679
    print_idecode_switch(file, table, result);
680
  else
681
    print_idecode_table(file, table, result);
682
}
683
 
684
 
685
/****************************************************************/
686
 
687
 
688
static void
689
print_run_until_stop_body(lf *file,
690
                          insn_table *table,
691
                          int can_stop)
692
{
693
  /* Output the function to execute real code:
694
 
695
     Unfortunatly, there are multiple cases to consider vis:
696
 
697
     <icache> X <smp> X <events> X <keep-running-flag> X ...
698
 
699
     Consequently this function is written in multiple different ways */
700
 
701
  lf_putstr(file, "{\n");
702
  lf_indent(file, +2);
703
  lf_putstr(file, "jmp_buf halt;\n");
704
  lf_putstr(file, "jmp_buf restart;\n");
705
  if (!generate_smp) {
706
    lf_putstr(file, "cpu *processor = NULL;\n");
707
    lf_putstr(file, "unsigned_word cia = -1;\n");
708
  }
709
  lf_putstr(file, "int last_cpu;\n");
710
  if (generate_smp) {
711
    lf_putstr(file, "int current_cpu;\n");
712
  }
713
 
714
  if ((code & generate_with_icache)) {
715
    lf_putstr(file, "int cpu_nr;\n");
716
    lf_putstr(file, "\n");
717
    lf_putstr(file, "/* flush the icache of a possible break insn */\n");
718
    lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
719
    lf_putstr(file, "  cpu_flush_icache(processors[cpu_nr]);\n");
720
  }
721
 
722
  lf_putstr(file, "\n");
723
  lf_putstr(file, "/* set the halt target initially */\n");
724
  lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n");
725
  lf_putstr(file, "if (setjmp(halt))\n");
726
  lf_putstr(file, "  return;\n");
727
 
728
  lf_putstr(file, "\n");
729
  lf_putstr(file, "/* where were we before the halt? */\n");
730
  lf_putstr(file, "last_cpu = psim_last_cpu(system);\n");
731
 
732
  lf_putstr(file, "\n");
733
  lf_putstr(file, "/* check for need to force event processing first */\n");
734
  lf_putstr(file, "if (WITH_EVENTS) {\n");
735
  lf_putstr(file, "  if (last_cpu == nr_cpus) {\n");
736
  lf_putstr(file, "    /* halted during event processing */\n");
737
  lf_putstr(file, "    event_queue_process(events);\n");
738
  lf_putstr(file, "    last_cpu = -1;\n");
739
  lf_putstr(file, "  }\n");
740
  lf_putstr(file, "  else if (last_cpu == nr_cpus - 1) {\n");
741
  lf_putstr(file, "    /* last cpu did halt */\n");
742
  lf_putstr(file, "    if (event_queue_tick(events)) {\n");
743
  lf_putstr(file, "      event_queue_process(events);\n");
744
  lf_putstr(file, "    }\n");
745
  lf_putstr(file, "    last_cpu = -1;\n");
746
  lf_putstr(file, "  }\n");
747
  lf_putstr(file, "}\n");
748
  lf_putstr(file, "else {\n");
749
  lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n");
750
  lf_putstr(file, "   /* cpu zero is next */\n");
751
  lf_putstr(file, "   last_cpu = -1;\n");
752
  lf_putstr(file, "}\n");
753
 
754
  lf_putstr(file, "\n");
755
  lf_putstr(file, "/* have ensured that the event queue can not be first */\n");
756
  lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n");
757
 
758
  if (!generate_smp) {
759
 
760
    lf_putstr(file, "\n\
761
/* CASE 1: NO SMP (with or with out instruction cache).\n\
762
\n\
763
   In this case, we can take advantage of the fact that the current\n\
764
   instruction address does not need to be returned to the cpu object\n\
765
   after every execution of an instruction.  Instead it only needs to\n\
766
   be saved when either A. the main loop exits or B. A cpu-halt or\n\
767
   cpu-restart call forces the loop to be re-enered.  The later\n\
768
   functions always save the current cpu instruction address.\n\
769
\n\
770
   Two subcases also exist that with and that without an instruction\n\
771
   cache.\n\
772
\n\
773
   An additional complexity is the need to ensure that a 1:1 ratio\n\
774
   is maintained between the execution of an instruction and the\n\
775
   incrementing of the simulation clock */");
776
 
777
    lf_putstr(file, "\n");
778
 
779
    lf_putstr(file, "\n");
780
    lf_putstr(file, "/* now add restart target as ready to run */\n");
781
    lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
782
    lf_putstr(file, "if (setjmp(restart)) {\n");
783
    lf_putstr(file, "  if (WITH_EVENTS) {\n");
784
    lf_putstr(file, "    /* when restart, cpu must have been last, clock next */\n");
785
    lf_putstr(file, "    if (event_queue_tick(events)) {\n");
786
    lf_putstr(file, "      event_queue_process(events);\n");
787
    lf_putstr(file, "    }\n");
788
    lf_putstr(file, "  }\n");
789
    lf_putstr(file, "}\n");
790
 
791
    lf_putstr(file, "\n");
792
    lf_putstr(file, "/* prime the main loop */\n");
793
    lf_putstr(file, "processor = processors[0];\n");
794
    lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
795
 
796
    lf_putstr(file, "\n");
797
    lf_putstr(file, "while (1) {\n");
798
    lf_indent(file, +2);
799
 
800
    if (!(code & generate_with_icache)) {
801
      lf_putstr(file, "instruction_word instruction =\n");
802
      lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
803
      lf_putstr(file, "\n");
804
      print_idecode_body(file, table, "cia =");;
805
    }
806
 
807
    if ((code & generate_with_icache)) {
808
      lf_putstr(file, "idecode_cache *cache_entry =\n");
809
      lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
810
      lf_putstr(file, "if (cache_entry->address == cia) {\n");
811
      lf_putstr(file, "  /* cache hit */\n");
812
      lf_putstr(file, "  idecode_semantic *const semantic = cache_entry->semantic;\n");
813
      lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
814
      /* tail */
815
      if (can_stop) {
816
        lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
817
        lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
818
      }
819
      lf_putstr(file, "}\n");
820
      lf_putstr(file, "else {\n");
821
      lf_putstr(file, "  /* cache miss */\n");
822
      if (!(code & generate_with_semantic_icache)) {
823
        lf_indent(file, +2);
824
        lf_putstr(file, "idecode_semantic *semantic;\n");
825
        lf_indent(file, -2);
826
      }
827
      lf_putstr(file, "  instruction_word instruction =\n");
828
      lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
829
      lf_putstr(file, "  if (WITH_MON != 0)\n");
830
      lf_putstr(file, "    mon_event(mon_event_icache_miss, processor, cia);\n");
831
      if ((code & generate_with_semantic_icache)) {
832
        lf_putstr(file, "{\n");
833
        lf_indent(file, +2);
834
        print_idecode_body(file, table, "cia =");
835
        lf_indent(file, -2);
836
        lf_putstr(file, "}\n");
837
      }
838
      else {
839
        print_idecode_body(file, table, "semantic =");
840
        lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
841
      }
842
      lf_putstr(file, "}\n");
843
    }
844
 
845
    /* events */
846
    lf_putstr(file, "\n");
847
    lf_putstr(file, "/* process any events */\n");
848
    lf_putstr(file, "if (WITH_EVENTS) {\n");
849
    lf_putstr(file, "  if (event_queue_tick(events)) {\n");
850
    lf_putstr(file, "    cpu_set_program_counter(processor, cia);\n");
851
    lf_putstr(file, "    event_queue_process(events);\n");
852
    lf_putstr(file, "    cia = cpu_get_program_counter(processor);\n");
853
    lf_putstr(file, "  }\n");
854
    lf_putstr(file, "}\n");
855
 
856
    /* tail */
857
    if (can_stop) {
858
      lf_putstr(file, "\n");
859
      lf_putstr(file, "/* abort if necessary */\n");
860
      lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
861
      lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*not important*/);\n");
862
    }
863
 
864
    lf_indent(file, -2);
865
    lf_putstr(file, "}\n");
866
  }
867
 
868
  if (generate_smp) {
869
 
870
    lf_putstr(file, "\n\
871
/* CASE 2: SMP (With or without ICACHE)\n\
872
\n\
873
   The complexity here comes from needing to correctly restart the\n\
874
   system when it is aborted.  In particular if cpu0 requests a\n\
875
   restart, the next cpu is still cpu1.  Cpu0 being restarted after\n\
876
   all the other CPU's and the event queue have been processed */");
877
 
878
    lf_putstr(file, "\n");
879
 
880
    lf_putstr(file, "\n");
881
    lf_putstr(file, "/* now establish the restart target */\n");
882
    lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
883
    lf_putstr(file, "if (setjmp(restart)) {\n");
884
    lf_putstr(file, "  current_cpu = psim_last_cpu(system);\n");
885
    lf_putstr(file, "  ASSERT(current_cpu >= 0 && current_cpu < nr_cpus);\n");
886
    lf_putstr(file, "}\n");
887
    lf_putstr(file, "else {\n");
888
    lf_putstr(file, "  current_cpu = last_cpu;\n");
889
    lf_putstr(file, "  ASSERT(current_cpu >= -1 && current_cpu < nr_cpus);\n");
890
    lf_putstr(file, "}\n");
891
 
892
 
893
    lf_putstr(file, "\n");
894
    lf_putstr(file, "while (1) {\n");
895
    lf_indent(file, +2);
896
 
897
    lf_putstr(file, "\n");
898
    lf_putstr(file, "if (WITH_EVENTS) {\n");
899
    lf_putstr(file, "  current_cpu += 1;\n");
900
    lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
901
    lf_putstr(file, "    if (event_queue_tick(events)) {\n");
902
    lf_putstr(file, "      event_queue_process(events);\n");
903
    lf_putstr(file, "    }\n");
904
    lf_putstr(file, "    current_cpu = 0;\n");
905
    lf_putstr(file, "  }\n");
906
    lf_putstr(file, "}\n");
907
    lf_putstr(file, "else {\n");
908
    lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
909
    lf_putstr(file, "}\n");
910
 
911
    lf_putstr(file, "\n");
912
    lf_putstr(file, "{\n");
913
    lf_indent(file, +2);
914
    lf_putstr(file, "cpu *processor = processors[current_cpu];\n");
915
    lf_putstr(file, "unsigned_word cia =\n");
916
    lf_putstr(file, "  cpu_get_program_counter(processor);\n");
917
 
918
    if (!(code & generate_with_icache)) {
919
      lf_putstr(file, "instruction_word instruction =\n");
920
      lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
921
      print_idecode_body(file, table, "cia =");
922
      if (can_stop) {
923
        lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
924
        lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
925
      }
926
      lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
927
    }
928
 
929
    if ((code & generate_with_icache)) {
930
      lf_putstr(file, "idecode_cache *cache_entry =\n");
931
      lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
932
      lf_putstr(file, "\n");
933
      lf_putstr(file, "if (cache_entry->address == cia) {\n");
934
      {
935
        lf_indent(file, +2);
936
        lf_putstr(file, "\n");
937
        lf_putstr(file, "/* cache hit */\n");
938
        lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
939
        lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
940
        /* tail */
941
        if (can_stop) {
942
          lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
943
          lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
944
        }
945
        lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
946
        lf_putstr(file, "\n");
947
        lf_indent(file, -2);
948
      }
949
      lf_putstr(file, "}\n");
950
      lf_putstr(file, "else {\n");
951
      {
952
        lf_indent(file, +2);
953
        lf_putstr(file, "\n");
954
        lf_putstr(file, "/* cache miss */\n");
955
        if (!(code & generate_with_semantic_icache)) {
956
          lf_putstr(file, "idecode_semantic *semantic;\n");
957
        }
958
        lf_putstr(file, "instruction_word instruction =\n");
959
        lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
960
        lf_putstr(file, "if (WITH_MON != 0)\n");
961
        lf_putstr(file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
962
        if ((code & generate_with_semantic_icache)) {
963
          lf_putstr(file, "{\n");
964
          lf_indent(file, +2);
965
          print_idecode_body(file, table, "cia =");
966
          lf_indent(file, -2);
967
          lf_putstr(file, "}\n");
968
        }
969
        else {
970
          print_idecode_body(file, table, "semantic = ");
971
          lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
972
        }
973
        /* tail */
974
        if (can_stop) {
975
          lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
976
          lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
977
        }
978
        lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
979
        lf_putstr(file, "\n");
980
        lf_indent(file, -2);
981
      }
982
      lf_putstr(file, "}\n");
983
    }
984
 
985
    /* close */
986
    lf_indent(file, -2);
987
    lf_putstr(file, "}\n");
988
 
989
    /* tail */
990
    lf_indent(file, -2);
991
    lf_putstr(file, "}\n");
992
  }
993
 
994
 
995
  lf_indent(file, -2);
996
  lf_putstr(file, "}\n");
997
}
998
 
999
 
1000
/****************************************************************/
1001
 
1002
static void
1003
print_jump(lf *file,
1004
           int is_tail)
1005
{
1006
  if (is_tail) {
1007
    lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
1008
    lf_putstr(file, "  cpu_halt(processor, nia, was_continuing, 0/*na*/);\n");
1009
  }
1010
 
1011
  if (!generate_smp) {
1012
    lf_putstr(file, "if (WITH_EVENTS) {\n");
1013
    lf_putstr(file, "  if (event_queue_tick(events)) {\n");
1014
    lf_putstr(file, "    cpu_set_program_counter(processor, nia);\n");
1015
    lf_putstr(file, "    event_queue_process(events);\n");
1016
    lf_putstr(file, "    nia = cpu_get_program_counter(processor);\n");
1017
    lf_putstr(file, "  }\n");
1018
    lf_putstr(file, "}\n");
1019
  }
1020
 
1021
  if (generate_smp) {
1022
    if (is_tail)
1023
      lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
1024
    lf_putstr(file, "if (WITH_EVENTS) {\n");
1025
    lf_putstr(file, "  current_cpu += 1;\n");
1026
    lf_putstr(file, "  if (current_cpu >= nr_cpus) {\n");
1027
    lf_putstr(file, "    if (event_queue_tick(events)) {\n");
1028
    lf_putstr(file, "      event_queue_process(events);\n");
1029
    lf_putstr(file, "    }\n");
1030
    lf_putstr(file, "    current_cpu = 0;\n");
1031
    lf_putstr(file, "  }\n");
1032
    lf_putstr(file, "}\n");
1033
    lf_putstr(file, "else {\n");
1034
    lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
1035
    lf_putstr(file, "}\n");
1036
    lf_putstr(file, "processor = processors[current_cpu];\n");
1037
    lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
1038
  }
1039
 
1040
  if ((code & generate_with_icache)) {
1041
    lf_putstr(file, "cache_entry = cpu_icache_entry(processor, nia);\n");
1042
    lf_putstr(file, "if (cache_entry->address == nia) {\n");
1043
    lf_putstr(file, "  /* cache hit */\n");
1044
    lf_putstr(file, "  goto *cache_entry->semantic;\n");
1045
    lf_putstr(file, "}\n");
1046
    if (is_tail) {
1047
      lf_putstr(file, "goto cache_miss;\n");
1048
    }
1049
  }
1050
 
1051
  if (!(code & generate_with_icache) && is_tail) {
1052
    lf_printf(file, "goto idecode;\n");
1053
  }
1054
 
1055
}
1056
 
1057
 
1058
 
1059
 
1060
 
1061
static void
1062
print_jump_insn(lf *file,
1063
                insn *instruction,
1064
                insn_bits *expanded_bits,
1065
                opcode_field *opcodes,
1066
                cache_table *cache_rules)
1067
{
1068
 
1069
  /* what we are for the moment */
1070
  lf_printf(file, "\n");
1071
  print_my_defines(file, expanded_bits, instruction->file_entry);
1072
 
1073
  /* output the icache entry */
1074
  if ((code & generate_with_icache)) {
1075
    lf_printf(file, "\n");
1076
    lf_indent(file, -1);
1077
    print_function_name(file,
1078
                        instruction->file_entry->fields[insn_name],
1079
                        expanded_bits,
1080
                        function_name_prefix_icache);
1081
    lf_printf(file, ":\n");
1082
    lf_indent(file, +1);
1083
    lf_printf(file, "{\n");
1084
    lf_indent(file, +2);
1085
    lf_putstr(file, "const unsigned_word cia = nia;\n");
1086
    print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
1087
    print_idecode_validate(file, instruction, opcodes);
1088
    lf_printf(file, "\n");
1089
    lf_printf(file, "{\n");
1090
    lf_indent(file, +2);
1091
    print_icache_body(file,
1092
                      instruction,
1093
                      expanded_bits,
1094
                      cache_rules,
1095
                      0, /*use_defines*/
1096
                      put_values_in_icache);
1097
    lf_printf(file, "cache_entry->address = nia;\n");
1098
    lf_printf(file, "cache_entry->semantic = &&");
1099
    print_function_name(file,
1100
                        instruction->file_entry->fields[insn_name],
1101
                        expanded_bits,
1102
                        function_name_prefix_semantics);
1103
    lf_printf(file, ";\n");
1104
    if ((code & generate_with_semantic_icache)) {
1105
      print_semantic_body(file,
1106
                          instruction,
1107
                          expanded_bits,
1108
                          opcodes);
1109
      print_jump(file, 1/*is-tail*/);
1110
    }
1111
    else {
1112
      lf_printf(file, "/* goto ");
1113
      print_function_name(file,
1114
                          instruction->file_entry->fields[insn_name],
1115
                          expanded_bits,
1116
                          function_name_prefix_semantics);
1117
      lf_printf(file, "; */\n");
1118
    }
1119
    lf_indent(file, -2);
1120
    lf_putstr(file, "}\n");
1121
    lf_indent(file, -2);
1122
    lf_printf(file, "}\n");
1123
  }
1124
 
1125
  /* print the semantics */
1126
  lf_printf(file, "\n");
1127
  lf_indent(file, -1);
1128
  print_function_name(file,
1129
                      instruction->file_entry->fields[insn_name],
1130
                      expanded_bits,
1131
                      function_name_prefix_semantics);
1132
  lf_printf(file, ":\n");
1133
  lf_indent(file, +1);
1134
  lf_printf(file, "{\n");
1135
  lf_indent(file, +2);
1136
  lf_putstr(file, "const unsigned_word cia = nia;\n");
1137
  print_icache_body(file,
1138
                    instruction,
1139
                    expanded_bits,
1140
                    cache_rules,
1141
                    ((code & generate_with_direct_access)
1142
                     ? define_variables
1143
                     : declare_variables),
1144
                    ((code & generate_with_icache)
1145
                     ? get_values_from_icache
1146
                     : do_not_use_icache));
1147
  print_semantic_body(file,
1148
                      instruction,
1149
                      expanded_bits,
1150
                      opcodes);
1151
  if (code & generate_with_direct_access)
1152
    print_icache_body(file,
1153
                      instruction,
1154
                      expanded_bits,
1155
                      cache_rules,
1156
                      undef_variables,
1157
                      ((code & generate_with_icache)
1158
                       ? get_values_from_icache
1159
                       : do_not_use_icache));
1160
  print_jump(file, 1/*is tail*/);
1161
  lf_indent(file, -2);
1162
  lf_printf(file, "}\n");
1163
}
1164
 
1165
static void
1166
print_jump_definition(insn_table *entry,
1167
                      lf *file,
1168
                      void *data,
1169
                      insn *instruction,
1170
                      int depth)
1171
{
1172
  cache_table *cache_rules = (cache_table*)data;
1173
  if (generate_expanded_instructions) {
1174
    ASSERT(entry->nr_insn == 1
1175
           && entry->opcode == NULL
1176
           && entry->parent != NULL
1177
           && entry->parent->opcode != NULL);
1178
    ASSERT(entry->nr_insn == 1
1179
           && entry->opcode == NULL
1180
           && entry->parent != NULL
1181
           && entry->parent->opcode != NULL
1182
           && entry->parent->opcode_rule != NULL);
1183
    print_jump_insn(file,
1184
                    entry->insns,
1185
                    entry->expanded_bits,
1186
                    entry->opcode,
1187
                    cache_rules);
1188
  }
1189
  else {
1190
    print_jump_insn(file,
1191
                    instruction,
1192
                    NULL,
1193
                    NULL,
1194
                    cache_rules);
1195
  }
1196
}
1197
 
1198
 
1199
static void
1200
print_jump_internal_function(insn_table *table,
1201
                             lf *file,
1202
                             void *data,
1203
                             table_entry *function)
1204
{
1205
  if (it_is("internal", function->fields[insn_flags])) {
1206
    lf_printf(file, "\n");
1207
    table_entry_print_cpp_line_nr(file, function);
1208
    lf_indent(file, -1);
1209
    print_function_name(file,
1210
                        function->fields[insn_name],
1211
                        NULL,
1212
                        ((code & generate_with_icache)
1213
                         ? function_name_prefix_icache
1214
                         : function_name_prefix_semantics));
1215
    lf_printf(file, ":\n");
1216
    lf_indent(file, +1);
1217
    lf_printf(file, "{\n");
1218
    lf_indent(file, +2);
1219
    lf_printf(file, "const unsigned_word cia = nia;\n");
1220
    lf_print__c_code(file, function->annex);
1221
    lf_print__internal_reference(file);
1222
    lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
1223
    lf_indent(file, -2);
1224
    lf_printf(file, "}\n");
1225
  }
1226
}
1227
 
1228
static void
1229
print_jump_until_stop_body(lf *file,
1230
                           insn_table *table,
1231
                           cache_table *cache_rules,
1232
                           int can_stop)
1233
{
1234
  lf_printf(file, "{\n");
1235
  lf_indent(file, +2);
1236
  if (!can_stop)
1237
    lf_printf(file, "int *keep_running = NULL;\n");
1238
  lf_putstr(file, "jmp_buf halt;\n");
1239
  lf_putstr(file, "jmp_buf restart;\n");
1240
  lf_putstr(file, "cpu *processor = NULL;\n");
1241
  lf_putstr(file, "unsigned_word nia = -1;\n");
1242
  lf_putstr(file, "instruction_word instruction = 0;\n");
1243
  if ((code & generate_with_icache)) {
1244
    lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
1245
  }
1246
  if (generate_smp) {
1247
    lf_putstr(file, "int current_cpu = -1;\n");
1248
  }
1249
 
1250
  /* all the switches and tables - they know about jumping */
1251
  print_idecode_lookups(file, table, cache_rules);
1252
 
1253
  /* start the simulation up */
1254
  if ((code & generate_with_icache)) {
1255
    lf_putstr(file, "\n");
1256
    lf_putstr(file, "{\n");
1257
    lf_putstr(file, "  int cpu_nr;\n");
1258
    lf_putstr(file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
1259
    lf_putstr(file, "    cpu_flush_icache(processors[cpu_nr]);\n");
1260
    lf_putstr(file, "}\n");
1261
  }
1262
 
1263
  lf_putstr(file, "\n");
1264
  lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
1265
 
1266
  lf_putstr(file, "\n");
1267
  lf_putstr(file, "if (setjmp(halt))\n");
1268
  lf_putstr(file, "  return;\n");
1269
 
1270
  lf_putstr(file, "\n");
1271
  lf_putstr(file, "setjmp(restart);\n");
1272
 
1273
  lf_putstr(file, "\n");
1274
  if (!generate_smp) {
1275
    lf_putstr(file, "processor = processors[0];\n");
1276
    lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
1277
  }
1278
  else {
1279
    lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
1280
  }
1281
 
1282
  if (!(code & generate_with_icache)) {
1283
    lf_printf(file, "\n");
1284
    lf_indent(file, -1);
1285
    lf_printf(file, "idecode:\n");
1286
    lf_indent(file, +1);
1287
  }
1288
 
1289
  print_jump(file, 0/*is_tail*/);
1290
 
1291
  if ((code & generate_with_icache)) {
1292
    lf_indent(file, -1);
1293
    lf_printf(file, "cache_miss:\n");
1294
    lf_indent(file, +1);
1295
  }
1296
 
1297
  lf_putstr(file, "instruction\n");
1298
  lf_putstr(file, "  = vm_instruction_map_read(cpu_instruction_map(processor),\n");
1299
  lf_putstr(file, "                            processor, nia);\n");
1300
  print_idecode_body(file, table, "/*IGORE*/");
1301
 
1302
  /* print out a table of all the internals functions */
1303
  insn_table_traverse_function(table,
1304
                               file, NULL,
1305
                               print_jump_internal_function);
1306
 
1307
 /* print out a table of all the instructions */
1308
  if (generate_expanded_instructions)
1309
    insn_table_traverse_tree(table,
1310
                             file, cache_rules,
1311
                             1,
1312
                             NULL, /* start */
1313
                             print_jump_definition, /* leaf */
1314
                             NULL, /* end */
1315
                             NULL); /* padding */
1316
  else
1317
    insn_table_traverse_insn(table,
1318
                             file, cache_rules,
1319
                             print_jump_definition);
1320
  lf_indent(file, -2);
1321
  lf_printf(file, "}\n");
1322
}
1323
 
1324
 
1325
/****************************************************************/
1326
 
1327
 
1328
 
1329
static void
1330
print_idecode_floating_point_unavailable(lf *file)
1331
{
1332
  if ((code & generate_jumps))
1333
    lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic");
1334
  else if ((code & generate_with_icache))
1335
    lf_printf(file, "return icache_floating_point_unavailable(%s);\n",
1336
              ICACHE_FUNCTION_ACTUAL);
1337
  else
1338
    lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
1339
              SEMANTIC_FUNCTION_ACTUAL);
1340
}
1341
 
1342
 
1343
/* Output code to do any final checks on the decoded instruction.
1344
   This includes things like verifying any on decoded fields have the
1345
   correct value and checking that (for floating point) floating point
1346
   hardware isn't disabled */
1347
 
1348
void
1349
print_idecode_validate(lf *file,
1350
                       insn *instruction,
1351
                       opcode_field *opcodes)
1352
{
1353
  /* Validate: unchecked instruction fields
1354
 
1355
     If any constant fields in the instruction were not checked by the
1356
     idecode tables, output code to check that they have the correct
1357
     value here */
1358
  {
1359
    unsigned check_mask = 0;
1360
    unsigned check_val = 0;
1361
    insn_field *field;
1362
    opcode_field *opcode;
1363
 
1364
    /* form check_mask/check_val containing what needs to be checked
1365
       in the instruction */
1366
    for (field = instruction->fields->first;
1367
         field->first < insn_bit_size;
1368
         field = field->next) {
1369
 
1370
      check_mask <<= field->width;
1371
      check_val <<= field->width;
1372
 
1373
      /* is it a constant that could need validating? */
1374
      if (!field->is_int && !field->is_slash)
1375
        continue;
1376
 
1377
      /* has it been checked by a table? */
1378
      for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
1379
        if (field->first >= opcode->first
1380
            && field->last <= opcode->last)
1381
          break;
1382
      }
1383
      if (opcode != NULL)
1384
        continue;
1385
 
1386
      check_mask |= (1 << field->width)-1;
1387
      check_val |= field->val_int;
1388
    }
1389
 
1390
    /* if any bits not checked by opcode tables, output code to check them */
1391
    if (check_mask) {
1392
      lf_printf(file, "\n");
1393
      lf_printf(file, "/* validate: %s */\n",
1394
                instruction->file_entry->fields[insn_format]);
1395
      lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
1396
                check_mask, check_val);
1397
      lf_indent(file, +2);
1398
      print_idecode_illegal(file, "return");
1399
      lf_indent(file, -2);
1400
    }
1401
  }
1402
 
1403
  /* Validate floating point hardware
1404
 
1405
     If the simulator is being built with out floating point hardware
1406
     (different to it being disabled in the MSR) then floating point
1407
     instructions are invalid */
1408
  {
1409
    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1410
      lf_printf(file, "\n");
1411
      lf_printf(file, "/* Validate: FP hardware exists */\n");
1412
      lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
1413
      lf_indent(file, +2);
1414
      print_idecode_illegal(file, "return");
1415
      lf_indent(file, -2);
1416
    }
1417
  }
1418
 
1419
  /* Validate: Floating Point available
1420
 
1421
     If floating point is not available, we enter a floating point
1422
     unavailable interrupt into the cache instead of the instruction
1423
     proper.
1424
 
1425
     The PowerPC spec requires a CSI after MSR[FP] is changed and when
1426
     ever a CSI occures we flush the instruction cache. */
1427
 
1428
  {
1429
    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
1430
      lf_printf(file, "\n");
1431
      lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
1432
      lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
1433
      lf_indent(file, +2);
1434
      print_idecode_floating_point_unavailable(file);
1435
      lf_indent(file, -2);
1436
    }
1437
  }
1438
}
1439
 
1440
 
1441
/****************************************************************/
1442
 
1443
 
1444
static void
1445
print_idecode_run_function_header(lf *file,
1446
                                  int can_stop,
1447
                                  int is_definition)
1448
{
1449
  int indent;
1450
  lf_printf(file, "\n");
1451
  lf_print_function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n"));
1452
  indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
1453
  if (is_definition)
1454
    lf_putstr(file, "\n");
1455
  else
1456
    lf_indent(file, +indent);
1457
  lf_putstr(file, "(psim *system,\n");
1458
  if (can_stop)
1459
    lf_putstr(file, " volatile int *keep_running,\n");
1460
  lf_printf(file, " event_queue *events,\n");
1461
  lf_putstr(file, " cpu *const processors[],\n");
1462
  lf_putstr(file, " const int nr_cpus)");
1463
  if (is_definition)
1464
    lf_putstr(file, ";");
1465
  else
1466
    lf_indent(file, -indent);
1467
  lf_putstr(file, "\n");
1468
}
1469
 
1470
 
1471
void
1472
gen_idecode_h(lf *file,
1473
              insn_table *table,
1474
              cache_table *cache_rules)
1475
{
1476
  lf_printf(file, "/* The idecode_*.h functions shall move to support */\n");
1477
  lf_printf(file, "#include \"idecode_expression.h\"\n");
1478
  lf_printf(file, "#include \"idecode_fields.h\"\n");
1479
  lf_printf(file, "#include \"idecode_branch.h\"\n");
1480
  lf_printf(file, "\n");
1481
  print_icache_struct(table, cache_rules, file);
1482
  lf_printf(file, "\n");
1483
  lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp);
1484
  lf_printf(file, "\n");
1485
  print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/);
1486
  print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);
1487
}
1488
 
1489
 
1490
void
1491
gen_idecode_c(lf *file,
1492
              insn_table *table,
1493
              cache_table *cache_rules)
1494
{
1495
  /* the intro */
1496
  lf_printf(file, "#include \"inline.c\"\n");
1497
  lf_printf(file, "\n");
1498
  lf_printf(file, "#include \"cpu.h\"\n");
1499
  lf_printf(file, "#include \"idecode.h\"\n");
1500
  lf_printf(file, "#include \"semantics.h\"\n");
1501
  lf_printf(file, "#include \"icache.h\"\n");
1502
  lf_printf(file, "#ifdef HAVE_COMMON_FPU\n");
1503
  lf_printf(file, "#include \"sim-inline.h\"\n");
1504
  lf_printf(file, "#include \"sim-fpu.h\"\n");
1505
  lf_printf(file, "#endif\n");
1506
  lf_printf(file, "#include \"support.h\"\n");
1507
  lf_printf(file, "\n");
1508
  lf_printf(file, "#include <setjmp.h>\n");
1509
  lf_printf(file, "\n");
1510
  lf_printf(file, "enum {\n");
1511
  lf_printf(file, "  /* greater or equal to zero => table */\n");
1512
  lf_printf(file, "  function_entry = -1,\n");
1513
  lf_printf(file, "  boolean_entry = -2,\n");
1514
  lf_printf(file, "};\n");
1515
  lf_printf(file, "\n");
1516
  lf_printf(file, "typedef struct _idecode_table_entry {\n");
1517
  lf_printf(file, "  int shift;\n");
1518
  lf_printf(file, "  instruction_word mask;\n");
1519
  lf_printf(file, "  instruction_word value;");
1520
  lf_printf(file, "  void *function_or_table;\n");
1521
  lf_printf(file, "} idecode_table_entry;\n");
1522
  lf_printf(file, "\n");
1523
  lf_printf(file, "\n");
1524
 
1525
  if ((code & generate_calls)) {
1526
 
1527
    print_idecode_lookups(file, table, cache_rules);
1528
 
1529
    /* output the main idecode routine */
1530
    print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1531
    print_run_until_stop_body(file, table, 0/* have stop argument */);
1532
 
1533
    print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1534
    print_run_until_stop_body(file, table, 1/* no stop argument */);
1535
 
1536
  }
1537
  else if ((code & generate_jumps)) {
1538
 
1539
    print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
1540
    print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
1541
 
1542
    print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
1543
    print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
1544
 
1545
  }
1546
  else {
1547
    error("Something is wrong!\n");
1548
  }
1549
}

powered by: WebSVN 2.1.0

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