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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [m32r/] [mloopx.in] - Blame information for rev 1775

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

Line No. Rev Author Line
1 1181 sfurman
# Simulator main loop for m32rx. -*- C -*-
2
# Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
#
4
# This file is part of the GNU Simulators.
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, or (at your option)
9
# 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 along
17
# with this program; if not, write to the Free Software Foundation, Inc.,
18
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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
                  /* Yep.  Here's the "interesting" [sic] part.  */
293
                  idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
294
                  sc += 3;
295
                  max_insns -= 3;
296
                  icount += 2;
297
                  pc += 4;
298
                  if (IDESC_CTI_P (idesc))
299
                    {
300
                      SET_CTI_VPC (sc - 3);
301
                      break;
302
                    }
303
                }
304
              else /* 2 serial 16 bit insns */
305
                {
306
                  idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
307
                  ++sc;
308
                  --max_insns;
309
                  ++icount;
310
                  pc += 2;
311
                  if (IDESC_CTI_P (idesc))
312
                    {
313
                      SET_CTI_VPC (sc - 1);
314
                      break;
315
                    }
316
                  /* While we're guaranteed that there's room to extract the
317
                     insn, when single stepping we can't; the pbb must stop
318
                     after the first insn.  */
319
                  if (max_insns == 0)
320
                    break;
321
                  idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
322
                  ++sc;
323
                  --max_insns;
324
                  ++icount;
325
                  pc += 2;
326
                  if (IDESC_CTI_P (idesc))
327
                    {
328
                      SET_CTI_VPC (sc - 1);
329
                      break;
330
                    }
331
                }
332
            }
333
        }
334
    }
335
  else /* ! FAST_P */
336
    {
337
      while (max_insns > 0)
338
        {
339
          USI insn = GETIMEMUSI (current_cpu, pc);
340
          int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
341
          int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
342
          SCACHE *cti_sc; /* ??? tmp hack */
343
          if ((SI) insn < 0)
344
            {
345
              /* 32 bit insn
346
                 Only emit before/after handlers if necessary.  */
347
              if (trace_p || profile_p)
348
                {
349
                  idesc = emit_full32 (current_cpu, pc, insn, sc,
350
                                       trace_p, profile_p);
351
                  cti_sc = sc + 1;
352
                  sc += 3;
353
                  max_insns -= 3;
354
                }
355
              else
356
                {
357
                  idesc = emit_32 (current_cpu, pc, insn, sc, 0);
358
                  cti_sc = sc;
359
                  ++sc;
360
                  --max_insns;
361
                }
362
              ++icount;
363
              pc += 4;
364
              if (IDESC_CTI_P (idesc))
365
                {
366
                  SET_CTI_VPC (cti_sc);
367
                  break;
368
                }
369
            }
370
          else
371
            {
372
              if ((insn & 0x8000) != 0) /* parallel? */
373
                {
374
                  /* Yep.  Here's the "interesting" [sic] part.
375
                     Only emit before/after handlers if necessary.  */
376
                  if (trace_p || profile_p)
377
                    {
378
                      idesc = emit_full_parallel (current_cpu, pc, insn, sc,
379
                                                  trace_p, profile_p);
380
                      cti_sc = sc + 1;
381
                      sc += 6;
382
                      max_insns -= 6;
383
                    }
384
                  else
385
                    {
386
                      idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
387
                      cti_sc = sc;
388
                      sc += 3;
389
                      max_insns -= 3;
390
                    }
391
                  icount += 2;
392
                  pc += 4;
393
                  if (IDESC_CTI_P (idesc))
394
                    {
395
                      SET_CTI_VPC (cti_sc);
396
                      break;
397
                    }
398
                }
399
              else /* 2 serial 16 bit insns */
400
                {
401
                  /* Only emit before/after handlers if necessary.  */
402
                  if (trace_p || profile_p)
403
                    {
404
                      idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
405
                                           trace_p, profile_p);
406
                      cti_sc = sc + 1;
407
                      sc += 3;
408
                      max_insns -= 3;
409
                    }
410
                  else
411
                    {
412
                      idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
413
                      cti_sc = sc;
414
                      ++sc;
415
                      --max_insns;
416
                    }
417
                  ++icount;
418
                  pc += 2;
419
                  if (IDESC_CTI_P (idesc))
420
                    {
421
                      SET_CTI_VPC (cti_sc);
422
                      break;
423
                    }
424
                  /* While we're guaranteed that there's room to extract the
425
                     insn, when single stepping we can't; the pbb must stop
426
                     after the first insn.  */
427
                  if (max_insns <= 0)
428
                    break;
429
                  /* Use the same trace/profile address for the 2nd insn.
430
                     Saves us having to compute it and they come in pairs
431
                     anyway (e.g. can never branch to the 2nd insn).  */
432
                  if (trace_p || profile_p)
433
                    {
434
                      idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
435
                                           trace_p, profile_p);
436
                      cti_sc = sc + 1;
437
                      sc += 3;
438
                      max_insns -= 3;
439
                    }
440
                  else
441
                    {
442
                      idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
443
                      cti_sc = sc;
444
                      ++sc;
445
                      --max_insns;
446
                    }
447
                  ++icount;
448
                  pc += 2;
449
                  if (IDESC_CTI_P (idesc))
450
                    {
451
                      SET_CTI_VPC (cti_sc);
452
                      break;
453
                    }
454
                }
455
            }
456
        }
457
    }
458
 
459
 Finish:
460
  SET_INSN_COUNT (icount);
461
}
462
EOF
463
 
464
;;
465
 
466
xfull-exec-pbb)
467
 
468
# Inputs: current_cpu, vpc, FAST_P
469
# Outputs: vpc
470
# vpc is the virtual program counter.
471
 
472
cat <
473
#define DEFINE_SWITCH
474
#include "semx-switch.c"
475
EOF
476
 
477
;;
478
 
479
*)
480
  echo "Invalid argument to mainloop.in: $1" >&2
481
  exit 1
482
  ;;
483
 
484
esac

powered by: WebSVN 2.1.0

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