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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [ppc/] [gen-icache.c] - Blame information for rev 1771

Go to most recent revision | 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-1997, 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
 
22
#include "misc.h"
23
#include "lf.h"
24
#include "table.h"
25
 
26
#include "filter.h"
27
 
28
#include "ld-decode.h"
29
#include "ld-cache.h"
30
#include "ld-insn.h"
31
 
32
#include "igen.h"
33
 
34
#include "gen-semantics.h"
35
#include "gen-idecode.h"
36
#include "gen-icache.h"
37
 
38
 
39
 
40
static void
41
print_icache_function_header(lf *file,
42
                             const char *basename,
43
                             insn_bits *expanded_bits,
44
                             int is_function_definition)
45
{
46
  lf_printf(file, "\n");
47
  lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
48
  print_function_name(file,
49
                      basename,
50
                      expanded_bits,
51
                      function_name_prefix_icache);
52
  lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
53
  if (!is_function_definition)
54
    lf_printf(file, ";");
55
  lf_printf(file, "\n");
56
}
57
 
58
 
59
void
60
print_icache_declaration(insn_table *entry,
61
                         lf *file,
62
                         void *data,
63
                         insn *instruction,
64
                         int depth)
65
{
66
  if (generate_expanded_instructions) {
67
    ASSERT(entry->nr_insn == 1);
68
    print_icache_function_header(file,
69
                                 entry->insns->file_entry->fields[insn_name],
70
                                 entry->expanded_bits,
71
                                 0/* is not function definition */);
72
  }
73
  else {
74
    print_icache_function_header(file,
75
                                 instruction->file_entry->fields[insn_name],
76
                                 NULL,
77
                                 0/* is not function definition */);
78
  }
79
}
80
 
81
 
82
 
83
static void
84
print_icache_extraction(lf *file,
85
                        insn *instruction,
86
                        const char *entry_name,
87
                        const char *entry_type,
88
                        const char *entry_expression,
89
                        const char *original_name,
90
                        const char *file_name,
91
                        int line_nr,
92
                        insn_field *cur_field,
93
                        insn_bits *bits,
94
                        icache_decl_type what_to_declare,
95
                        icache_body_type what_to_do,
96
                        const char *reason)
97
{
98
  const char *expression;
99
  ASSERT(entry_name != NULL);
100
 
101
  /* Define a storage area for the cache element */
102
  if (what_to_declare == undef_variables) {
103
    /* We've finished with the value - destory it */
104
    lf_indent_suppress(file);
105
    lf_printf(file, "#undef %s\n", entry_name);
106
    return;
107
  }
108
  else if (what_to_declare == define_variables) {
109
    lf_indent_suppress(file);
110
    lf_printf(file, "#define %s ", entry_name);
111
  }
112
  else {
113
    if (file_name != NULL)
114
      lf_print__external_reference(file, line_nr, file_name);
115
    lf_printf(file, "%s const %s UNUSED = ",
116
              entry_type == NULL ? "unsigned" : entry_type,
117
              entry_name);
118
  }
119
 
120
  /* define a value for that storage area as determined by what is in
121
     the cache */
122
  if (bits != NULL
123
      && strcmp(entry_name, cur_field->val_string) == 0
124
      && ((bits->opcode->is_boolean && bits->value == 0)
125
          || (!bits->opcode->is_boolean))) {
126
    /* The simple field has been made constant (as a result of
127
       expanding instructions or similar).  Remember that for a
128
       boolean field, value is either 0 (implying the required
129
       boolean_constant) or nonzero (implying some other value and
130
       handled later below) - Define the variable accordingly */
131
    expression = "constant field";
132
    ASSERT(bits->field == cur_field);
133
    ASSERT(entry_type == NULL);
134
    if (bits->opcode->is_boolean)
135
      lf_printf(file, "%d", bits->opcode->boolean_constant);
136
    else if (bits->opcode->last < bits->field->last)
137
      lf_printf(file, "%d",
138
                bits->value << (bits->field->last - bits->opcode->last));
139
    else
140
      lf_printf(file, "%d", bits->value);
141
  }
142
  else if (bits != NULL
143
           && original_name != NULL
144
           && strncmp(entry_name,
145
                      original_name, strlen(original_name)) == 0
146
           && strncmp(entry_name + strlen(original_name),
147
                      "_is_", strlen("_is_")) == 0
148
           && ((bits->opcode->is_boolean
149
                && (atol(entry_name + strlen(original_name) + strlen("_is_"))
150
                    == bits->opcode->boolean_constant))
151
               || (!bits->opcode->is_boolean))) {
152
    expression = "constant compare";
153
    /* An entry, derived from ORIGINAL_NAME, is testing to see of the
154
       ORIGINAL_NAME has a specific constant value.  That value
155
       matching a boolean or constant field */
156
    if (bits->opcode->is_boolean)
157
      lf_printf(file, "%d /* %s == %d */",
158
                bits->value == 0,
159
                original_name,
160
                bits->opcode->boolean_constant);
161
    else if (bits->opcode->last < bits->field->last)
162
      lf_printf(file, "%d /* %s == %d */",
163
                (atol(entry_name + strlen(original_name) + strlen("_is_"))
164
                 == (bits->value << (bits->field->last - bits->opcode->last))),
165
                original_name,
166
                (bits->value << (bits->field->last - bits->opcode->last)));
167
    else
168
      lf_printf(file, "%d /* %s == %d */",
169
                (atol(entry_name + strlen(original_name) + strlen("_is_"))
170
                 == bits->value),
171
                original_name,
172
                bits->value);
173
  }
174
  else {
175
    /* put the field in the local variable, possibly also enter it
176
       into the cache */
177
    expression = "extraction";
178
    /* handle the cache */
179
    if ((what_to_do & get_values_from_icache)
180
        || (what_to_do & put_values_in_icache)) {
181
      lf_printf(file, "cache_entry->crack.%s.%s",
182
                instruction->file_entry->fields[insn_form],
183
                entry_name);
184
      if (what_to_do & put_values_in_icache) /* also put it in the cache? */
185
        lf_printf(file, " = ");
186
    }
187
    if ((what_to_do & put_values_in_icache)
188
        || what_to_do == do_not_use_icache) {
189
      if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
190
        lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
191
                  i2target(hi_bit_nr, cur_field->first),
192
                  i2target(hi_bit_nr, cur_field->last));
193
      else if (entry_expression != NULL)
194
        lf_printf(file, "%s", entry_expression);
195
      else
196
        lf_printf(file, "eval_%s", entry_name);
197
    }
198
  }
199
 
200
  if (!((what_to_declare == define_variables)
201
        || (what_to_declare == undef_variables)))
202
    lf_printf(file, ";");
203
  if (reason != NULL)
204
    lf_printf(file, " /* %s - %s */", reason, expression);
205
  lf_printf(file, "\n");
206
}
207
 
208
 
209
void
210
print_icache_body(lf *file,
211
                  insn *instruction,
212
                  insn_bits *expanded_bits,
213
                  cache_table *cache_rules,
214
                  icache_decl_type what_to_declare,
215
                  icache_body_type what_to_do)
216
{
217
  insn_field *cur_field;
218
 
219
  /* extract instruction fields */
220
  lf_printf(file, "/* extraction: %s ",
221
            instruction->file_entry->fields[insn_format]);
222
  switch (what_to_declare) {
223
  case define_variables:
224
    lf_printf(file, "#define");
225
    break;
226
  case declare_variables:
227
    lf_printf(file, "declare");
228
    break;
229
  case undef_variables:
230
    lf_printf(file, "#undef");
231
    break;
232
  }
233
  lf_printf(file, " ");
234
  switch (what_to_do) {
235
  case get_values_from_icache:
236
    lf_printf(file, "get-values-from-icache");
237
    break;
238
  case put_values_in_icache:
239
    lf_printf(file, "put-values-in-icache");
240
    break;
241
  case both_values_and_icache:
242
    lf_printf(file, "get-values-from-icache|put-values-in-icache");
243
    break;
244
  case do_not_use_icache:
245
    lf_printf(file, "do-not-use-icache");
246
    break;
247
  }
248
  lf_printf(file, " */\n");
249
 
250
  for (cur_field = instruction->fields->first;
251
       cur_field->first < insn_bit_size;
252
       cur_field = cur_field->next) {
253
    if (cur_field->is_string) {
254
      insn_bits *bits;
255
      int found_rule = 0;
256
      /* find any corresponding value */
257
      for (bits = expanded_bits;
258
           bits != NULL;
259
           bits = bits->last) {
260
        if (bits->field == cur_field)
261
          break;
262
      }
263
      /* try the cache rule table for what to do */
264
      {
265
        cache_table *cache_rule;
266
        for (cache_rule = cache_rules;
267
             cache_rule != NULL;
268
             cache_rule = cache_rule->next) {
269
          if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
270
            found_rule = 1;
271
            if (cache_rule->type == scratch_value
272
                && ((what_to_do & put_values_in_icache)
273
                    || what_to_do == do_not_use_icache))
274
              print_icache_extraction(file,
275
                                      instruction,
276
                                      cache_rule->derived_name,
277
                                      cache_rule->type_def,
278
                                      cache_rule->expression,
279
                                      cache_rule->field_name,
280
                                      cache_rule->file_entry->file_name,
281
                                      cache_rule->file_entry->line_nr,
282
                                      cur_field,
283
                                      bits,
284
                                      what_to_declare,
285
                                      do_not_use_icache,
286
                                      "icache scratch");
287
            else if (cache_rule->type == compute_value
288
                     && ((what_to_do & get_values_from_icache)
289
                         || what_to_do == do_not_use_icache))
290
              print_icache_extraction(file,
291
                                      instruction,
292
                                      cache_rule->derived_name,
293
                                      cache_rule->type_def,
294
                                      cache_rule->expression,
295
                                      cache_rule->field_name,
296
                                      cache_rule->file_entry->file_name,
297
                                      cache_rule->file_entry->line_nr,
298
                                      cur_field,
299
                                      bits,
300
                                      what_to_declare,
301
                                      do_not_use_icache,
302
                                      "semantic compute");
303
            else if (cache_rule->type == cache_value
304
                     && ((what_to_declare != undef_variables)
305
                         || !(what_to_do & put_values_in_icache)))
306
              print_icache_extraction(file,
307
                                      instruction,
308
                                      cache_rule->derived_name,
309
                                      cache_rule->type_def,
310
                                      cache_rule->expression,
311
                                      cache_rule->field_name,
312
                                      cache_rule->file_entry->file_name,
313
                                      cache_rule->file_entry->line_nr,
314
                                      cur_field,
315
                                      bits,
316
                                      ((what_to_do & put_values_in_icache)
317
                                       ? declare_variables
318
                                       : what_to_declare),
319
                                      what_to_do,
320
                                      "in icache");
321
          }
322
        }
323
      }
324
      /* No rule at all, assume that this is needed in the semantic
325
         function (when values are extracted from the icache) and
326
         hence must be put into the cache */
327
      if (found_rule == 0
328
          && ((what_to_declare != undef_variables)
329
              || !(what_to_do & put_values_in_icache)))
330
        print_icache_extraction(file,
331
                                instruction,
332
                                cur_field->val_string,
333
                                NULL, NULL, NULL, /* type, exp, orig */
334
                                instruction->file_entry->file_name,
335
                                instruction->file_entry->line_nr,
336
                                cur_field,
337
                                bits,
338
                                ((what_to_do & put_values_in_icache)
339
                                 ? declare_variables
340
                                 : what_to_declare),
341
                                what_to_do,
342
                                "default in icache");
343
      /* any thing else ... */
344
    }
345
  }
346
 
347
  lf_print__internal_reference(file);
348
 
349
  if ((code & generate_with_insn_in_icache)) {
350
    lf_printf(file, "\n");
351
    print_icache_extraction(file,
352
                            instruction,
353
                            "insn",
354
                            "instruction_word",
355
                            "instruction",
356
                            NULL, /* origin */
357
                            NULL, 0, /* file_name & line_nr */
358
                            NULL, NULL,
359
                            what_to_declare,
360
                            what_to_do,
361
                            NULL);
362
  }
363
}
364
 
365
 
366
 
367
typedef struct _icache_tree icache_tree;
368
struct _icache_tree {
369
  char *name;
370
  icache_tree *next;
371
  icache_tree *children;
372
};
373
 
374
static icache_tree *
375
icache_tree_insert(icache_tree *tree,
376
                   char *name)
377
{
378
  icache_tree *new_tree;
379
  /* find it */
380
  icache_tree **ptr_to_cur_tree = &tree->children;
381
  icache_tree *cur_tree = *ptr_to_cur_tree;
382
  while (cur_tree != NULL
383
         && strcmp(cur_tree->name, name) < 0) {
384
    ptr_to_cur_tree = &cur_tree->next;
385
    cur_tree = *ptr_to_cur_tree;
386
  }
387
  ASSERT(cur_tree == NULL
388
         || strcmp(cur_tree->name, name) >= 0);
389
  /* already in the tree */
390
  if (cur_tree != NULL
391
      && strcmp(cur_tree->name, name) == 0)
392
    return cur_tree;
393
  /* missing, insert it */
394
  ASSERT(cur_tree == NULL
395
         || strcmp(cur_tree->name, name) > 0);
396
  new_tree = ZALLOC(icache_tree);
397
  new_tree->name = name;
398
  new_tree->next = cur_tree;
399
  *ptr_to_cur_tree = new_tree;
400
  return new_tree;
401
}
402
 
403
 
404
static icache_tree *
405
insn_table_cache_fields(insn_table *table)
406
{
407
  icache_tree *tree = ZALLOC(icache_tree);
408
  insn *instruction;
409
  for (instruction = table->insns;
410
       instruction != NULL;
411
       instruction = instruction->next) {
412
    insn_field *field;
413
    icache_tree *form =
414
      icache_tree_insert(tree,
415
                         instruction->file_entry->fields[insn_form]);
416
    for (field = instruction->fields->first;
417
         field != NULL;
418
         field = field->next) {
419
      if (field->is_string)
420
        icache_tree_insert(form, field->val_string);
421
    }
422
  }
423
  return tree;
424
}
425
 
426
 
427
 
428
extern void
429
print_icache_struct(insn_table *instructions,
430
                    cache_table *cache_rules,
431
                    lf *file)
432
{
433
  icache_tree *tree = insn_table_cache_fields(instructions);
434
 
435
  lf_printf(file, "\n");
436
  lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
437
            (code & generate_with_icache) ? icache_size : 0);
438
  lf_printf(file, "\n");
439
 
440
  /* create an instruction cache if being used */
441
  if ((code & generate_with_icache)) {
442
    icache_tree *form;
443
    lf_printf(file, "typedef struct _idecode_cache {\n");
444
    lf_printf(file, "  unsigned_word address;\n");
445
    lf_printf(file, "  void *semantic;\n");
446
    lf_printf(file, "  union {\n");
447
    for (form = tree->children;
448
         form != NULL;
449
         form = form->next) {
450
      icache_tree *field;
451
      lf_printf(file, "    struct {\n");
452
      if (code & generate_with_insn_in_icache)
453
        lf_printf(file, "      instruction_word insn;\n");
454
      for (field = form->children;
455
           field != NULL;
456
           field = field->next) {
457
        cache_table *cache_rule;
458
        int found_rule = 0;
459
        for (cache_rule = cache_rules;
460
             cache_rule != NULL;
461
             cache_rule = cache_rule->next) {
462
          if (strcmp(field->name, cache_rule->field_name) == 0) {
463
            found_rule = 1;
464
            if (cache_rule->derived_name != NULL)
465
              lf_printf(file, "      %s %s; /* %s */\n",
466
                        (cache_rule->type_def == NULL
467
                         ? "unsigned"
468
                         : cache_rule->type_def),
469
                        cache_rule->derived_name,
470
                        cache_rule->field_name);
471
          }
472
        }
473
        if (!found_rule)
474
          lf_printf(file, "      unsigned %s;\n", field->name);
475
      }
476
      lf_printf(file, "    } %s;\n", form->name);
477
    }
478
    lf_printf(file, "  } crack;\n");
479
    lf_printf(file, "} idecode_cache;\n");
480
  }
481
  else {
482
    /* alernativly, since no cache, emit a dummy definition for
483
       idecode_cache so that code refering to the type can still compile */
484
    lf_printf(file, "typedef void idecode_cache;\n");
485
  }
486
  lf_printf(file, "\n");
487
}
488
 
489
 
490
 
491
static void
492
print_icache_function(lf *file,
493
                      insn *instruction,
494
                      insn_bits *expanded_bits,
495
                      opcode_field *opcodes,
496
                      cache_table *cache_rules)
497
{
498
  int indent;
499
 
500
  /* generate code to enter decoded instruction into the icache */
501
  lf_printf(file, "\n");
502
  lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
503
  indent = print_function_name(file,
504
                               instruction->file_entry->fields[insn_name],
505
                               expanded_bits,
506
                               function_name_prefix_icache);
507
  lf_indent(file, +indent);
508
  lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
509
  lf_indent(file, -indent);
510
 
511
  /* function header */
512
  lf_printf(file, "{\n");
513
  lf_indent(file, +2);
514
 
515
  print_my_defines(file, expanded_bits, instruction->file_entry);
516
  print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
517
 
518
  print_idecode_validate(file, instruction, opcodes);
519
 
520
  lf_printf(file, "\n");
521
  lf_printf(file, "{\n");
522
  lf_indent(file, +2);
523
  if ((code & generate_with_semantic_icache))
524
    lf_printf(file, "unsigned_word nia;\n");
525
  print_icache_body(file,
526
                    instruction,
527
                    expanded_bits,
528
                    cache_rules,
529
                    ((code & generate_with_direct_access)
530
                     ? define_variables
531
                     : declare_variables),
532
                    ((code & generate_with_semantic_icache)
533
                     ? both_values_and_icache
534
                     : put_values_in_icache));
535
 
536
  lf_printf(file, "\n");
537
  lf_printf(file, "cache_entry->address = cia;\n");
538
  lf_printf(file, "cache_entry->semantic = ");
539
  print_function_name(file,
540
                      instruction->file_entry->fields[insn_name],
541
                      expanded_bits,
542
                      function_name_prefix_semantics);
543
  lf_printf(file, ";\n");
544
  lf_printf(file, "\n");
545
 
546
  if ((code & generate_with_semantic_icache)) {
547
    lf_printf(file, "/* semantic routine */\n");
548
    print_semantic_body(file,
549
                        instruction,
550
                        expanded_bits,
551
                        opcodes);
552
    lf_printf(file, "return nia;\n");
553
  }
554
 
555
  if (!(code & generate_with_semantic_icache)) {
556
    lf_printf(file, "/* return the function proper */\n");
557
    lf_printf(file, "return ");
558
    print_function_name(file,
559
                        instruction->file_entry->fields[insn_name],
560
                        expanded_bits,
561
                        function_name_prefix_semantics);
562
    lf_printf(file, ";\n");
563
  }
564
 
565
  if ((code & generate_with_direct_access))
566
    print_icache_body(file,
567
                      instruction,
568
                      expanded_bits,
569
                      cache_rules,
570
                      undef_variables,
571
                      ((code & generate_with_semantic_icache)
572
                       ? both_values_and_icache
573
                       : put_values_in_icache));
574
 
575
  lf_indent(file, -2);
576
  lf_printf(file, "}\n");
577
  lf_indent(file, -2);
578
  lf_printf(file, "}\n");
579
}
580
 
581
 
582
void
583
print_icache_definition(insn_table *entry,
584
                        lf *file,
585
                        void *data,
586
                        insn *instruction,
587
                        int depth)
588
{
589
  cache_table *cache_rules = (cache_table*)data;
590
  if (generate_expanded_instructions) {
591
    ASSERT(entry->nr_insn == 1
592
           && entry->opcode == NULL
593
           && entry->parent != NULL
594
           && entry->parent->opcode != NULL);
595
    ASSERT(entry->nr_insn == 1
596
           && entry->opcode == NULL
597
           && entry->parent != NULL
598
           && entry->parent->opcode != NULL
599
           && entry->parent->opcode_rule != NULL);
600
    print_icache_function(file,
601
                          entry->insns,
602
                          entry->expanded_bits,
603
                          entry->opcode,
604
                          cache_rules);
605
  }
606
  else {
607
    print_icache_function(file,
608
                          instruction,
609
                          NULL,
610
                          NULL,
611
                          cache_rules);
612
  }
613
}
614
 
615
 
616
 
617
void
618
print_icache_internal_function_declaration(insn_table *table,
619
                                           lf *file,
620
                                           void *data,
621
                                           table_entry *function)
622
{
623
  ASSERT((code & generate_with_icache) != 0);
624
  if (it_is("internal", function->fields[insn_flags])) {
625
    lf_printf(file, "\n");
626
    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
627
                           "\n");
628
    print_function_name(file,
629
                        function->fields[insn_name],
630
                        NULL,
631
                        function_name_prefix_icache);
632
    lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
633
  }
634
}
635
 
636
 
637
void
638
print_icache_internal_function_definition(insn_table *table,
639
                                          lf *file,
640
                                          void *data,
641
                                          table_entry *function)
642
{
643
  ASSERT((code & generate_with_icache) != 0);
644
  if (it_is("internal", function->fields[insn_flags])) {
645
    lf_printf(file, "\n");
646
    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
647
                           "\n");
648
    print_function_name(file,
649
                        function->fields[insn_name],
650
                        NULL,
651
                        function_name_prefix_icache);
652
    lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
653
    lf_printf(file, "{\n");
654
    lf_indent(file, +2);
655
    lf_printf(file, "/* semantic routine */\n");
656
    table_entry_print_cpp_line_nr(file, function);
657
    if ((code & generate_with_semantic_icache)) {
658
      lf_print__c_code(file, function->annex);
659
      lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
660
      lf_printf(file, "return 0;\n");
661
    }
662
    else {
663
      lf_printf(file, "return ");
664
      print_function_name(file,
665
                          function->fields[insn_name],
666
                          NULL,
667
                          function_name_prefix_semantics);
668
      lf_printf(file, ";\n");
669
    }
670
 
671
    lf_print__internal_reference(file);
672
    lf_indent(file, -2);
673
    lf_printf(file, "}\n");
674
  }
675
}

powered by: WebSVN 2.1.0

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