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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [ld-insn.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  This file is part of the program psim.
2
 
3
    Copyright 1994, 1995, 1996, 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
 
22
#include "misc.h"
23
#include "lf.h"
24
#include "table.h"
25
#include "filter.h"
26
#include "ld-decode.h"
27
#include "ld-cache.h"
28
#include "ld-insn.h"
29
 
30
#include "igen.h"
31
 
32
static void
33
update_depth(insn_table *entry,
34
             lf *file,
35
             void *data,
36
             insn *instruction,
37
             int depth)
38
{
39
  int *max_depth = (int*)data;
40
  if (*max_depth < depth)
41
    *max_depth = depth;
42
}
43
 
44
 
45
int
46
insn_table_depth(insn_table *table)
47
{
48
  int depth = 0;
49
  insn_table_traverse_tree(table,
50
                           NULL,
51
                           &depth,
52
                           1,
53
                           NULL, /*start*/
54
                           update_depth,
55
                           NULL, /*end*/
56
                           NULL); /*padding*/
57
  return depth;
58
}
59
 
60
 
61
static insn_fields *
62
parse_insn_format(table_entry *entry,
63
                  char *format)
64
{
65
  char *chp;
66
  insn_fields *fields = ZALLOC(insn_fields);
67
 
68
  /* create a leading sentinal */
69
  fields->first = ZALLOC(insn_field);
70
  fields->first->first = -1;
71
  fields->first->last = -1;
72
  fields->first->width = 0;
73
 
74
  /* and a trailing sentinal */
75
  fields->last = ZALLOC(insn_field);
76
  fields->last->first = insn_bit_size;
77
  fields->last->last = insn_bit_size;
78
  fields->last->width = 0;
79
 
80
  /* link them together */
81
  fields->first->next = fields->last;
82
  fields->last->prev = fields->first;
83
 
84
  /* now work through the formats */
85
  chp = format;
86
 
87
  while (*chp != '\0') {
88
    char *start_pos;
89
    char *start_val;
90
    int strlen_val;
91
    int strlen_pos;
92
    insn_field *new_field;
93
 
94
    /* sanity check */
95
    if (!isdigit(*chp)) {
96
      error("%s:%d: missing position field at `%s'\n",
97
            entry->file_name, entry->line_nr, chp);
98
    }
99
 
100
    /* break out the bit position */
101
    start_pos = chp;
102
    while (isdigit(*chp))
103
      chp++;
104
    strlen_pos = chp - start_pos;
105
    if (*chp == '.' && strlen_pos > 0)
106
      chp++;
107
    else {
108
      error("%s:%d: missing field value at %s\n",
109
            entry->file_name, entry->line_nr, chp);
110
      break;
111
    }
112
 
113
    /* break out the value */
114
    start_val = chp;
115
    while ((*start_val == '/' && *chp == '/')
116
           || (isdigit(*start_val) && isdigit(*chp))
117
           || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
118
      chp++;
119
    strlen_val = chp - start_val;
120
    if (*chp == ',')
121
      chp++;
122
    else if (*chp != '\0' || strlen_val == 0) {
123
      error("%s:%d: missing field terminator at %s\n",
124
            entry->file_name, entry->line_nr, chp);
125
      break;
126
    }
127
 
128
    /* create a new field and insert it */
129
    new_field = ZALLOC(insn_field);
130
    new_field->next = fields->last;
131
    new_field->prev = fields->last->prev;
132
    new_field->next->prev = new_field;
133
    new_field->prev->next = new_field;
134
 
135
    /* the value */
136
    new_field->val_string = (char*)zalloc(strlen_val+1);
137
    strncpy(new_field->val_string, start_val, strlen_val);
138
    if (isdigit(*new_field->val_string)) {
139
      new_field->val_int = a2i(new_field->val_string);
140
      new_field->is_int = 1;
141
    }
142
    else if (new_field->val_string[0] == '/') {
143
      new_field->is_slash = 1;
144
    }
145
    else {
146
      new_field->is_string = 1;
147
    }
148
 
149
    /* the pos */
150
    new_field->pos_string = (char*)zalloc(strlen_pos+1);
151
    strncpy(new_field->pos_string, start_pos, strlen_pos);
152
    new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
153
    new_field->last = new_field->next->first - 1; /* guess */
154
    new_field->width = new_field->last - new_field->first + 1; /* guess */
155
    new_field->prev->last = new_field->first-1; /*fix*/
156
    new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
157
  }
158
 
159
  /* fiddle first/last so that the sentinals `disapear' */
160
  ASSERT(fields->first->last < 0);
161
  ASSERT(fields->last->first >= insn_bit_size);
162
  fields->first = fields->first->next;
163
  fields->last = fields->last->prev;
164
 
165
  /* now go over this again, pointing each bit position at a field
166
     record */
167
  {
168
    int i;
169
    insn_field *field;
170
    field = fields->first;
171
    for (i = 0; i < insn_bit_size; i++) {
172
      while (field->last < i)
173
        field = field->next;
174
      fields->bits[i] = field;
175
    }
176
  }
177
 
178
  /* go over each of the fields, and compute a `value' for the insn */
179
  {
180
    insn_field *field;
181
    fields->value = 0;
182
    for (field = fields->first;
183
         field->last < insn_bit_size;
184
         field = field->next) {
185
      fields->value <<= field->width;
186
      if (field->is_int)
187
        fields->value |= field->val_int;
188
    }
189
  }
190
  return fields;
191
}
192
 
193
 
194
void
195
parse_include_entry (table *file,
196
                     table_entry *file_entry,
197
                     filter *filters,
198
                     table_include *includes)
199
{
200
  /* parse the include file_entry */
201
  if (file_entry->nr_fields < 4)
202
    error ("Incorrect nr fields for include record\n");
203
  /* process it */
204
  if (!is_filtered_out(file_entry->fields[include_flags], filters))
205
    {
206
      table_push (file, includes,
207
                file_entry->fields[include_path],
208
                file_entry->nr_fields, file_entry->nr_fields);
209
    }
210
}
211
 
212
static void
213
model_table_insert(insn_table *table,
214
                   table_entry *file_entry)
215
{
216
  int len;
217
 
218
  /* create a new model */
219
  model *new_model = ZALLOC(model);
220
 
221
  new_model->name = file_entry->fields[model_identifer];
222
  new_model->printable_name = file_entry->fields[model_name];
223
  new_model->insn_default = file_entry->fields[model_default];
224
 
225
  while (*new_model->insn_default && isspace(*new_model->insn_default))
226
    new_model->insn_default++;
227
 
228
  len = strlen(new_model->insn_default);
229
  if (max_model_fields_len < len)
230
    max_model_fields_len = len;
231
 
232
  /* append it to the end of the model list */
233
  if (last_model)
234
    last_model->next = new_model;
235
  else
236
    models = new_model;
237
  last_model = new_model;
238
}
239
 
240
static void
241
model_table_insert_specific(insn_table *table,
242
                            table_entry *file_entry,
243
                            insn **start_ptr,
244
                            insn **end_ptr)
245
{
246
  insn *ptr = ZALLOC(insn);
247
  ptr->file_entry = file_entry;
248
  if (*end_ptr)
249
    (*end_ptr)->next = ptr;
250
  else
251
    (*start_ptr) = ptr;
252
  (*end_ptr) = ptr;
253
}
254
 
255
 
256
static void
257
insn_table_insert_function(insn_table *table,
258
                           table_entry *file_entry)
259
{
260
  /* create a new function */
261
  insn *new_function = ZALLOC(insn);
262
  new_function->file_entry = file_entry;
263
 
264
  /* append it to the end of the function list */
265
  if (table->last_function)
266
    table->last_function->next = new_function;
267
  else
268
    table->functions = new_function;
269
  table->last_function = new_function;
270
}
271
 
272
extern void
273
insn_table_insert_insn(insn_table *table,
274
                       table_entry *file_entry,
275
                       insn_fields *fields)
276
{
277
  insn **ptr_to_cur_insn = &table->insns;
278
  insn *cur_insn = *ptr_to_cur_insn;
279
  table_model_entry *insn_model_ptr;
280
  model *model_ptr;
281
 
282
  /* create a new instruction */
283
  insn *new_insn = ZALLOC(insn);
284
  new_insn->file_entry = file_entry;
285
  new_insn->fields = fields;
286
 
287
  /* Check out any model information returned to make sure the model
288
     is correct.  */
289
  for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
290
    char *name = insn_model_ptr->fields[insn_model_name];
291
    int len = strlen (insn_model_ptr->fields[insn_model_fields]);
292
 
293
    while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) {
294
      len--;
295
      insn_model_ptr->fields[insn_model_fields]++;
296
    }
297
 
298
    if (max_model_fields_len < len)
299
      max_model_fields_len = len;
300
 
301
    for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
302
      if (strcmp(name, model_ptr->printable_name) == 0) {
303
 
304
        /* Replace the name field with that of the global model, so that when we
305
           want to print it out, we can just compare pointers.  */
306
        insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name;
307
        break;
308
      }
309
    }
310
 
311
    if (!model_ptr)
312
      error("%s:%d: machine model `%s' was not known about\n",
313
            file_entry->file_name, file_entry->line_nr, name);
314
  }
315
 
316
  /* insert it according to the order of the fields */
317
  while (cur_insn != NULL
318
         && new_insn->fields->value >= cur_insn->fields->value) {
319
    ptr_to_cur_insn = &cur_insn->next;
320
    cur_insn = *ptr_to_cur_insn;
321
  }
322
 
323
  new_insn->next = cur_insn;
324
  *ptr_to_cur_insn = new_insn;
325
 
326
  table->nr_insn++;
327
}
328
 
329
 
330
 
331
insn_table *
332
load_insn_table(const char *file_name,
333
                decode_table *decode_rules,
334
                filter *filters,
335
                table_include *includes,
336
                cache_table **cache_rules)
337
{
338
  table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
339
  insn_table *table = ZALLOC(insn_table);
340
  table_entry *file_entry;
341
  table->opcode_rule = decode_rules;
342
 
343
  while ((file_entry = table_entry_read(file)) != NULL) {
344
    if (it_is("function", file_entry->fields[insn_flags])
345
        || it_is("internal", file_entry->fields[insn_flags])) {
346
      insn_table_insert_function(table, file_entry);
347
    }
348
    else if ((it_is("function", file_entry->fields[insn_form])
349
              || it_is("internal", file_entry->fields[insn_form]))
350
             && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
351
      /* Ok, this is evil.  Need to convert a new style function into
352
         an old style function.  Construct an old style table and then
353
         copy it back.  */
354
      char *fields[nr_insn_table_fields];
355
      memset (fields, 0, sizeof fields);
356
      fields[insn_flags] = file_entry->fields[insn_form];
357
      fields[function_type] = file_entry->fields[insn_name];
358
      fields[function_name] = file_entry->fields[insn_comment];
359
      fields[function_param] = file_entry->fields[insn_field_6];
360
      memcpy (file_entry->fields, fields,
361
              sizeof (fields[0]) * file_entry->nr_fields);
362
      insn_table_insert_function(table, file_entry);
363
#if 0
364
      ":" "..."
365
       ":" <filter-flags>
366
       ":" <filter-models>
367
       ":" <typedef>
368
       ":" <name>
369
       [ ":" <parameter-list> ]
370
       <nl>
371
       [ <function-model> ]
372
       <code-block>
373
#endif
374
    }
375
    else if (it_is("model", file_entry->fields[insn_flags])) {
376
      model_table_insert(table, file_entry);
377
    }
378
    else if (it_is("model-macro", file_entry->fields[insn_flags])) {
379
      model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
380
    }
381
    else if (it_is("model-function", file_entry->fields[insn_flags])) {
382
      model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
383
    }
384
    else if (it_is("model-internal", file_entry->fields[insn_flags])) {
385
      model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
386
    }
387
    else if (it_is("model-static", file_entry->fields[insn_flags])) {
388
      model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
389
    }
390
    else if (it_is("model-data", file_entry->fields[insn_flags])) {
391
      model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
392
    }
393
    else if (it_is("include", file_entry->fields[insn_form])
394
             && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
395
      parse_include_entry (file, file_entry, filters, includes);
396
    }
397
    else if ((it_is("cache", file_entry->fields[insn_form])
398
              || it_is("compute", file_entry->fields[insn_form])
399
              || it_is("scratch", file_entry->fields[insn_form]))
400
             && !is_filtered_out(file_entry->fields[insn_flags], filters)) {
401
      append_cache_rule (cache_rules,
402
                         file_entry->fields[insn_form], /* type */
403
                         file_entry->fields[cache_name],
404
                         file_entry->fields[cache_derived_name],
405
                         file_entry->fields[cache_type_def],
406
                         file_entry->fields[cache_expression],
407
                         file_entry);
408
    }
409
    else {
410
      insn_fields *fields;
411
      /* skip instructions that aren't relevant to the mode */
412
      if (is_filtered_out(file_entry->fields[insn_flags], filters)) {
413
        fprintf(stderr, "Dropping %s - %s\n",
414
                file_entry->fields[insn_name],
415
                file_entry->fields[insn_flags]);
416
      }
417
      else {
418
        /* create/insert the new instruction */
419
        fields = parse_insn_format(file_entry,
420
                                   file_entry->fields[insn_format]);
421
        insn_table_insert_insn(table, file_entry, fields);
422
      }
423
    }
424
  }
425
  return table;
426
}
427
 
428
 
429
extern void
430
insn_table_traverse_tree(insn_table *table,
431
                         lf *file,
432
                         void *data,
433
                         int depth,
434
                         leaf_handler *start,
435
                         insn_handler *leaf,
436
                         leaf_handler *end,
437
                         padding_handler *padding)
438
{
439
  insn_table *entry;
440
  int entry_nr;
441
 
442
  ASSERT(table != NULL
443
         && table->opcode != NULL
444
         && table->nr_entries > 0
445
         && table->entries != 0);
446
 
447
  if (start != NULL && depth >= 0)
448
    start(table, file, data, depth);
449
 
450
  for (entry_nr = 0, entry = table->entries;
451
       entry_nr < (table->opcode->is_boolean
452
                   ? 2
453
                   : (1 << (table->opcode->last - table->opcode->first + 1)));
454
       entry_nr ++) {
455
    if (entry == NULL
456
        || (!table->opcode->is_boolean
457
            && entry_nr < entry->opcode_nr)) {
458
      if (padding != NULL && depth >= 0)
459
        padding(table, file, data, depth, entry_nr);
460
    }
461
    else {
462
      ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
463
                               || table->opcode->is_boolean));
464
      if (entry->opcode != NULL && depth != 0) {
465
        insn_table_traverse_tree(entry, file, data, depth+1,
466
                                 start, leaf, end, padding);
467
      }
468
      else if (depth >= 0) {
469
        if (leaf != NULL)
470
          leaf(entry, file, data, entry->insns, depth);
471
      }
472
      entry = entry->sibling;
473
    }
474
  }
475
  if (end != NULL && depth >= 0)
476
    end(table, file, data, depth);
477
}
478
 
479
 
480
extern void
481
insn_table_traverse_function(insn_table *table,
482
                             lf *file,
483
                             void *data,
484
                             function_handler *leaf)
485
{
486
  insn *function;
487
  for (function = table->functions;
488
       function != NULL;
489
       function = function->next) {
490
    leaf(table, file, data, function->file_entry);
491
  }
492
}
493
 
494
extern void
495
insn_table_traverse_insn(insn_table *table,
496
                         lf *file,
497
                         void *data,
498
                         insn_handler *handler)
499
{
500
  insn *instruction;
501
  for (instruction = table->insns;
502
       instruction != NULL;
503
       instruction = instruction->next) {
504
    handler(table, file, data, instruction, 0);
505
  }
506
}
507
 
508
 
509
/****************************************************************/
510
 
511
typedef enum {
512
  field_constant_int = 1,
513
  field_constant_slash = 2,
514
  field_constant_string = 3
515
} constant_field_types;
516
 
517
 
518
static int
519
insn_field_is_constant(insn_field *field,
520
                       decode_table *rule)
521
{
522
  /* field is an integer */
523
  if (field->is_int)
524
    return field_constant_int;
525
  /* field is `/' and treating that as a constant */
526
  if (field->is_slash && rule->force_slash)
527
    return field_constant_slash;
528
  /* field, though variable is on the list */
529
  if (field->is_string && rule->force_expansion != NULL) {
530
    char *forced_fields = rule->force_expansion;
531
    while (*forced_fields != '\0') {
532
      int field_len;
533
      char *end = strchr(forced_fields, ',');
534
      if (end == NULL)
535
        field_len = strlen(forced_fields);
536
      else
537
        field_len = end-forced_fields;
538
      if (strncmp(forced_fields, field->val_string, field_len) == 0
539
          && field->val_string[field_len] == '\0')
540
        return field_constant_string;
541
      forced_fields += field_len;
542
      if (*forced_fields == ',')
543
        forced_fields++;
544
    }
545
  }
546
  return 0;
547
}
548
 
549
 
550
static opcode_field *
551
insn_table_find_opcode_field(insn *insns,
552
                             decode_table *rule,
553
                             int string_only)
554
{
555
  opcode_field *curr_opcode = ZALLOC(opcode_field);
556
  insn *entry;
557
  ASSERT(rule);
558
 
559
  curr_opcode->first = insn_bit_size;
560
  curr_opcode->last = -1;
561
  for (entry = insns; entry != NULL; entry = entry->next) {
562
    insn_fields *fields = entry->fields;
563
    opcode_field new_opcode;
564
 
565
    /* find a start point for the opcode field */
566
    new_opcode.first = rule->first;
567
    while (new_opcode.first <= rule->last
568
           && (!string_only
569
               || insn_field_is_constant(fields->bits[new_opcode.first],
570
                                         rule) != field_constant_string)
571
           && (string_only
572
               || !insn_field_is_constant(fields->bits[new_opcode.first],
573
                                          rule)))
574
      new_opcode.first = fields->bits[new_opcode.first]->last + 1;
575
    ASSERT(new_opcode.first > rule->last
576
           || (string_only
577
               && insn_field_is_constant(fields->bits[new_opcode.first],
578
                                         rule) == field_constant_string)
579
           || (!string_only
580
               && insn_field_is_constant(fields->bits[new_opcode.first],
581
                                         rule)));
582
 
583
    /* find the end point for the opcode field */
584
    new_opcode.last = rule->last;
585
    while (new_opcode.last >= rule->first
586
           && (!string_only
587
               || insn_field_is_constant(fields->bits[new_opcode.last],
588
                                         rule) != field_constant_string)
589
           && (string_only
590
               || !insn_field_is_constant(fields->bits[new_opcode.last],
591
                                          rule)))
592
      new_opcode.last = fields->bits[new_opcode.last]->first - 1;
593
    ASSERT(new_opcode.last < rule->first
594
           || (string_only
595
               && insn_field_is_constant(fields->bits[new_opcode.last],
596
                                         rule) == field_constant_string)
597
           || (!string_only
598
               && insn_field_is_constant(fields->bits[new_opcode.last],
599
                                         rule)));
600
 
601
    /* now see if our current opcode needs expanding */
602
    if (new_opcode.first <= rule->last
603
        && curr_opcode->first > new_opcode.first)
604
      curr_opcode->first = new_opcode.first;
605
    if (new_opcode.last >= rule->first
606
        && curr_opcode->last < new_opcode.last)
607
      curr_opcode->last = new_opcode.last;
608
 
609
  }
610
 
611
  /* was any thing interesting found? */
612
  if (curr_opcode->first > rule->last) {
613
    ASSERT(curr_opcode->last < rule->first);
614
    return NULL;
615
  }
616
  ASSERT(curr_opcode->last >= rule->first);
617
  ASSERT(curr_opcode->first <= rule->last);
618
 
619
  /* if something was found, check it includes the forced field range */
620
  if (!string_only
621
      && curr_opcode->first > rule->force_first) {
622
    curr_opcode->first = rule->force_first;
623
  }
624
  if (!string_only
625
      && curr_opcode->last < rule->force_last) {
626
    curr_opcode->last = rule->force_last;
627
  }
628
  /* handle special case elminating any need to do shift after mask */
629
  if (string_only
630
      && rule->force_last == insn_bit_size-1) {
631
    curr_opcode->last = insn_bit_size-1;
632
  }
633
 
634
  /* handle any special cases */
635
  switch (rule->type) {
636
  case normal_decode_rule:
637
    /* let the above apply */
638
    break;
639
  case expand_forced_rule:
640
    /* expand a limited nr of bits, ignoring the rest */
641
    curr_opcode->first = rule->force_first;
642
    curr_opcode->last = rule->force_last;
643
    break;
644
  case boolean_rule:
645
    curr_opcode->is_boolean = 1;
646
    curr_opcode->boolean_constant = rule->special_constant;
647
    break;
648
  default:
649
    error("Something is going wrong\n");
650
  }
651
 
652
  return curr_opcode;
653
}
654
 
655
 
656
static void
657
insn_table_insert_expanded(insn_table *table,
658
                           insn *old_insn,
659
                           int new_opcode_nr,
660
                           insn_bits *new_bits)
661
{
662
  insn_table **ptr_to_cur_entry = &table->entries;
663
  insn_table *cur_entry = *ptr_to_cur_entry;
664
 
665
  /* find the new table for this entry */
666
  while (cur_entry != NULL
667
         && cur_entry->opcode_nr < new_opcode_nr) {
668
    ptr_to_cur_entry = &cur_entry->sibling;
669
    cur_entry = *ptr_to_cur_entry;
670
  }
671
 
672
  if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
673
    insn_table *new_entry = ZALLOC(insn_table);
674
    new_entry->opcode_nr = new_opcode_nr;
675
    new_entry->expanded_bits = new_bits;
676
    new_entry->opcode_rule = table->opcode_rule->next;
677
    new_entry->sibling = cur_entry;
678
    new_entry->parent = table;
679
    *ptr_to_cur_entry = new_entry;
680
    cur_entry = new_entry;
681
    table->nr_entries++;
682
  }
683
  /* ASSERT new_bits == cur_entry bits */
684
  ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
685
  insn_table_insert_insn(cur_entry,
686
                         old_insn->file_entry,
687
                         old_insn->fields);
688
}
689
 
690
static void
691
insn_table_expand_opcode(insn_table *table,
692
                         insn *instruction,
693
                         int field_nr,
694
                         int opcode_nr,
695
                         insn_bits *bits)
696
{
697
 
698
  if (field_nr > table->opcode->last) {
699
    insn_table_insert_expanded(table, instruction, opcode_nr, bits);
700
  }
701
  else {
702
    insn_field *field = instruction->fields->bits[field_nr];
703
    if (field->is_int || field->is_slash) {
704
      ASSERT(field->first >= table->opcode->first
705
             && field->last <= table->opcode->last);
706
      insn_table_expand_opcode(table, instruction, field->last+1,
707
                               ((opcode_nr << field->width) + field->val_int),
708
                               bits);
709
    }
710
    else {
711
      int val;
712
      int last_pos = ((field->last < table->opcode->last)
713
                        ? field->last : table->opcode->last);
714
      int first_pos = ((field->first > table->opcode->first)
715
                         ? field->first : table->opcode->first);
716
      int width = last_pos - first_pos + 1;
717
      int last_val = (table->opcode->is_boolean
718
                      ? 2 : (1 << width));
719
      for (val = 0; val < last_val; val++) {
720
        insn_bits *new_bits = ZALLOC(insn_bits);
721
        new_bits->field = field;
722
        new_bits->value = val;
723
        new_bits->last = bits;
724
        new_bits->opcode = table->opcode;
725
        insn_table_expand_opcode(table, instruction, last_pos+1,
726
                                 ((opcode_nr << width) | val),
727
                                 new_bits);
728
      }
729
    }
730
  }
731
}
732
 
733
static void
734
insn_table_insert_expanding(insn_table *table,
735
                            insn *entry)
736
{
737
  insn_table_expand_opcode(table,
738
                           entry,
739
                           table->opcode->first,
740
                           0,
741
                           table->expanded_bits);
742
}
743
 
744
 
745
extern void
746
insn_table_expand_insns(insn_table *table)
747
{
748
 
749
  ASSERT(table->nr_insn >= 1);
750
 
751
  /* determine a valid opcode */
752
  while (table->opcode_rule) {
753
    /* specials only for single instructions */
754
    if ((table->nr_insn > 1
755
         && table->opcode_rule->special_mask == 0
756
         && table->opcode_rule->type == normal_decode_rule)
757
        || (table->nr_insn == 1
758
            && table->opcode_rule->special_mask != 0
759
            && ((table->insns->fields->value
760
                 & table->opcode_rule->special_mask)
761
                == table->opcode_rule->special_value))
762
        || (generate_expanded_instructions
763
            && table->opcode_rule->special_mask == 0
764
            && table->opcode_rule->type == normal_decode_rule))
765
      table->opcode =
766
        insn_table_find_opcode_field(table->insns,
767
                                     table->opcode_rule,
768
                                     table->nr_insn == 1/*string*/
769
                                     );
770
    if (table->opcode != NULL)
771
      break;
772
    table->opcode_rule = table->opcode_rule->next;
773
  }
774
 
775
  /* did we find anything */
776
  if (table->opcode == NULL) {
777
    return;
778
  }
779
  ASSERT(table->opcode != NULL);
780
 
781
  /* back link what we found to its parent */
782
  if (table->parent != NULL) {
783
    ASSERT(table->parent->opcode != NULL);
784
    table->opcode->parent = table->parent->opcode;
785
  }
786
 
787
  /* expand the raw instructions according to the opcode */
788
  {
789
    insn *entry;
790
    for (entry = table->insns; entry != NULL; entry = entry->next) {
791
      insn_table_insert_expanding(table, entry);
792
    }
793
  }
794
 
795
  /* and do the same for the sub entries */
796
  {
797
    insn_table *entry;
798
    for (entry = table->entries; entry != NULL; entry =  entry->sibling) {
799
      insn_table_expand_insns(entry);
800
    }
801
  }
802
}
803
 
804
 
805
 
806
 
807
#ifdef MAIN
808
 
809
static void
810
dump_insn_field(insn_field *field,
811
                int indent)
812
{
813
 
814
  printf("(insn_field*)0x%x\n", (unsigned)field);
815
 
816
  dumpf(indent, "(first %d)\n", field->first);
817
 
818
  dumpf(indent, "(last %d)\n", field->last);
819
 
820
  dumpf(indent, "(width %d)\n", field->width);
821
 
822
  if (field->is_int)
823
    dumpf(indent, "(is_int %d)\n", field->val_int);
824
 
825
  if (field->is_slash)
826
    dumpf(indent, "(is_slash)\n");
827
 
828
  if (field->is_string)
829
    dumpf(indent, "(is_string `%s')\n", field->val_string);
830
 
831
  dumpf(indent, "(next 0x%x)\n", field->next);
832
 
833
  dumpf(indent, "(prev 0x%x)\n", field->prev);
834
 
835
 
836
}
837
 
838
static void
839
dump_insn_fields(insn_fields *fields,
840
                 int indent)
841
{
842
  int i;
843
 
844
  printf("(insn_fields*)%p\n", fields);
845
 
846
  dumpf(indent, "(first 0x%x)\n", fields->first);
847
  dumpf(indent, "(last 0x%x)\n", fields->last);
848
 
849
  dumpf(indent, "(value 0x%x)\n", fields->value);
850
 
851
  for (i = 0; i < insn_bit_size; i++) {
852
    dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
853
    dump_insn_field(fields->bits[i], indent+1);
854
    dumpf(indent, " )\n");
855
  }
856
 
857
}
858
 
859
 
860
static void
861
dump_opcode_field(opcode_field *field, int indent, int levels)
862
{
863
  printf("(opcode_field*)%p\n", field);
864
  if (levels && field != NULL) {
865
    dumpf(indent, "(first %d)\n", field->first);
866
    dumpf(indent, "(last %d)\n", field->last);
867
    dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
868
    dumpf(indent, "(parent ");
869
    dump_opcode_field(field->parent, indent, levels-1);
870
  }
871
}
872
 
873
 
874
static void
875
dump_insn_bits(insn_bits *bits, int indent, int levels)
876
{
877
  printf("(insn_bits*)%p\n", bits);
878
 
879
  if (levels && bits != NULL) {
880
    dumpf(indent, "(value %d)\n", bits->value);
881
    dumpf(indent, "(opcode ");
882
    dump_opcode_field(bits->opcode, indent+1, 0);
883
    dumpf(indent, " )\n");
884
    dumpf(indent, "(field ");
885
    dump_insn_field(bits->field, indent+1);
886
    dumpf(indent, " )\n");
887
    dumpf(indent, "(last ");
888
    dump_insn_bits(bits->last, indent+1, levels-1);
889
  }
890
}
891
 
892
 
893
 
894
static void
895
dump_insn(insn *entry, int indent, int levels)
896
{
897
  printf("(insn*)%p\n", entry);
898
 
899
  if (levels && entry != NULL) {
900
 
901
    dumpf(indent, "(file_entry ");
902
    dump_table_entry(entry->file_entry, indent+1);
903
    dumpf(indent, " )\n");
904
 
905
    dumpf(indent, "(fields ");
906
    dump_insn_fields(entry->fields, indent+1);
907
    dumpf(indent, " )\n");
908
 
909
    dumpf(indent, "(next ");
910
    dump_insn(entry->next, indent+1, levels-1);
911
    dumpf(indent, " )\n");
912
 
913
  }
914
 
915
}
916
 
917
 
918
static void
919
dump_insn_table(insn_table *table,
920
                int indent, int levels)
921
{
922
 
923
  printf("(insn_table*)%p\n", table);
924
 
925
  if (levels && table != NULL) {
926
 
927
    dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
928
 
929
    dumpf(indent, "(expanded_bits ");
930
    dump_insn_bits(table->expanded_bits, indent+1, -1);
931
    dumpf(indent, " )\n");
932
 
933
    dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
934
 
935
    dumpf(indent, "(insns ");
936
    dump_insn(table->insns, indent+1, table->nr_insn);
937
    dumpf(indent, " )\n");
938
 
939
    dumpf(indent, "(opcode_rule ");
940
    dump_decode_rule(table->opcode_rule, indent+1);
941
    dumpf(indent, " )\n");
942
 
943
    dumpf(indent, "(opcode ");
944
    dump_opcode_field(table->opcode, indent+1, 1);
945
    dumpf(indent, " )\n");
946
 
947
    dumpf(indent, "(nr_entries %d)\n", table->entries);
948
    dumpf(indent, "(entries ");
949
    dump_insn_table(table->entries, indent+1, table->nr_entries);
950
    dumpf(indent, " )\n");
951
 
952
    dumpf(indent, "(sibling ", table->sibling);
953
    dump_insn_table(table->sibling, indent+1, levels-1);
954
    dumpf(indent, " )\n");
955
 
956
    dumpf(indent, "(parent ", table->parent);
957
    dump_insn_table(table->parent, indent+1, 0);
958
    dumpf(indent, " )\n");
959
 
960
  }
961
}
962
 
963
int insn_bit_size = max_insn_bit_size;
964
int hi_bit_nr;
965
int generate_expanded_instructions;
966
 
967
int
968
main(int argc, char **argv)
969
{
970
  filter *filters = NULL;
971
  decode_table *decode_rules = NULL;
972
  insn_table *instructions = NULL;
973
  cache_table *cache_rules = NULL;
974
 
975
  if (argc != 5)
976
    error("Usage: insn <filter> <hi-bit-nr> <decode-table> <insn-table>\n");
977
 
978
  filters = new_filter(argv[1], filters);
979
  hi_bit_nr = a2i(argv[2]);
980
  ASSERT(hi_bit_nr < insn_bit_size);
981
  decode_rules = load_decode_table(argv[3], hi_bit_nr);
982
  instructions = load_insn_table(argv[4], decode_rules, filters, NULL,
983
                                 &cache_rules);
984
  insn_table_expand_insns(instructions);
985
 
986
  dump_insn_table(instructions, 0, -1);
987
  return 0;
988
}
989
 
990
#endif

powered by: WebSVN 2.1.0

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