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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [cpu/] [or32/] [generate.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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