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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [m32r/] [mloopx.in] - Blame information for rev 301

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

Line No. Rev Author Line
1 24 jeremybenn
# Simulator main loop for m32rx. -*- C -*-
2
#
3
# Copyright 1996, 1997, 1998, 2004, 2007, 2008 Free Software Foundation, Inc.
4
#
5
# This file is part of the GNU Simulators.
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 3 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, see .
19
 
20
# Syntax:
21
# /bin/sh mainloop.in command
22
#
23
# Command is one of:
24
#
25
# init
26
# support
27
# extract-{simple,scache,pbb}
28
# {full,fast}-exec-{simple,scache,pbb}
29
#
30
# A target need only provide a "full" version of one of simple,scache,pbb.
31
# If the target wants it can also provide a fast version of same, or if
32
# the slow (full featured) version is `simple', then the fast version can be
33
# one of scache/pbb.
34
# A target can't provide more than this.
35
 
36
# ??? After a few more ports are done, revisit.
37
# Will eventually need to machine generate a lot of this.
38
 
39
case "x$1" in
40
 
41
xsupport)
42
 
43
cat <
44
 
45
/* Emit insns to write back the results of insns executed in parallel.
46
   SC points to a sufficient number of scache entries for the writeback
47
   handlers.
48
   SC1/ID1 is the first insn (left slot, lower address).
49
   SC2/ID2 is the second insn (right slot, higher address).  */
50
 
51
static INLINE void
52
emit_par_finish (SIM_CPU *current_cpu, PCADDR pc, SCACHE *sc,
53
                 SCACHE *sc1, const IDESC *id1, SCACHE *sc2, const IDESC *id2)
54
{
55
  ARGBUF *abuf;
56
 
57
  abuf = &sc->argbuf;
58
  id1 = id1->par_idesc;
59
  abuf->fields.write.abuf = &sc1->argbuf;
60
  @cpu@_fill_argbuf (current_cpu, abuf, id1, pc, 0);
61
  /* no need to set trace_p,profile_p */
62
#if 0 /* not currently needed for id2 since results written directly */
63
  abuf = &sc[1].argbuf;
64
  id2 = id2->par_idesc;
65
  abuf->fields.write.abuf = &sc2->argbuf;
66
  @cpu@_fill_argbuf (current_cpu, abuf, id2, pc + 2, 0);
67
  /* no need to set trace_p,profile_p */
68
#endif
69
}
70
 
71
static INLINE const IDESC *
72
emit_16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
73
         SCACHE *sc, int fast_p, int parallel_p)
74
{
75
  ARGBUF *abuf = &sc->argbuf;
76
  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
77
 
78
  if (parallel_p)
79
    id = id->par_idesc;
80
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
81
  return id;
82
}
83
 
84
static INLINE const IDESC *
85
emit_full16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
86
             int trace_p, int profile_p)
87
{
88
  const IDESC *id;
89
 
90
  @cpu@_emit_before (current_cpu, sc, pc, 1);
91
  id = emit_16 (current_cpu, pc, insn, sc + 1, 0, 0);
92
  @cpu@_emit_after (current_cpu, sc + 2, pc);
93
  sc[1].argbuf.trace_p = trace_p;
94
  sc[1].argbuf.profile_p = profile_p;
95
  return id;
96
}
97
 
98
static INLINE const IDESC *
99
emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
100
               SCACHE *sc, int fast_p)
101
{
102
  const IDESC *id,*id2;
103
 
104
  /* Emit both insns, then emit a finisher-upper.
105
     We speed things up by handling the second insn serially
106
     [not parallelly].  Then the writeback only has to deal
107
     with the first insn.  */
108
  /* ??? Revisit to handle exceptions right.  */
109
 
110
  /* FIXME: No need to handle this parallely if second is nop.  */
111
  id = emit_16 (current_cpu, pc, insn >> 16, sc, fast_p, 1);
112
 
113
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
114
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, fast_p, 0);
115
 
116
  /* Set sc/snc insns notion of where to skip to.  */
117
  if (IDESC_SKIP_P (id))
118
    SEM_SKIP_COMPILE (current_cpu, sc, 1);
119
 
120
  /* Emit code to finish executing the semantics
121
     (write back the results).  */
122
  emit_par_finish (current_cpu, pc, sc + 2, sc, id, sc + 1, id2);
123
 
124
  return id;
125
}
126
 
127
static INLINE const IDESC *
128
emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
129
                    SCACHE *sc, int trace_p, int profile_p)
130
{
131
  const IDESC *id,*id2;
132
 
133
  /* Emit both insns, then emit a finisher-upper.
134
     We speed things up by handling the second insn serially
135
     [not parallelly].  Then the writeback only has to deal
136
     with the first insn.  */
137
  /* ??? Revisit to handle exceptions right.  */
138
 
139
  @cpu@_emit_before (current_cpu, sc, pc, 1);
140
 
141
  /* FIXME: No need to handle this parallelly if second is nop.  */
142
  id = emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 1);
143
  sc[1].argbuf.trace_p = trace_p;
144
  sc[1].argbuf.profile_p = profile_p;
145
 
146
  @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
147
 
148
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
149
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 3, 0, 0);
150
  sc[3].argbuf.trace_p = trace_p;
151
  sc[3].argbuf.profile_p = profile_p;
152
 
153
  /* Set sc/snc insns notion of where to skip to.  */
154
  if (IDESC_SKIP_P (id))
155
    SEM_SKIP_COMPILE (current_cpu, sc, 4);
156
 
157
  /* Emit code to finish executing the semantics
158
     (write back the results).  */
159
  emit_par_finish (current_cpu, pc, sc + 4, sc + 1, id, sc + 3, id2);
160
 
161
  @cpu@_emit_after (current_cpu, sc + 5, pc);
162
 
163
  return id;
164
}
165
 
166
static INLINE const IDESC *
167
emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
168
         SCACHE *sc, int fast_p)
169
{
170
  ARGBUF *abuf = &sc->argbuf;
171
  const IDESC *id = @cpu@_decode (current_cpu, pc,
172
                                  (USI) insn >> 16, insn, abuf);
173
 
174
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
175
  return id;
176
}
177
 
178
static INLINE const IDESC *
179
emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
180
             int trace_p, int profile_p)
181
{
182
  const IDESC *id;
183
 
184
  @cpu@_emit_before (current_cpu, sc, pc, 1);
185
  id = emit_32 (current_cpu, pc, insn, sc + 1, 0);
186
  @cpu@_emit_after (current_cpu, sc + 2, pc);
187
  sc[1].argbuf.trace_p = trace_p;
188
  sc[1].argbuf.profile_p = profile_p;
189
  return id;
190
}
191
 
192
EOF
193
 
194
;;
195
 
196
xinit)
197
 
198
# Nothing needed.
199
 
200
;;
201
 
202
xextract-pbb)
203
 
204
# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
205
# Outputs: sc, pc
206
# sc must be left pointing past the last created entry.
207
# pc must be left pointing past the last created entry.
208
# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
209
# to record the vpc of the cti insn.
210
# SET_INSN_COUNT(n) must be called to record number of real insns.
211
 
212
cat <
213
{
214
  const IDESC *idesc;
215
  int icount = 0;
216
 
217
  if ((pc & 3) != 0)
218
    {
219
      /* This occurs when single stepping and when compiling the not-taken
220
         part of conditional branches.  */
221
      UHI insn = GETIMEMUHI (current_cpu, pc);
222
      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
223
      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
224
      SCACHE *cti_sc; /* ??? tmp hack */
225
 
226
      /* A parallel insn isn't allowed here, but we don't mind nops.
227
         ??? We need to wait until the insn is executed before signalling
228
         the error, for situations where such signalling is wanted.  */
229
#if 0
230
      if ((insn & 0x8000) != 0
231
          && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
232
        sim_engine_invalid_insn (current_cpu, pc, 0);
233
#endif
234
 
235
      /* Only emit before/after handlers if necessary.  */
236
      if (FAST_P || (! trace_p && ! profile_p))
237
        {
238
          idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
239
          cti_sc = sc;
240
          ++sc;
241
          --max_insns;
242
        }
243
      else
244
        {
245
          idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
246
                               trace_p, profile_p);
247
          cti_sc = sc + 1;
248
          sc += 3;
249
          max_insns -= 3;
250
        }
251
      ++icount;
252
      pc += 2;
253
      if (IDESC_CTI_P (idesc))
254
        {
255
          SET_CTI_VPC (cti_sc);
256
          goto Finish;
257
        }
258
    }
259
 
260
  /* There are two copies of the compiler: full(!fast) and fast.
261
     The "full" case emits before/after handlers for each insn.
262
     Having two copies of this code is a tradeoff, having one copy
263
     seemed a bit more difficult to read (due to constantly testing
264
     FAST_P).  ??? On the other hand, with address ranges we'll want to
265
     omit before/after handlers for unwanted insns.  Having separate loops
266
     for FAST/!FAST avoids constantly doing the test in the loop, but
267
     typically FAST_P is a constant and such tests will get optimized out.  */
268
 
269
  if (FAST_P)
270
    {
271
      while (max_insns > 0)
272
        {
273
          USI insn = GETIMEMUSI (current_cpu, pc);
274
          if ((SI) insn < 0)
275
            {
276
              /* 32 bit insn */
277
              idesc = emit_32 (current_cpu, pc, insn, sc, 1);
278
              ++sc;
279
              --max_insns;
280
              ++icount;
281
              pc += 4;
282
              if (IDESC_CTI_P (idesc))
283
                {
284
                  SET_CTI_VPC (sc - 1);
285
                  break;
286
                }
287
            }
288
          else
289
            {
290
              if ((insn & 0x8000) != 0) /* parallel? */
291
                {
292
                  int up_count;
293
 
294
                  if (((insn >> 16) & 0xfff0) == 0x10f0)
295
                    {
296
                      /* FIXME: No need to handle this sequentially if system
297
                         calls will be able to execute after second insn in
298
                         parallel. ( trap #num || insn ) */
299
                      /* insn */
300
                      idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
301
                                       sc, 1, 0);
302
                      /* trap */
303
                      emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
304
                      up_count = 2;
305
                    }
306
                  else
307
                    {
308
                      /* Yep.  Here's the "interesting" [sic] part.  */
309
                      idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
310
                      up_count = 3;
311
                    }
312
                  sc += up_count;
313
                  max_insns -= up_count;
314
                  icount += 2;
315
                  pc += 4;
316
                  if (IDESC_CTI_P (idesc))
317
                    {
318
                      SET_CTI_VPC (sc - up_count);
319
                      break;
320
                    }
321
                }
322
              else /* 2 serial 16 bit insns */
323
                {
324
                  idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
325
                  ++sc;
326
                  --max_insns;
327
                  ++icount;
328
                  pc += 2;
329
                  if (IDESC_CTI_P (idesc))
330
                    {
331
                      SET_CTI_VPC (sc - 1);
332
                      break;
333
                    }
334
                  /* While we're guaranteed that there's room to extract the
335
                     insn, when single stepping we can't; the pbb must stop
336
                     after the first insn.  */
337
                  if (max_insns == 0)
338
                    break;
339
                  idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
340
                  ++sc;
341
                  --max_insns;
342
                  ++icount;
343
                  pc += 2;
344
                  if (IDESC_CTI_P (idesc))
345
                    {
346
                      SET_CTI_VPC (sc - 1);
347
                      break;
348
                    }
349
                }
350
            }
351
        }
352
    }
353
  else /* ! FAST_P */
354
    {
355
      while (max_insns > 0)
356
        {
357
          USI insn = GETIMEMUSI (current_cpu, pc);
358
          int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
359
          int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
360
          SCACHE *cti_sc; /* ??? tmp hack */
361
          if ((SI) insn < 0)
362
            {
363
              /* 32 bit insn
364
                 Only emit before/after handlers if necessary.  */
365
              if (trace_p || profile_p)
366
                {
367
                  idesc = emit_full32 (current_cpu, pc, insn, sc,
368
                                       trace_p, profile_p);
369
                  cti_sc = sc + 1;
370
                  sc += 3;
371
                  max_insns -= 3;
372
                }
373
              else
374
                {
375
                  idesc = emit_32 (current_cpu, pc, insn, sc, 0);
376
                  cti_sc = sc;
377
                  ++sc;
378
                  --max_insns;
379
                }
380
              ++icount;
381
              pc += 4;
382
              if (IDESC_CTI_P (idesc))
383
                {
384
                  SET_CTI_VPC (cti_sc);
385
                  break;
386
                }
387
            }
388
          else
389
            {
390
              if ((insn & 0x8000) != 0) /* parallel? */
391
                {
392
                  /* Yep.  Here's the "interesting" [sic] part.
393
                     Only emit before/after handlers if necessary.  */
394
                  if (trace_p || profile_p)
395
                    {
396
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
397
                        {
398
                          /* FIXME: No need to handle this sequentially if
399
                             system calls will be able to execute after second
400
                             insn in parallel. ( trap #num || insn ) */
401
                          /* insn */
402
                          idesc = emit_full16 (current_cpu, pc + 2,
403
                                               insn & 0x7fff, sc, 0, 0);
404
                          /* trap */
405
                          emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
406
                                       0, 0);
407
                        }
408
                      else
409
                        {
410
                          idesc = emit_full_parallel (current_cpu, pc, insn,
411
                                                      sc, trace_p, profile_p);
412
                        }
413
                      cti_sc = sc + 1;
414
                      sc += 6;
415
                      max_insns -= 6;
416
                    }
417
                  else
418
                    {
419
                      int up_count;
420
 
421
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
422
                        {
423
                          /* FIXME: No need to handle this sequentially if
424
                             system calls will be able to execute after second
425
                             insn in parallel. ( trap #num || insn ) */
426
                          /* insn */
427
                          idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
428
                                           sc, 0, 0);
429
                          /* trap */
430
                          emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
431
                          up_count = 2;
432
                        }
433
                      else
434
                        {
435
                          idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
436
                          up_count = 3;
437
                        }
438
                      cti_sc = sc;
439
                      sc += up_count;
440
                      max_insns -= up_count;
441
                    }
442
                  icount += 2;
443
                  pc += 4;
444
                  if (IDESC_CTI_P (idesc))
445
                    {
446
                      SET_CTI_VPC (cti_sc);
447
                      break;
448
                    }
449
                }
450
              else /* 2 serial 16 bit insns */
451
                {
452
                  /* Only emit before/after handlers if necessary.  */
453
                  if (trace_p || profile_p)
454
                    {
455
                      idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
456
                                           trace_p, profile_p);
457
                      cti_sc = sc + 1;
458
                      sc += 3;
459
                      max_insns -= 3;
460
                    }
461
                  else
462
                    {
463
                      idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
464
                      cti_sc = sc;
465
                      ++sc;
466
                      --max_insns;
467
                    }
468
                  ++icount;
469
                  pc += 2;
470
                  if (IDESC_CTI_P (idesc))
471
                    {
472
                      SET_CTI_VPC (cti_sc);
473
                      break;
474
                    }
475
                  /* While we're guaranteed that there's room to extract the
476
                     insn, when single stepping we can't; the pbb must stop
477
                     after the first insn.  */
478
                  if (max_insns <= 0)
479
                    break;
480
                  /* Use the same trace/profile address for the 2nd insn.
481
                     Saves us having to compute it and they come in pairs
482
                     anyway (e.g. can never branch to the 2nd insn).  */
483
                  if (trace_p || profile_p)
484
                    {
485
                      idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
486
                                           trace_p, profile_p);
487
                      cti_sc = sc + 1;
488
                      sc += 3;
489
                      max_insns -= 3;
490
                    }
491
                  else
492
                    {
493
                      idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
494
                      cti_sc = sc;
495
                      ++sc;
496
                      --max_insns;
497
                    }
498
                  ++icount;
499
                  pc += 2;
500
                  if (IDESC_CTI_P (idesc))
501
                    {
502
                      SET_CTI_VPC (cti_sc);
503
                      break;
504
                    }
505
                }
506
            }
507
        }
508
    }
509
 
510
 Finish:
511
  SET_INSN_COUNT (icount);
512
}
513
EOF
514
 
515
;;
516
 
517
xfull-exec-pbb)
518
 
519
# Inputs: current_cpu, vpc, FAST_P
520
# Outputs: vpc
521
# vpc is the virtual program counter.
522
 
523
cat <
524
#define DEFINE_SWITCH
525
#include "semx-switch.c"
526
EOF
527
 
528
;;
529
 
530
*)
531
  echo "Invalid argument to mainloop.in: $1" >&2
532
  exit 1
533
  ;;
534
 
535
esac

powered by: WebSVN 2.1.0

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