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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [cpu.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _CPU_C_
23
#define _CPU_C_
24
 
25
#include <setjmp.h>
26
 
27
#include "cpu.h"
28
#include "idecode.h"
29
 
30
#ifdef HAVE_STRING_H
31
#include <string.h>
32
#else
33
#ifdef HAVE_STRINGS_H
34
#include <strings.h>
35
#endif
36
#endif
37
 
38
struct _cpu {
39
 
40
  /* the registers */
41
  registers regs;
42
 
43
  /* current instruction address */
44
  unsigned_word program_counter;
45
 
46
  /* the memory maps */
47
  core *physical; /* all of memory */
48
  vm *virtual;
49
  vm_instruction_map *instruction_map; /* instructions */
50
  vm_data_map *data_map; /* data */
51
 
52
  /* the system this processor is contained within */
53
  cpu_mon *monitor;
54
  os_emul *os_emulation;
55
  psim *system;
56
  event_queue *events;
57
  int cpu_nr;
58
 
59
  /* Current CPU model information */
60
  model_data *model_ptr;
61
 
62
#if WITH_IDECODE_CACHE_SIZE
63
  /* a cache to store cracked instructions */
64
  idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
65
#endif
66
 
67
  /* any interrupt state */
68
  interrupts ints;
69
 
70
  /* address reservation: keep the physical address and the contents
71
     of memory at that address */
72
  memory_reservation reservation;
73
 
74
  /* offset from event time to this cpu's idea of the local time */
75
  signed64 time_base_local_time;
76
  signed64 decrementer_local_time;
77
  event_entry_tag decrementer_event;
78
 
79
};
80
 
81
INLINE_CPU\
82
(cpu *)
83
cpu_create(psim *system,
84
           core *memory,
85
           cpu_mon *monitor,
86
           os_emul *os_emulation,
87
           int cpu_nr)
88
{
89
  cpu *processor = ZALLOC(cpu);
90
 
91
  /* create the virtual memory map from the core */
92
  processor->physical = memory;
93
  processor->virtual = vm_create(memory);
94
  processor->instruction_map = vm_create_instruction_map(processor->virtual);
95
  processor->data_map = vm_create_data_map(processor->virtual);
96
 
97
  if (CURRENT_MODEL_ISSUE > 0)
98
    processor->model_ptr = model_create (processor);
99
 
100
  /* link back to core system */
101
  processor->system = system;
102
  processor->events = psim_event_queue(system);
103
  processor->cpu_nr = cpu_nr;
104
  processor->monitor = monitor;
105
  processor->os_emulation = os_emulation;
106
 
107
  return processor;
108
}
109
 
110
 
111
INLINE_CPU\
112
(void)
113
cpu_init(cpu *processor)
114
{
115
  memset(&processor->regs, 0, sizeof(processor->regs));
116
  /* vm init is delayed until after the device tree has been init as
117
     the devices may further init the cpu */
118
  if (CURRENT_MODEL_ISSUE > 0)
119
    model_init (processor->model_ptr);
120
}
121
 
122
 
123
/* find ones way home */
124
 
125
INLINE_CPU\
126
(psim *)
127
cpu_system(cpu *processor)
128
{
129
  return processor->system;
130
}
131
 
132
INLINE_CPU\
133
(int)
134
cpu_nr(cpu *processor)
135
{
136
  return processor->cpu_nr;
137
}
138
 
139
INLINE_CPU\
140
(cpu_mon *)
141
cpu_monitor(cpu *processor)
142
{
143
  return processor->monitor;
144
}
145
 
146
INLINE_CPU\
147
(os_emul *)
148
cpu_os_emulation(cpu *processor)
149
{
150
  return processor->os_emulation;
151
}
152
 
153
INLINE_CPU\
154
(model_data *)
155
cpu_model(cpu *processor)
156
{
157
  return processor->model_ptr;
158
}
159
 
160
 
161
/* program counter manipulation */
162
 
163
INLINE_CPU\
164
(void)
165
cpu_set_program_counter(cpu *processor,
166
                        unsigned_word new_program_counter)
167
{
168
  processor->program_counter = new_program_counter;
169
}
170
 
171
INLINE_CPU\
172
(unsigned_word)
173
cpu_get_program_counter(cpu *processor)
174
{
175
  return processor->program_counter;
176
}
177
 
178
 
179
INLINE_CPU\
180
(void)
181
cpu_restart(cpu *processor,
182
            unsigned_word nia)
183
{
184
  ASSERT(processor != NULL);
185
  cpu_set_program_counter(processor, nia);
186
  psim_restart(processor->system, processor->cpu_nr);
187
}
188
 
189
INLINE_CPU\
190
(void)
191
cpu_halt(cpu *processor,
192
         unsigned_word nia,
193
         stop_reason reason,
194
         int signal)
195
{
196
  ASSERT(processor != NULL);
197
  if (CURRENT_MODEL_ISSUE > 0)
198
    model_halt(processor->model_ptr);
199
  cpu_set_program_counter(processor, nia);
200
  psim_halt(processor->system, processor->cpu_nr, reason, signal);
201
}
202
 
203
EXTERN_CPU\
204
(void)
205
cpu_error(cpu *processor,
206
          unsigned_word cia,
207
          const char *fmt,
208
          ...)
209
{
210
  char message[1024];
211
  va_list ap;
212
 
213
  /* format the message */
214
  va_start(ap, fmt);
215
  vsprintf(message, fmt, ap);
216
  va_end(ap);
217
 
218
  /* sanity check */
219
  if (strlen(message) >= sizeof(message))
220
    error("cpu_error: buffer overflow");
221
 
222
  if (processor != NULL) {
223
    printf_filtered("cpu %d, cia 0x%lx: %s\n",
224
                    processor->cpu_nr + 1, (unsigned long)cia, message);
225
    cpu_halt(processor, cia, was_signalled, -1);
226
  }
227
  else {
228
    error("cpu: %s", message);
229
  }
230
}
231
 
232
 
233
/* The processors local concept of time */
234
 
235
INLINE_CPU\
236
(signed64)
237
cpu_get_time_base(cpu *processor)
238
{
239
  return (event_queue_time(processor->events)
240
          - processor->time_base_local_time);
241
}
242
 
243
INLINE_CPU\
244
(void)
245
cpu_set_time_base(cpu *processor,
246
                  signed64 time_base)
247
{
248
  processor->time_base_local_time = (event_queue_time(processor->events)
249
                                     - time_base);
250
}
251
 
252
INLINE_CPU\
253
(signed32)
254
cpu_get_decrementer(cpu *processor)
255
{
256
  return (processor->decrementer_local_time
257
          - event_queue_time(processor->events));
258
}
259
 
260
STATIC_INLINE_CPU\
261
(void)
262
cpu_decrement_event(void *data)
263
{
264
  cpu *processor = (cpu*)data;
265
  processor->decrementer_event = NULL;
266
  decrementer_interrupt(processor);
267
}
268
 
269
INLINE_CPU\
270
(void)
271
cpu_set_decrementer(cpu *processor,
272
                    signed32 decrementer)
273
{
274
  signed64 old_decrementer = cpu_get_decrementer(processor);
275
  event_queue_deschedule(processor->events, processor->decrementer_event);
276
  processor->decrementer_event = NULL;
277
  processor->decrementer_local_time = (event_queue_time(processor->events)
278
                                       + decrementer);
279
  if (decrementer < 0 && old_decrementer >= 0)
280
    /* A decrementer interrupt occures if the sign of the decrement
281
       register is changed from positive to negative by the load
282
       instruction */
283
    decrementer_interrupt(processor);
284
  else if (decrementer >= 0)
285
    processor->decrementer_event = event_queue_schedule(processor->events,
286
                                                        decrementer,
287
                                                        cpu_decrement_event,
288
                                                        processor);
289
}
290
 
291
 
292
#if WITH_IDECODE_CACHE_SIZE
293
/* allow access to the cpu's instruction cache */
294
INLINE_CPU\
295
(idecode_cache *)
296
cpu_icache_entry(cpu *processor,
297
                 unsigned_word cia)
298
{
299
  return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
300
}
301
 
302
 
303
INLINE_CPU\
304
(void)
305
cpu_flush_icache(cpu *processor)
306
{
307
  int i;
308
  /* force all addresses to 0xff... so that they never hit */
309
  for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
310
    processor->icache[i].address = MASK(0, 63);
311
}
312
#endif
313
 
314
 
315
/* address map revelation */
316
 
317
INLINE_CPU\
318
(vm_instruction_map *)
319
cpu_instruction_map(cpu *processor)
320
{
321
  return processor->instruction_map;
322
}
323
 
324
INLINE_CPU\
325
(vm_data_map *)
326
cpu_data_map(cpu *processor)
327
{
328
  return processor->data_map;
329
}
330
 
331
INLINE_CPU\
332
(void)
333
cpu_page_tlb_invalidate_entry(cpu *processor,
334
                              unsigned_word ea)
335
{
336
  vm_page_tlb_invalidate_entry(processor->virtual, ea);
337
}
338
 
339
INLINE_CPU\
340
(void)
341
cpu_page_tlb_invalidate_all(cpu *processor)
342
{
343
  vm_page_tlb_invalidate_all(processor->virtual);
344
}
345
 
346
 
347
/* interrupt access */
348
 
349
INLINE_CPU\
350
(interrupts *)
351
cpu_interrupts(cpu *processor)
352
{
353
  return &processor->ints;
354
}
355
 
356
 
357
 
358
/* reservation access */
359
 
360
INLINE_CPU\
361
(memory_reservation *)
362
cpu_reservation(cpu *processor)
363
{
364
  return &processor->reservation;
365
}
366
 
367
 
368
/* register access */
369
 
370
INLINE_CPU\
371
(registers *)
372
cpu_registers(cpu *processor)
373
{
374
  return &processor->regs;
375
}
376
 
377
INLINE_CPU\
378
(void)
379
cpu_synchronize_context(cpu *processor,
380
                        unsigned_word cia)
381
{
382
#if (WITH_IDECODE_CACHE_SIZE)
383
  /* kill of the cache */
384
  cpu_flush_icache(processor);
385
#endif
386
 
387
  /* update virtual memory */
388
  vm_synchronize_context(processor->virtual,
389
                         processor->regs.spr,
390
                         processor->regs.sr,
391
                         processor->regs.msr,
392
                         processor, cia);
393
}
394
 
395
 
396
/* might again be useful one day */
397
 
398
INLINE_CPU\
399
(void)
400
cpu_print_info(cpu *processor, int verbose)
401
{
402
}
403
 
404
#endif /* _CPU_C_ */

powered by: WebSVN 2.1.0

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