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

Subversion Repositories or1k

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

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 1342 nogj
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
4 709 markom
 
5
This file is part of OpenRISC 1000 Architectural Simulator.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
 
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <stdarg.h>
25
#include <ctype.h>
26
 
27
#include "config.h"
28
#include "opcode/or32.h"
29
 
30 1342 nogj
static char *in_file;
31
static char *out_file;
32 709 markom
 
33 1342 nogj
/* Whether this instruction stores something in register */
34
static int write_to_reg;
35 709 markom
 
36 1342 nogj
static int out_lines = 0;
37 709 markom
 
38 1342 nogj
void debug(int level, const char *format, ...)
39 709 markom
{
40 1308 phoenix
#if DEBUG
41 709 markom
  char *p;
42
  va_list ap;
43
 
44
  if ((p = malloc(1000)) == NULL)
45
    return;
46
  va_start(ap, format);
47
  (void) vsnprintf(p, 1000, format, ap);
48
  va_end(ap);
49
  printf("%s\n", p);
50
  fflush(stdout);
51
  free(p);
52
#endif
53
}
54
 
55 1342 nogj
static int shift_fprintf(int level, FILE *f, const char *fmt, ...)
56
{
57
  va_list ap;
58
  int i;
59 713 markom
 
60 1342 nogj
  va_start(ap, fmt);
61
  for(i = 0; i < level; i++)
62
    fprintf(f, "  ");
63 712 markom
 
64 1342 nogj
  i = vfprintf(f, fmt, ap);
65
  va_end(ap);
66
 
67
  out_lines++;
68
  return i + (level * 2);
69 712 markom
}
70
 
71 713 markom
/* Generates a execute sequence for one instruction */
72 709 markom
int output_function (FILE *fo, const char *func_name, int level)
73
{
74
  FILE *fi;
75 1342 nogj
  int olevel;
76
  int line_num = 0;
77
 
78
  if ((fi = fopen (in_file, "rt")) == NULL) {
79
    printf("could not open file\n");
80
    return 1;
81
  }
82
 
83 709 markom
  while (!feof (fi)) {
84
    char line[10000], *str = line;
85
    fgets (str, sizeof (line), fi);
86 1342 nogj
    line[sizeof (line) - 1] = 0;
87
    line_num++;
88 709 markom
    if (strncmp (str, "INSTRUCTION (", 13) == 0) {
89
      char *s;
90
      str += 13;
91
      while (isspace (*str)) str++;
92
      s = str;
93
      while (*s && *s != ')') s++;
94
      *s = 0;
95
      while (isspace(*(s - 1))) s--;
96
      *s = 0;
97
      if (strcmp (str, func_name) == 0) {
98 712 markom
        olevel = 1;
99 709 markom
        str += strlen (str) + 1;
100
        while (isspace (*str)) str++;
101
        s = str;
102
        while (*s && *s != '\n' && *s != '\r') s++;
103
        *s = 0;
104
        while (isspace(*(s - 1))) s--;
105
        *s = 0;
106 1342 nogj
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", line_num, in_file);*/
107
        shift_fprintf (level, fo, "%s", str);
108
        shift_fprintf (level, fo, "   /* \"%s\" */\n", func_name);
109 709 markom
        do {
110 712 markom
          fgets (line, sizeof (line), fi);
111
          line[sizeof(line) - 1] = 0;
112
          for (str = line; *str; str++) {
113 1342 nogj
            if (*str == '{') olevel++;
114
            else if (*str == '}') olevel--;
115 712 markom
          }
116 1342 nogj
          shift_fprintf (level, fo, "%s", line);
117 709 markom
        } while (olevel);
118 1342 nogj
        fclose(fi);
119
        /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/
120 709 markom
        return 0;
121
      }
122
    }
123
  }
124 1342 nogj
  shift_fprintf (level, fo, "%s ();\n", func_name);
125 1244 hpanther
 
126
  fclose(fi);
127 709 markom
  return 0;
128
}
129
 
130 1346 nogj
/* Parses operands. */
131 709 markom
 
132 1342 nogj
static int
133 709 markom
gen_eval_operands (FILE *fo, int insn_index, int level)
134
{
135
  struct insn_op_struct *opd = op_start[insn_index];
136 1342 nogj
  int i;
137
  int num_ops;
138
  int nbits = 0;
139
  int set_param = 0;
140 709 markom
  int dis = 0;
141 1342 nogj
  int sbit;
142 1346 nogj
  int dis_op = -1;
143 709 markom
 
144 1342 nogj
  write_to_reg = 0;
145
 
146 1350 nogj
  shift_fprintf (level, fo, "uorreg_t ");
147 1342 nogj
 
148
  /* Count number of operands */
149
  for (i = 0, num_ops = 0;; i++) {
150
    if (!(opd[i].type & OPTYPE_OP))
151
      continue;
152
    if (opd[i].type & OPTYPE_DIS)
153
      continue;
154
    if (num_ops)
155
      fprintf(fo, ", ");
156
    fprintf(fo, "%c", 'a' + num_ops);
157
    num_ops++;
158
    if (opd[i].type & OPTYPE_LAST)
159
      break;
160
  }
161
 
162
  fprintf (fo, ";\n");
163
 
164
  shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops);
165
 
166
  i = 0;
167
  num_ops = 0;
168
  do {
169
/*
170
    printf("opd[%i].type<last> = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0');    printf("opd[%i].type<op> = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0');
171
    printf("opd[%i].type<reg> = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0');
172
    printf("opd[%i].type<sig> = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0');
173
    printf("opd[%i].type<dis> = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0');
174
    printf("opd[%i].type<shr> = %i\n", i, opd->type & OPTYPE_SHR);
175
    printf("opd[%i].type<sbit> = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR);
176
    printf("opd[%i].data = %i\n", i, opd->data);
177
*/
178
 
179
    if (!nbits)
180
      shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops,
181
                     opd->type & OPTYPE_SHR, (1 << opd->data) - 1);
182
    else
183
      shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n",
184
                     'a' + num_ops, opd->type & OPTYPE_SHR,
185
                     (1 << opd->data) - 1, nbits);
186
 
187
    nbits += opd->data;
188
 
189 1346 nogj
    if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) {
190 1342 nogj
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
191 709 markom
      if (opd->type & OPTYPE_SIG)
192 1342 nogj
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
193
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
194
                       0xffffffff << sbit);
195 709 markom
      opd++;
196 1342 nogj
      shift_fprintf (level, fo, "(signed)%c += (signed)reg[(insn >> %i) & 0x%x];\n",
197
                     'a' + num_ops, opd->type & OPTYPE_SHR,
198
                     (1 << opd->data) - 1);
199
      dis = 1;
200 1346 nogj
      dis_op = num_ops;
201 709 markom
    }
202 1342 nogj
 
203
    if (opd->type & OPTYPE_OP) {
204
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
205
      if (opd->type & OPTYPE_SIG)
206
        shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n",
207
                       'a' + num_ops, 1 << sbit, 'a' + num_ops,
208
                       0xffffffff << sbit);
209
      if ((opd->type & OPTYPE_REG) && !dis) {
210
        if(!i) {
211
          shift_fprintf (level, fo, "#define SET_PARAM0(val) reg[a] = val\n");
212
          set_param = 1;
213
        }
214
        shift_fprintf (level, fo, "#define PARAM%i reg[%c]\n", num_ops,
215
                      'a' + num_ops);
216
        if(opd->type & OPTYPE_DST)
217
          write_to_reg = 1;
218
      } else {
219
        shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops,
220
                       'a' + num_ops);
221
      }
222
      num_ops++;
223
      nbits = 0;
224
      dis = 0;
225
    }
226
 
227
    if ((opd->type & OPTYPE_LAST))
228
      break;
229
    opd++;
230
    i++;
231
  } while (1);
232
 
233
  output_function (fo, or32_opcodes[insn_index].function_name, level);
234
 
235
  if (set_param)
236
    shift_fprintf (level, fo, "#undef SET_PARAM\n");
237
 
238
  for (i = 0; i < num_ops; i++)
239
    shift_fprintf (level, fo, "#undef PARAM%i\n", i);
240
 
241 1346 nogj
  return dis_op;
242 709 markom
}
243
 
244 713 markom
/* Generates decode and execute for one instruction instance */
245 1342 nogj
static int output_call (FILE *fo, int index, int level)
246 709 markom
{
247 1346 nogj
  int dis_op = -1;
248 1342 nogj
 
249
  /*printf ("%i:%s\n", index, insn_name (index));*/
250
 
251
  shift_fprintf (level++, fo, "{\n");
252
 
253 717 markom
  if (index >= 0)
254 1346 nogj
    dis_op = gen_eval_operands (fo, index, level);
255 1342 nogj
 
256 709 markom
  if (index < 0) output_function (fo, "l_invalid", level);
257 1342 nogj
 
258 713 markom
  fprintf (fo, "\n");
259 717 markom
 
260 1342 nogj
  shift_fprintf (level++, fo, "if (do_stats) {\n");
261
 
262 1346 nogj
  if (dis_op >= 0)
263
    shift_fprintf (level, fo, "insn_ea = %c;\n", 'a' + dis_op);
264
 
265 1342 nogj
  shift_fprintf (level, fo, "current->insn_index = %i;   /* \"%s\" */\n", index,
266
                 insn_name (index));
267
 
268
  shift_fprintf (level, fo, "analysis(current);\n");
269
  shift_fprintf (--level, fo, "}\n");
270
  if (write_to_reg)
271
    shift_fprintf (level, fo, "reg[0] = 0; /* Repair in case we changed it */\n");
272
  shift_fprintf (--level, fo, "}\n");
273 709 markom
  return 0;
274
}
275
 
276 713 markom
/* Generates .c file header */
277 1342 nogj
static int generate_header (FILE *fo)
278 709 markom
{
279
  fprintf (fo, "/* This file was automatically generated by generate (see cpu/or32/generate.c) */\n\n");
280 712 markom
  fprintf (fo, "static inline void decode_execute (struct iqueue_entry *current)\n{\n");
281 1350 nogj
  fprintf (fo, "  uint32_t insn = current->insn;\n");
282 1342 nogj
  out_lines = 5;
283 709 markom
  return 0;
284
}
285
 
286 713 markom
/* Generates .c file footer */
287 1342 nogj
static int generate_footer (FILE *fo)
288 709 markom
{
289
  fprintf (fo, "}\n");
290
  return 0;
291
}
292
 
293
/* Decodes all instructions and generates code for that.  This function
294
   is similar to insn_decode, except it decodes all instructions. */
295
static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level)
296
{
297 1342 nogj
  unsigned long shift = *a;
298
  unsigned long mask;
299 709 markom
  int i;
300 1342 nogj
  int prev_inv = 0;
301
 
302 709 markom
  if (!(*a & LEAF_FLAG)) {
303 1342 nogj
    shift = *a++;
304
    mask = *a++;
305
    shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift,
306
                   mask);
307 709 markom
    for (i = 0; i <= mask; i++, a++) {
308
      if (!*a) {
309 1342 nogj
        shift_fprintf (level, fo, "case 0x%x:\n", i);
310
        prev_inv = 1;
311 709 markom
      } else {
312 1342 nogj
        if(prev_inv) {
313
          shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
314
          shift_fprintf (level--, fo, "break;\n");
315 709 markom
        }
316 1342 nogj
        shift_fprintf (level, fo, "case 0x%x:\n", i);
317
        generate_body (fo, automata + *a, cur_mask | (mask << shift), ++level);
318
        shift_fprintf (level--, fo, "break;\n");
319
        prev_inv = 0;
320 709 markom
      }
321
    }
322 1342 nogj
    if (prev_inv) {
323
      shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n");
324
      shift_fprintf (level--, fo, "break;\n");
325 709 markom
    }
326 1342 nogj
    shift_fprintf (level, fo, "}\n");
327 709 markom
  } else {
328
    i = *a & ~LEAF_FLAG;
329 1342 nogj
 
330 709 markom
    /* Final check - do we have direct match?
331
       (based on or32_opcodes this should be the only possibility,
332
       but in case of invalid/missing instruction we must perform a check)  */
333
 
334
    if (ti[i].insn_mask != cur_mask) {
335 1342 nogj
      shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", ti[i].insn_mask, cur_mask);
336
      shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n",
337
                     ti[i].insn_mask, ti[i].insn);
338 709 markom
    }
339 1342 nogj
    shift_fprintf (level, fo, "/* Instruction: %s */\n", or32_opcodes[i].name);
340
 
341
    output_call (fo, i, level);
342
 
343
    if (ti[i].insn_mask != cur_mask) {
344
      shift_fprintf (--level, fo, "} else {\n");
345
      shift_fprintf (++level, fo, "/* Invalid insn */\n");
346
      output_call (fo, -1, level);
347
      shift_fprintf (--level, fo, "}\n");
348
    }
349 709 markom
  }
350
  return 0;
351
}
352
 
353
/* Main function; it takes two parameters:
354
   input_file(possibly insnset.c) output_file(possibly execgen.c)*/
355
int main (int argc, char *argv[])
356
{
357
  FILE *fo;
358
 
359
  if (argc != 3) {
360
    fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n");
361
    exit (-1);
362
  }
363
 
364
  in_file = argv[1];
365 1342 nogj
  out_file = argv[2];
366 709 markom
  if (!(fo = fopen (argv[2], "wt+"))) {
367
    fprintf (stderr, "Cannot create '%s'.\n", argv[2]);
368
    exit (1);
369
  }
370
 
371
  build_automata ();
372 1342 nogj
  if (generate_header (fo)) {
373
    fprintf (stderr, "generate_header\n");
374
    return 1;
375
  }
376
 
377
  if (generate_body (fo, automata, 0, 1)) {
378
    fprintf (stderr, "generate_body\n");
379
    return 1;
380
  }
381
 
382
  if (generate_footer (fo)) {
383
    fprintf (stderr, "generate_footer\n");
384
    return 1;
385
  }
386
 
387 709 markom
  fclose (fo);
388
  destruct_automata ();
389
  return 0;
390
}
391 713 markom
 

powered by: WebSVN 2.1.0

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