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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_58/] [or1ksim/] [cpu/] [or32/] [generate.c] - Blame information for rev 709

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

Line No. Rev Author Line
1 709 markom
/* generate.c -- generates file execgen.c from instruction set
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include <stdarg.h>
24
#include <ctype.h>
25
 
26
#include "config.h"
27
#include "opcode/or32.h"
28
#include "abstract.h"
29
#include "labels.h"
30
#include "parse.h"
31
#include "execute.h"
32
 
33
#define LEAF_FLAG         (0x80000000)
34
#define SHIFT {int i; for (i = 0; i < level; i++) fprintf (fo, "  ");}
35
 
36
extern unsigned long *automata;
37
extern struct temp_insn_struct {
38
  unsigned long insn;
39
  unsigned long insn_mask;
40
  int in_pass;
41
} *ti;
42
 
43
static char *in_file;
44
 
45
inline void debug(int level, const char *format, ...)
46
{
47
  char *p;
48
  va_list ap;
49
 
50
#if DEBUG
51
  if ((p = malloc(1000)) == NULL)
52
    return;
53
  va_start(ap, format);
54
  (void) vsnprintf(p, 1000, format, ap);
55
  va_end(ap);
56
  printf("%s\n", p);
57
  fflush(stdout);
58
  free(p);
59
#endif
60
}
61
 
62
int output_function (FILE *fo, const char *func_name, int level)
63
{
64
  FILE *fi;
65
  if ((fi = fopen (in_file, "rt")) == NULL) return 1;
66
  while (!feof (fi)) {
67
    char line[10000], *str = line;
68
    fgets (str, sizeof (line), fi);
69
    line[sizeof(line) - 1] = 0;
70
    if (strncmp (str, "INSTRUCTION (", 13) == 0) {
71
      char *s;
72
      str += 13;
73
      while (isspace (*str)) str++;
74
      s = str;
75
      while (*s && *s != ')') s++;
76
      *s = 0;
77
      while (isspace(*(s - 1))) s--;
78
      *s = 0;
79
      if (strcmp (str, func_name) == 0) {
80
        char c;
81
        int olevel = 1;
82
        str += strlen (str) + 1;
83
        while (isspace (*str)) str++;
84
        s = str;
85
        while (*s && *s != '\n' && *s != '\r') s++;
86
        *s = 0;
87
        while (isspace(*(s - 1))) s--;
88
        *s = 0;
89
        fprintf (fo, "%s", str);
90
        fprintf (fo, "   /* \"%s\" */\n", func_name);
91
        SHIFT;
92
        do {
93
          c = fgetc (fi);
94
          if (c == '}') {olevel--;}
95
          else if (c == '{') {olevel++;}
96
          fputc (c, fo);
97
          if (c == '\n') SHIFT;
98
        } while (olevel);
99
        return 0;
100
      }
101
    }
102
  }
103
  fprintf (fo, "{\n");
104
  level++;
105
  SHIFT; fprintf (fo, "%s ();\n", func_name);
106
  level--;
107
  SHIFT; fprintf (fo, "}");
108
  return 0;
109
}
110
 
111
/* Parses and puts operands into op[] structure.
112
   Replacement for eval_operands routine. */
113
 
114
static void
115
gen_eval_operands (FILE *fo, int insn_index, int level)
116
{
117
  struct insn_op_struct *opd = op_start[insn_index];
118
  int dis = 0;
119
  int no = 0;
120
  int firstd = 1;
121
 
122
  while (1)
123
    {
124
      int nbits = 0, first = 1;
125
      while (1)
126
        {
127
          SHIFT; fprintf (fo, "tmp %s= ((insn  >> %i) & 0x%08x) << %i;\n", first ? "" : "|", opd->type & OPTYPE_SHR, (1 << opd->data) - 1, nbits);
128
          nbits += opd->data;
129
          if (opd->type & OPTYPE_OP)
130
            break;
131
          opd++;
132
          first = 0;
133
        }
134
 
135
      /* Do we have to sign extend? */
136
      if (opd->type & OPTYPE_SIG)
137
        {
138
          int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
139
          SHIFT; fprintf (fo, "if (tmp & (1 << %i)) tmp |= 0xFFFFFFFF << %i; /* Sign extend */\n", sbit, sbit);
140
        }
141
      if (opd->type & OPTYPE_DIS) {
142
        /* We have to read register later.  */
143
        SHIFT; fprintf (fo, "data %s= tmp;\n", firstd ? "" : "+");
144
        firstd = 0;
145
        dis = 1;
146
      } else
147
        {
148
          if (dis && (opd->type & OPTYPE_REG)) {
149
            SHIFT; fprintf (fo, "op[%i] = data + eval_reg32 (tmp);\n", no);
150
          } else {
151
            SHIFT; fprintf (fo, "op[%i] = tmp;\n", no);
152
          }
153
          SHIFT; fprintf (fo, "op[%i + MAX_OPERANDS] = 0x%08x;\n", no, opd->type | (dis ? OPTYPE_DIS : 0));
154
          no++;
155
          firstd = 1;
156
          dis = 0;
157
        }
158
      if(opd->type & OPTYPE_LAST) {
159
        SHIFT; fprintf (fo, "num_op = %i;\n", no);
160
        return;
161
      }
162
      opd++;
163
    }
164
  SHIFT; fprintf (fo, "num_op = %i;\n", no);
165
}
166
 
167
int output_call (FILE *fo, int index, int level)
168
{
169
  fprintf (fo, "{\n");
170
  level++;
171
  if (index >= 0) {
172
    SHIFT; fprintf (fo, "unsigned long data = 0, tmp = 0, nbits = 0;\n");
173
  }
174
  SHIFT; fprintf (fo, "insn_index = %i;   /* \"%s\" */\n", index, insn_name (index));
175
  if (index >= 0) {
176
    SHIFT; fprintf (fo, "op = &cur->op[0];\n");
177
    //SHIFT; fprintf (fo, "eval_operands (insn, insn_index, &breakpoint);\n");
178
    gen_eval_operands (fo, index, level);
179
  }
180
  SHIFT;
181
  if (index < 0) output_function (fo, "l_invalid", level);
182
  else output_function (fo, or32_opcodes[index].function_name, level);
183
  fprintf (fo, "\n");
184
  level--;
185
  SHIFT; fprintf (fo, "}");
186
  return 0;
187
}
188
 
189
static int generate_header (FILE *fo)
190
{
191
  fprintf (fo, "/* This file was automatically generated by generate (see cpu/or32/generate.c) */\n\n");
192
  fprintf (fo, "static inline void decode_execute (struct iqueue_entry *current, int *breapoint)\n{\n");
193
  fprintf (fo, "  unsigned long insn = current->insn;\n");
194
  fprintf (fo, "  int insn_index = -1;\n");
195
  return 0;
196
}
197
 
198
int generate_footer (FILE *fo)
199
{
200
  fprintf (fo, "  current->insn_index = insn_index;\n");
201
  fprintf (fo, "}\n");
202
  return 0;
203
}
204
 
205
/* Decodes all instructions and generates code for that.  This function
206
   is similar to insn_decode, except it decodes all instructions. */
207
static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
208
{
209
 
210
  int i;
211
  if (!(*a & LEAF_FLAG)) {
212
    unsigned int shift = *a++;
213
    unsigned int mask  = *a++;
214
    int prev_invalid = 0;
215
    fprintf (fo, "\n");
216
    SHIFT; fprintf (fo, "/* (insn >> %i) & 0x%x */\n", shift, mask);
217
    SHIFT; fprintf (fo, "switch ((insn >> %i) & 0x%x) {\n", shift, mask);
218
    level++;
219
 
220
    /* Print each case recursively */
221
    for (i = 0; i <= mask; i++, a++) {
222
      /* Group invalid instruction decodes together */
223
      if (!*a) {
224
        if (prev_invalid) fprintf (fo, "\n");
225
        prev_invalid = 1;
226
        SHIFT; fprintf (fo, "case 0x%02x: ", i);
227
      } else {
228
        if (prev_invalid) {
229
          if (output_call (fo, -1, level)) return 1;
230
          fprintf (fo, "  break;\n");
231
        }
232
        SHIFT; fprintf (fo, "case 0x%02x: ", i);
233
        if (generate_body (fo, automata + *a, cur_mask | (mask << shift), level + 1)) return 1;
234
        prev_invalid = 0;
235
      }
236
    }
237
    if (prev_invalid) {
238
      if (output_call (fo, -1, level)) return 1;
239
      fprintf (fo, "  break;\n");
240
    }
241
    level--;
242
    SHIFT;
243
    if (level > 1)
244
      fprintf (fo, "}  break;\n");
245
    else
246
      fprintf (fo, "}\n");
247
  } else {
248
    i = *a & ~LEAF_FLAG;
249
    /* Final check - do we have direct match?
250
       (based on or32_opcodes this should be the only possibility,
251
       but in case of invalid/missing instruction we must perform a check)  */
252
 
253
    if (ti[i].insn_mask != cur_mask) {
254
      fprintf (fo, "\n");
255
      SHIFT; fprintf (fo, "/* Not unique: real mask %08x and current mask %08x differ - do final check */\n", ti[i].insn_mask, cur_mask);
256
      SHIFT; fprintf (fo, "if ((insn & 0x%08x) == 0x%08x) ", ti[i].insn_mask, ti[i].insn);
257
      output_call (fo, i, level);
258
      fprintf (fo, " else ");
259
      if (output_call (fo, -1, level)) return 1;
260
    } else {
261
      output_call (fo, i, level - 1);
262
    }
263
    fprintf (fo, "  break;\n");
264
  }
265
  return 0;
266
}
267
 
268
/* Main function; it takes two parameters:
269
   input_file(possibly insnset.c) output_file(possibly execgen.c)*/
270
int main (int argc, char *argv[])
271
{
272
  FILE *fo;
273
 
274
  if (argc != 3) {
275
    fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
276
    exit (-1);
277
  }
278
 
279
  in_file = argv[1];
280
  if (!(fo = fopen (argv[2], "wt+"))) {
281
    fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
282
    exit (1);
283
  }
284
 
285
  build_automata ();
286
  if (generate_header (fo)) {fprintf (stderr, "generate_header\n"); return 1;}
287
  if (generate_body (fo, automata, 0, 1)) {fprintf (stderr, "generate_body\n"); return 1;}
288
  if (generate_footer (fo)) {fprintf (stderr, "generate_footer\n"); return 1;}
289
  fclose (fo);
290
  destruct_automata ();
291
  return 0;
292
}

powered by: WebSVN 2.1.0

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