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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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