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

Subversion Repositories or1k

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

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 712 markom
unsigned long op[MAX_OPERANDS];
45
int num_op;
46 709 markom
 
47
inline void debug(int level, const char *format, ...)
48
{
49
  char *p;
50
  va_list ap;
51
 
52
#if DEBUG
53
  if ((p = malloc(1000)) == NULL)
54
    return;
55
  va_start(ap, format);
56
  (void) vsnprintf(p, 1000, format, ap);
57
  va_end(ap);
58
  printf("%s\n", p);
59
  fflush(stdout);
60
  free(p);
61
#endif
62
}
63
 
64 712 markom
static int olevel;
65
 
66
char *replace_operands (FILE *fo, char *str) {
67
  int replace = 0;
68
  if (*str == '}') {olevel--;}
69
  else if (*str == '{') {olevel++;}
70
  else if (strncmp ("eval_operand", str, 12) == 0) {
71
    replace = 1; str += 12;
72
  } else if (strncmp ("set_operand", str, 11) == 0) {
73
    replace = 2; str += 11;
74
  }
75
  if (replace) {
76
    int width, oper;
77
    sscanf (str, "%i(%i", &width, &oper);
78
    while (*str && *str != '(') str++;
79
    while (*str && *str != ',') str++;
80
    str++;
81
    if (replace == 1) {
82
      if (op[oper] & OPTYPE_DIS) {
83
        fprintf (fo, "eval_mem%i (%c", width, 'a' + oper);
84
      } else {
85
        if (op[oper] & OPTYPE_REG) {
86
          fprintf (fo, "eval_reg%i (%c", width, 'a' + oper);
87
        } else {
88
          fprintf (fo, "(%c", 'a' + oper);
89
        }
90
      }
91
    } else {
92
      op[oper] |= OPTYPE_DST;
93
      if (op[oper] & OPTYPE_DIS) {
94
        fprintf (fo, "set_mem%i(%c,", width, 'a' + oper);
95
      } else if (op[oper] & OPTYPE_REG) {
96
        fprintf (fo, "set_reg%i(%c,",width, 'a' + oper);
97
      } else {
98
        fprintf (stderr, "Invalid operand type.\n");
99
        exit (1);
100
      }
101
      while (*str != ',') str = replace_operands (fo, str) + 1;
102
    }
103
    while (*str && *str != ')') str++;
104
    if (op[oper] & OPTYPE_DIS) fprintf (fo, ", &breakpoint)");
105
    else fprintf (fo, ")");
106
  } else {
107
    fputc (*str, fo);
108
  }
109
  return str;
110
}
111
 
112 709 markom
int output_function (FILE *fo, const char *func_name, int level)
113
{
114
  FILE *fi;
115
  if ((fi = fopen (in_file, "rt")) == NULL) return 1;
116
  while (!feof (fi)) {
117
    char line[10000], *str = line;
118
    fgets (str, sizeof (line), fi);
119
    line[sizeof(line) - 1] = 0;
120
    if (strncmp (str, "INSTRUCTION (", 13) == 0) {
121
      char *s;
122
      str += 13;
123
      while (isspace (*str)) str++;
124
      s = str;
125
      while (*s && *s != ')') s++;
126
      *s = 0;
127
      while (isspace(*(s - 1))) s--;
128
      *s = 0;
129
      if (strcmp (str, func_name) == 0) {
130 712 markom
        olevel = 1;
131 709 markom
        str += strlen (str) + 1;
132
        while (isspace (*str)) str++;
133
        s = str;
134
        while (*s && *s != '\n' && *s != '\r') s++;
135
        *s = 0;
136
        while (isspace(*(s - 1))) s--;
137
        *s = 0;
138
        fprintf (fo, "%s", str);
139
        fprintf (fo, "   /* \"%s\" */\n", func_name);
140
        SHIFT;
141
        do {
142 712 markom
          fgets (line, sizeof (line), fi);
143
          line[sizeof(line) - 1] = 0;
144
          for (str = line; *str; str++) {
145
            str = replace_operands (fo, str);
146
          }
147
          SHIFT;
148 709 markom
        } while (olevel);
149
        return 0;
150
      }
151
    }
152
  }
153
  fprintf (fo, "{\n");
154
  level++;
155
  SHIFT; fprintf (fo, "%s ();\n", func_name);
156
  level--;
157
  SHIFT; fprintf (fo, "}");
158
  return 0;
159
}
160
 
161
/* Parses and puts operands into op[] structure.
162
   Replacement for eval_operands routine. */
163
 
164
static void
165
gen_eval_operands (FILE *fo, int insn_index, int level)
166
{
167
  struct insn_op_struct *opd = op_start[insn_index];
168
  int dis = 0;
169
  int no = 0;
170
  int firstd = 1;
171 712 markom
 
172 709 markom
  while (1)
173
    {
174
      int nbits = 0, first = 1;
175
      while (1)
176
        {
177
          SHIFT; fprintf (fo, "tmp %s= ((insn  >> %i) & 0x%08x) << %i;\n", first ? "" : "|", opd->type & OPTYPE_SHR, (1 << opd->data) - 1, nbits);
178
          nbits += opd->data;
179
          if (opd->type & OPTYPE_OP)
180
            break;
181
          opd++;
182
          first = 0;
183
        }
184
 
185
      /* Do we have to sign extend? */
186
      if (opd->type & OPTYPE_SIG)
187
        {
188
          int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
189
          SHIFT; fprintf (fo, "if (tmp & (1 << %i)) tmp |= 0xFFFFFFFF << %i; /* Sign extend */\n", sbit, sbit);
190
        }
191
      if (opd->type & OPTYPE_DIS) {
192
        /* We have to read register later.  */
193
        SHIFT; fprintf (fo, "data %s= tmp;\n", firstd ? "" : "+");
194
        firstd = 0;
195
        dis = 1;
196
      } else
197
        {
198
          if (dis && (opd->type & OPTYPE_REG)) {
199 712 markom
            SHIFT; fprintf (fo, "op[%i] = %c = data + eval_reg32 (tmp);\n", no, 'a' + no);
200 709 markom
          } else {
201 712 markom
            SHIFT; fprintf (fo, "op[%i] = %c = tmp;\n", no, 'a' + no);
202 709 markom
          }
203
          SHIFT; fprintf (fo, "op[%i + MAX_OPERANDS] = 0x%08x;\n", no, opd->type | (dis ? OPTYPE_DIS : 0));
204 712 markom
          op[no] = opd->type | (dis ? OPTYPE_DIS : 0);
205 709 markom
          no++;
206
          firstd = 1;
207
          dis = 0;
208
        }
209
      if(opd->type & OPTYPE_LAST) {
210
        SHIFT; fprintf (fo, "num_op = %i;\n", no);
211 712 markom
        num_op = no;
212 709 markom
        return;
213
      }
214
      opd++;
215
    }
216
  SHIFT; fprintf (fo, "num_op = %i;\n", no);
217
}
218
 
219
int output_call (FILE *fo, int index, int level)
220
{
221 712 markom
  int i;
222
  printf ("%i:%s\n", index, insn_name (index));
223 709 markom
  fprintf (fo, "{\n");
224
  level++;
225
  if (index >= 0) {
226 712 markom
    SHIFT; fprintf (fo, "unsigned long data, tmp;\n");
227
    SHIFT; fprintf (fo, "unsigned long a, b, c; /* operands */\n");
228 709 markom
  }
229
  if (index >= 0) {
230 712 markom
    SHIFT; fprintf (fo, "insn_index = %i;   /* \"%s\" */\n", index, insn_name (index));
231 709 markom
    gen_eval_operands (fo, index, level);
232 712 markom
  } else {
233
    SHIFT; fprintf (fo, "/* insn_index = -1 by default */\n");
234 709 markom
  }
235
  SHIFT;
236
  if (index < 0) output_function (fo, "l_invalid", level);
237
  else output_function (fo, or32_opcodes[index].function_name, level);
238 712 markom
  printf ("\n");
239
  for (i = 0; i < num_op; i++)
240
    if (op[i] & OPTYPE_DST) {
241
      SHIFT; fprintf (fo, "IFF (config.cpu.dependstats) op[%i + MAX_OPERANDS] |= OPTYPE_DST;\n", i);
242
    }
243 709 markom
  level--;
244
  SHIFT; fprintf (fo, "}");
245
  return 0;
246
}
247
 
248
static int generate_header (FILE *fo)
249
{
250
  fprintf (fo, "/* This file was automatically generated by generate (see cpu/or32/generate.c) */\n\n");
251 712 markom
  fprintf (fo, "static inline void decode_execute (struct iqueue_entry *current)\n{\n");
252 709 markom
  fprintf (fo, "  unsigned long insn = current->insn;\n");
253
  fprintf (fo, "  int insn_index = -1;\n");
254 712 markom
  fprintf (fo, "  op = &cur->op[0];\n");
255 709 markom
  return 0;
256
}
257
 
258
int generate_footer (FILE *fo)
259
{
260
  fprintf (fo, "  current->insn_index = insn_index;\n");
261
  fprintf (fo, "}\n");
262
  return 0;
263
}
264
 
265
/* Decodes all instructions and generates code for that.  This function
266
   is similar to insn_decode, except it decodes all instructions. */
267
static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
268
{
269
 
270
  int i;
271
  if (!(*a & LEAF_FLAG)) {
272
    unsigned int shift = *a++;
273
    unsigned int mask  = *a++;
274
    int prev_invalid = 0;
275
    fprintf (fo, "\n");
276
    SHIFT; fprintf (fo, "/* (insn >> %i) & 0x%x */\n", shift, mask);
277
    SHIFT; fprintf (fo, "switch ((insn >> %i) & 0x%x) {\n", shift, mask);
278
    level++;
279
 
280
    /* Print each case recursively */
281
    for (i = 0; i <= mask; i++, a++) {
282
      /* Group invalid instruction decodes together */
283
      if (!*a) {
284
        if (prev_invalid) fprintf (fo, "\n");
285
        prev_invalid = 1;
286
        SHIFT; fprintf (fo, "case 0x%02x: ", i);
287
      } else {
288
        if (prev_invalid) {
289
          if (output_call (fo, -1, level)) return 1;
290
          fprintf (fo, "  break;\n");
291
        }
292
        SHIFT; fprintf (fo, "case 0x%02x: ", i);
293
        if (generate_body (fo, automata + *a, cur_mask | (mask << shift), level + 1)) return 1;
294
        prev_invalid = 0;
295
      }
296
    }
297
    if (prev_invalid) {
298
      if (output_call (fo, -1, level)) return 1;
299
      fprintf (fo, "  break;\n");
300
    }
301
    level--;
302
    if (level > 1)
303
      fprintf (fo, "}  break;\n");
304
    else
305
      fprintf (fo, "}\n");
306
  } else {
307
    i = *a & ~LEAF_FLAG;
308
    /* Final check - do we have direct match?
309
       (based on or32_opcodes this should be the only possibility,
310
       but in case of invalid/missing instruction we must perform a check)  */
311
 
312
    if (ti[i].insn_mask != cur_mask) {
313
      fprintf (fo, "\n");
314
      SHIFT; fprintf (fo, "/* Not unique: real mask %08x and current mask %08x differ - do final check */\n", ti[i].insn_mask, cur_mask);
315
      SHIFT; fprintf (fo, "if ((insn & 0x%08x) == 0x%08x) ", ti[i].insn_mask, ti[i].insn);
316
      output_call (fo, i, level);
317
      fprintf (fo, " else ");
318
      if (output_call (fo, -1, level)) return 1;
319
    } else {
320
      output_call (fo, i, level - 1);
321
    }
322
    fprintf (fo, "  break;\n");
323
  }
324
  return 0;
325
}
326
 
327
/* Main function; it takes two parameters:
328
   input_file(possibly insnset.c) output_file(possibly execgen.c)*/
329
int main (int argc, char *argv[])
330
{
331
  FILE *fo;
332
 
333
  if (argc != 3) {
334
    fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
335
    exit (-1);
336
  }
337
 
338
  in_file = argv[1];
339
  if (!(fo = fopen (argv[2], "wt+"))) {
340
    fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
341
    exit (1);
342
  }
343
 
344
  build_automata ();
345
  if (generate_header (fo)) {fprintf (stderr, "generate_header\n"); return 1;}
346
  if (generate_body (fo, automata, 0, 1)) {fprintf (stderr, "generate_body\n"); return 1;}
347
  if (generate_footer (fo)) {fprintf (stderr, "generate_footer\n"); return 1;}
348
  fclose (fo);
349
  destruct_automata ();
350
  return 0;
351
}

powered by: WebSVN 2.1.0

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