1a1ba9ba4Schristos #include "config.h"
2a1ba9ba4Schristos #include <inttypes.h>
3a1ba9ba4Schristos #include <signal.h>
4a1ba9ba4Schristos #include "bfd.h"
5a1ba9ba4Schristos #include "gdb/callback.h"
6a1ba9ba4Schristos #include "gdb/remote-sim.h"
7a1ba9ba4Schristos
8a1ba9ba4Schristos #include "sim-main.h"
9a1ba9ba4Schristos #include "sim-options.h"
10a1ba9ba4Schristos
11a1ba9ba4Schristos #include "gdb/sim-d10v.h"
12a1ba9ba4Schristos #include "gdb/signals.h"
13a1ba9ba4Schristos
14a1ba9ba4Schristos #ifdef HAVE_STRING_H
15a1ba9ba4Schristos #include <string.h>
16a1ba9ba4Schristos #else
17a1ba9ba4Schristos #ifdef HAVE_STRINGS_H
18a1ba9ba4Schristos #include <strings.h>
19a1ba9ba4Schristos #endif /* HAVE_STRING_H */
20a1ba9ba4Schristos #endif /* HAVE_STRINGS_H */
21a1ba9ba4Schristos
22a1ba9ba4Schristos #ifdef HAVE_STDLIB_H
23a1ba9ba4Schristos #include <stdlib.h>
24a1ba9ba4Schristos #endif
25a1ba9ba4Schristos
26a1ba9ba4Schristos enum _leftright { LEFT_FIRST, RIGHT_FIRST };
27a1ba9ba4Schristos
28a1ba9ba4Schristos int d10v_debug;
29a1ba9ba4Schristos
30a1ba9ba4Schristos /* Set this to true to get the previous segment layout. */
31a1ba9ba4Schristos
32a1ba9ba4Schristos int old_segment_mapping;
33a1ba9ba4Schristos
34a1ba9ba4Schristos unsigned long ins_type_counters[ (int)INS_MAX ];
35a1ba9ba4Schristos
36a1ba9ba4Schristos uint16 OP[4];
37a1ba9ba4Schristos
38a1ba9ba4Schristos static long hash (long insn, int format);
39*b2396a7bSchristos static struct hash_entry *lookup_hash (SIM_DESC, SIM_CPU *, uint32 ins, int size);
40a1ba9ba4Schristos static void get_operands (struct simops *s, uint32 ins);
41*b2396a7bSchristos static void do_long (SIM_DESC, SIM_CPU *, uint32 ins);
42*b2396a7bSchristos static void do_2_short (SIM_DESC, SIM_CPU *, uint16 ins1, uint16 ins2, enum _leftright leftright);
43*b2396a7bSchristos static void do_parallel (SIM_DESC, SIM_CPU *, uint16 ins1, uint16 ins2);
44a1ba9ba4Schristos static char *add_commas (char *buf, int sizeof_buf, unsigned long value);
45*b2396a7bSchristos static INLINE uint8 *map_memory (SIM_DESC, SIM_CPU *, unsigned phys_addr);
46a1ba9ba4Schristos
47a1ba9ba4Schristos #define MAX_HASH 63
48a1ba9ba4Schristos struct hash_entry
49a1ba9ba4Schristos {
50a1ba9ba4Schristos struct hash_entry *next;
51a1ba9ba4Schristos uint32 opcode;
52a1ba9ba4Schristos uint32 mask;
53a1ba9ba4Schristos int size;
54a1ba9ba4Schristos struct simops *ops;
55a1ba9ba4Schristos };
56a1ba9ba4Schristos
57a1ba9ba4Schristos struct hash_entry hash_table[MAX_HASH+1];
58a1ba9ba4Schristos
59a1ba9ba4Schristos INLINE static long
hash(long insn,int format)60a1ba9ba4Schristos hash (long insn, int format)
61a1ba9ba4Schristos {
62a1ba9ba4Schristos if (format & LONG_OPCODE)
63a1ba9ba4Schristos return ((insn & 0x3F000000) >> 24);
64a1ba9ba4Schristos else
65a1ba9ba4Schristos return((insn & 0x7E00) >> 9);
66a1ba9ba4Schristos }
67a1ba9ba4Schristos
68a1ba9ba4Schristos INLINE static struct hash_entry *
lookup_hash(SIM_DESC sd,SIM_CPU * cpu,uint32 ins,int size)69*b2396a7bSchristos lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint32 ins, int size)
70a1ba9ba4Schristos {
71a1ba9ba4Schristos struct hash_entry *h;
72a1ba9ba4Schristos
73a1ba9ba4Schristos if (size)
74a1ba9ba4Schristos h = &hash_table[(ins & 0x3F000000) >> 24];
75a1ba9ba4Schristos else
76a1ba9ba4Schristos h = &hash_table[(ins & 0x7E00) >> 9];
77a1ba9ba4Schristos
78a1ba9ba4Schristos while ((ins & h->mask) != h->opcode || h->size != size)
79a1ba9ba4Schristos {
80a1ba9ba4Schristos if (h->next == NULL)
81*b2396a7bSchristos sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGILL);
82a1ba9ba4Schristos h = h->next;
83a1ba9ba4Schristos }
84a1ba9ba4Schristos return (h);
85a1ba9ba4Schristos }
86a1ba9ba4Schristos
87a1ba9ba4Schristos INLINE static void
get_operands(struct simops * s,uint32 ins)88a1ba9ba4Schristos get_operands (struct simops *s, uint32 ins)
89a1ba9ba4Schristos {
90a1ba9ba4Schristos int i, shift, bits, flags;
91a1ba9ba4Schristos uint32 mask;
92a1ba9ba4Schristos for (i=0; i < s->numops; i++)
93a1ba9ba4Schristos {
94a1ba9ba4Schristos shift = s->operands[3*i];
95a1ba9ba4Schristos bits = s->operands[3*i+1];
96a1ba9ba4Schristos flags = s->operands[3*i+2];
97a1ba9ba4Schristos mask = 0x7FFFFFFF >> (31 - bits);
98a1ba9ba4Schristos OP[i] = (ins >> shift) & mask;
99a1ba9ba4Schristos }
100a1ba9ba4Schristos /* FIXME: for tracing, update values that need to be updated each
101a1ba9ba4Schristos instruction decode cycle */
102a1ba9ba4Schristos State.trace.psw = PSW;
103a1ba9ba4Schristos }
104a1ba9ba4Schristos
105a1ba9ba4Schristos static void
do_long(SIM_DESC sd,SIM_CPU * cpu,uint32 ins)106*b2396a7bSchristos do_long (SIM_DESC sd, SIM_CPU *cpu, uint32 ins)
107a1ba9ba4Schristos {
108a1ba9ba4Schristos struct hash_entry *h;
109a1ba9ba4Schristos #ifdef DEBUG
110a1ba9ba4Schristos if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
111*b2396a7bSchristos sim_io_printf (sd, "do_long 0x%x\n", ins);
112a1ba9ba4Schristos #endif
113*b2396a7bSchristos h = lookup_hash (sd, cpu, ins, 1);
114a1ba9ba4Schristos if (h == NULL)
115a1ba9ba4Schristos return;
116a1ba9ba4Schristos get_operands (h->ops, ins);
117a1ba9ba4Schristos State.ins_type = INS_LONG;
118a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
119*b2396a7bSchristos (h->ops->func) (sd, cpu);
120a1ba9ba4Schristos }
121a1ba9ba4Schristos
122a1ba9ba4Schristos static void
do_2_short(SIM_DESC sd,SIM_CPU * cpu,uint16 ins1,uint16 ins2,enum _leftright leftright)123*b2396a7bSchristos do_2_short (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2, enum _leftright leftright)
124a1ba9ba4Schristos {
125a1ba9ba4Schristos struct hash_entry *h;
126a1ba9ba4Schristos enum _ins_type first, second;
127a1ba9ba4Schristos
128a1ba9ba4Schristos #ifdef DEBUG
129a1ba9ba4Schristos if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
130*b2396a7bSchristos sim_io_printf (sd, "do_2_short 0x%x (%s) -> 0x%x\n", ins1,
131*b2396a7bSchristos leftright ? "left" : "right", ins2);
132a1ba9ba4Schristos #endif
133a1ba9ba4Schristos
134a1ba9ba4Schristos if (leftright == LEFT_FIRST)
135a1ba9ba4Schristos {
136a1ba9ba4Schristos first = INS_LEFT;
137a1ba9ba4Schristos second = INS_RIGHT;
138a1ba9ba4Schristos ins_type_counters[ (int)INS_LEFTRIGHT ]++;
139a1ba9ba4Schristos }
140a1ba9ba4Schristos else
141a1ba9ba4Schristos {
142a1ba9ba4Schristos first = INS_RIGHT;
143a1ba9ba4Schristos second = INS_LEFT;
144a1ba9ba4Schristos ins_type_counters[ (int)INS_RIGHTLEFT ]++;
145a1ba9ba4Schristos }
146a1ba9ba4Schristos
147a1ba9ba4Schristos /* Issue the first instruction */
148*b2396a7bSchristos h = lookup_hash (sd, cpu, ins1, 0);
149a1ba9ba4Schristos if (h == NULL)
150a1ba9ba4Schristos return;
151a1ba9ba4Schristos get_operands (h->ops, ins1);
152a1ba9ba4Schristos State.ins_type = first;
153a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
154*b2396a7bSchristos (h->ops->func) (sd, cpu);
155a1ba9ba4Schristos
156a1ba9ba4Schristos /* Issue the second instruction (if the PC hasn't changed) */
157*b2396a7bSchristos if (!State.pc_changed)
158a1ba9ba4Schristos {
159a1ba9ba4Schristos /* finish any existing instructions */
160a1ba9ba4Schristos SLOT_FLUSH ();
161*b2396a7bSchristos h = lookup_hash (sd, cpu, ins2, 0);
162a1ba9ba4Schristos if (h == NULL)
163a1ba9ba4Schristos return;
164a1ba9ba4Schristos get_operands (h->ops, ins2);
165a1ba9ba4Schristos State.ins_type = second;
166a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
167a1ba9ba4Schristos ins_type_counters[ (int)INS_CYCLES ]++;
168*b2396a7bSchristos (h->ops->func) (sd, cpu);
169a1ba9ba4Schristos }
170*b2396a7bSchristos else
171a1ba9ba4Schristos ins_type_counters[ (int)INS_COND_JUMP ]++;
172a1ba9ba4Schristos }
173a1ba9ba4Schristos
174a1ba9ba4Schristos static void
do_parallel(SIM_DESC sd,SIM_CPU * cpu,uint16 ins1,uint16 ins2)175*b2396a7bSchristos do_parallel (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2)
176a1ba9ba4Schristos {
177a1ba9ba4Schristos struct hash_entry *h1, *h2;
178a1ba9ba4Schristos #ifdef DEBUG
179a1ba9ba4Schristos if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
180*b2396a7bSchristos sim_io_printf (sd, "do_parallel 0x%x || 0x%x\n", ins1, ins2);
181a1ba9ba4Schristos #endif
182a1ba9ba4Schristos ins_type_counters[ (int)INS_PARALLEL ]++;
183*b2396a7bSchristos h1 = lookup_hash (sd, cpu, ins1, 0);
184a1ba9ba4Schristos if (h1 == NULL)
185a1ba9ba4Schristos return;
186*b2396a7bSchristos h2 = lookup_hash (sd, cpu, ins2, 0);
187a1ba9ba4Schristos if (h2 == NULL)
188a1ba9ba4Schristos return;
189a1ba9ba4Schristos
190a1ba9ba4Schristos if (h1->ops->exec_type == PARONLY)
191a1ba9ba4Schristos {
192a1ba9ba4Schristos get_operands (h1->ops, ins1);
193a1ba9ba4Schristos State.ins_type = INS_LEFT_COND_TEST;
194a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
195*b2396a7bSchristos (h1->ops->func) (sd, cpu);
196a1ba9ba4Schristos if (State.exe)
197a1ba9ba4Schristos {
198a1ba9ba4Schristos ins_type_counters[ (int)INS_COND_TRUE ]++;
199a1ba9ba4Schristos get_operands (h2->ops, ins2);
200a1ba9ba4Schristos State.ins_type = INS_RIGHT_COND_EXE;
201a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
202*b2396a7bSchristos (h2->ops->func) (sd, cpu);
203a1ba9ba4Schristos }
204a1ba9ba4Schristos else
205a1ba9ba4Schristos ins_type_counters[ (int)INS_COND_FALSE ]++;
206a1ba9ba4Schristos }
207a1ba9ba4Schristos else if (h2->ops->exec_type == PARONLY)
208a1ba9ba4Schristos {
209a1ba9ba4Schristos get_operands (h2->ops, ins2);
210a1ba9ba4Schristos State.ins_type = INS_RIGHT_COND_TEST;
211a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
212*b2396a7bSchristos (h2->ops->func) (sd, cpu);
213a1ba9ba4Schristos if (State.exe)
214a1ba9ba4Schristos {
215a1ba9ba4Schristos ins_type_counters[ (int)INS_COND_TRUE ]++;
216a1ba9ba4Schristos get_operands (h1->ops, ins1);
217a1ba9ba4Schristos State.ins_type = INS_LEFT_COND_EXE;
218a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
219*b2396a7bSchristos (h1->ops->func) (sd, cpu);
220a1ba9ba4Schristos }
221a1ba9ba4Schristos else
222a1ba9ba4Schristos ins_type_counters[ (int)INS_COND_FALSE ]++;
223a1ba9ba4Schristos }
224a1ba9ba4Schristos else
225a1ba9ba4Schristos {
226a1ba9ba4Schristos get_operands (h1->ops, ins1);
227a1ba9ba4Schristos State.ins_type = INS_LEFT_PARALLEL;
228a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
229*b2396a7bSchristos (h1->ops->func) (sd, cpu);
230a1ba9ba4Schristos get_operands (h2->ops, ins2);
231a1ba9ba4Schristos State.ins_type = INS_RIGHT_PARALLEL;
232a1ba9ba4Schristos ins_type_counters[ (int)State.ins_type ]++;
233*b2396a7bSchristos (h2->ops->func) (sd, cpu);
234a1ba9ba4Schristos }
235a1ba9ba4Schristos }
236a1ba9ba4Schristos
237a1ba9ba4Schristos static char *
add_commas(char * buf,int sizeof_buf,unsigned long value)238a1ba9ba4Schristos add_commas (char *buf, int sizeof_buf, unsigned long value)
239a1ba9ba4Schristos {
240a1ba9ba4Schristos int comma = 3;
241a1ba9ba4Schristos char *endbuf = buf + sizeof_buf - 1;
242a1ba9ba4Schristos
243a1ba9ba4Schristos *--endbuf = '\0';
244a1ba9ba4Schristos do {
245a1ba9ba4Schristos if (comma-- == 0)
246a1ba9ba4Schristos {
247a1ba9ba4Schristos *--endbuf = ',';
248a1ba9ba4Schristos comma = 2;
249a1ba9ba4Schristos }
250a1ba9ba4Schristos
251a1ba9ba4Schristos *--endbuf = (value % 10) + '0';
252a1ba9ba4Schristos } while ((value /= 10) != 0);
253a1ba9ba4Schristos
254a1ba9ba4Schristos return endbuf;
255a1ba9ba4Schristos }
256a1ba9ba4Schristos
257*b2396a7bSchristos static void
sim_size(int power)258a1ba9ba4Schristos sim_size (int power)
259a1ba9ba4Schristos {
260a1ba9ba4Schristos int i;
261a1ba9ba4Schristos for (i = 0; i < IMEM_SEGMENTS; i++)
262a1ba9ba4Schristos {
263a1ba9ba4Schristos if (State.mem.insn[i])
264a1ba9ba4Schristos free (State.mem.insn[i]);
265a1ba9ba4Schristos }
266a1ba9ba4Schristos for (i = 0; i < DMEM_SEGMENTS; i++)
267a1ba9ba4Schristos {
268a1ba9ba4Schristos if (State.mem.data[i])
269a1ba9ba4Schristos free (State.mem.data[i]);
270a1ba9ba4Schristos }
271a1ba9ba4Schristos for (i = 0; i < UMEM_SEGMENTS; i++)
272a1ba9ba4Schristos {
273a1ba9ba4Schristos if (State.mem.unif[i])
274a1ba9ba4Schristos free (State.mem.unif[i]);
275a1ba9ba4Schristos }
276a1ba9ba4Schristos /* Always allocate dmem segment 0. This contains the IMAP and DMAP
277a1ba9ba4Schristos registers. */
278a1ba9ba4Schristos State.mem.data[0] = calloc (1, SEGMENT_SIZE);
279a1ba9ba4Schristos }
280a1ba9ba4Schristos
281a1ba9ba4Schristos /* For tracing - leave info on last access around. */
282a1ba9ba4Schristos static char *last_segname = "invalid";
283a1ba9ba4Schristos static char *last_from = "invalid";
284a1ba9ba4Schristos static char *last_to = "invalid";
285a1ba9ba4Schristos
286a1ba9ba4Schristos enum
287a1ba9ba4Schristos {
288a1ba9ba4Schristos IMAP0_OFFSET = 0xff00,
289a1ba9ba4Schristos DMAP0_OFFSET = 0xff08,
290a1ba9ba4Schristos DMAP2_SHADDOW = 0xff04,
291a1ba9ba4Schristos DMAP2_OFFSET = 0xff0c
292a1ba9ba4Schristos };
293a1ba9ba4Schristos
294a1ba9ba4Schristos static void
set_dmap_register(SIM_DESC sd,int reg_nr,unsigned long value)295*b2396a7bSchristos set_dmap_register (SIM_DESC sd, int reg_nr, unsigned long value)
296a1ba9ba4Schristos {
297*b2396a7bSchristos uint8 *raw = map_memory (sd, NULL, SIM_D10V_MEMORY_DATA
298a1ba9ba4Schristos + DMAP0_OFFSET + 2 * reg_nr);
299a1ba9ba4Schristos WRITE_16 (raw, value);
300a1ba9ba4Schristos #ifdef DEBUG
301a1ba9ba4Schristos if ((d10v_debug & DEBUG_MEMORY))
302a1ba9ba4Schristos {
303*b2396a7bSchristos sim_io_printf (sd, "mem: dmap%d=0x%04lx\n", reg_nr, value);
304a1ba9ba4Schristos }
305a1ba9ba4Schristos #endif
306a1ba9ba4Schristos }
307a1ba9ba4Schristos
308a1ba9ba4Schristos static unsigned long
dmap_register(SIM_DESC sd,SIM_CPU * cpu,void * regcache,int reg_nr)309*b2396a7bSchristos dmap_register (SIM_DESC sd, SIM_CPU *cpu, void *regcache, int reg_nr)
310a1ba9ba4Schristos {
311*b2396a7bSchristos uint8 *raw = map_memory (sd, cpu, SIM_D10V_MEMORY_DATA
312a1ba9ba4Schristos + DMAP0_OFFSET + 2 * reg_nr);
313a1ba9ba4Schristos return READ_16 (raw);
314a1ba9ba4Schristos }
315a1ba9ba4Schristos
316a1ba9ba4Schristos static void
set_imap_register(SIM_DESC sd,int reg_nr,unsigned long value)317*b2396a7bSchristos set_imap_register (SIM_DESC sd, int reg_nr, unsigned long value)
318a1ba9ba4Schristos {
319*b2396a7bSchristos uint8 *raw = map_memory (sd, NULL, SIM_D10V_MEMORY_DATA
320a1ba9ba4Schristos + IMAP0_OFFSET + 2 * reg_nr);
321a1ba9ba4Schristos WRITE_16 (raw, value);
322a1ba9ba4Schristos #ifdef DEBUG
323a1ba9ba4Schristos if ((d10v_debug & DEBUG_MEMORY))
324a1ba9ba4Schristos {
325*b2396a7bSchristos sim_io_printf (sd, "mem: imap%d=0x%04lx\n", reg_nr, value);
326a1ba9ba4Schristos }
327a1ba9ba4Schristos #endif
328a1ba9ba4Schristos }
329a1ba9ba4Schristos
330a1ba9ba4Schristos static unsigned long
imap_register(SIM_DESC sd,SIM_CPU * cpu,void * regcache,int reg_nr)331*b2396a7bSchristos imap_register (SIM_DESC sd, SIM_CPU *cpu, void *regcache, int reg_nr)
332a1ba9ba4Schristos {
333*b2396a7bSchristos uint8 *raw = map_memory (sd, cpu, SIM_D10V_MEMORY_DATA
334a1ba9ba4Schristos + IMAP0_OFFSET + 2 * reg_nr);
335a1ba9ba4Schristos return READ_16 (raw);
336a1ba9ba4Schristos }
337a1ba9ba4Schristos
338a1ba9ba4Schristos enum
339a1ba9ba4Schristos {
340a1ba9ba4Schristos HELD_SPI_IDX = 0,
341a1ba9ba4Schristos HELD_SPU_IDX = 1
342a1ba9ba4Schristos };
343a1ba9ba4Schristos
344a1ba9ba4Schristos static unsigned long
spu_register(void)345a1ba9ba4Schristos spu_register (void)
346a1ba9ba4Schristos {
347a1ba9ba4Schristos if (PSW_SM)
348a1ba9ba4Schristos return GPR (SP_IDX);
349a1ba9ba4Schristos else
350a1ba9ba4Schristos return HELD_SP (HELD_SPU_IDX);
351a1ba9ba4Schristos }
352a1ba9ba4Schristos
353a1ba9ba4Schristos static unsigned long
spi_register(void)354a1ba9ba4Schristos spi_register (void)
355a1ba9ba4Schristos {
356a1ba9ba4Schristos if (!PSW_SM)
357a1ba9ba4Schristos return GPR (SP_IDX);
358a1ba9ba4Schristos else
359a1ba9ba4Schristos return HELD_SP (HELD_SPI_IDX);
360a1ba9ba4Schristos }
361a1ba9ba4Schristos
362a1ba9ba4Schristos static void
set_spi_register(unsigned long value)363a1ba9ba4Schristos set_spi_register (unsigned long value)
364a1ba9ba4Schristos {
365a1ba9ba4Schristos if (!PSW_SM)
366a1ba9ba4Schristos SET_GPR (SP_IDX, value);
367a1ba9ba4Schristos SET_HELD_SP (HELD_SPI_IDX, value);
368a1ba9ba4Schristos }
369a1ba9ba4Schristos
370a1ba9ba4Schristos static void
set_spu_register(unsigned long value)371a1ba9ba4Schristos set_spu_register (unsigned long value)
372a1ba9ba4Schristos {
373a1ba9ba4Schristos if (PSW_SM)
374a1ba9ba4Schristos SET_GPR (SP_IDX, value);
375a1ba9ba4Schristos SET_HELD_SP (HELD_SPU_IDX, value);
376a1ba9ba4Schristos }
377a1ba9ba4Schristos
378a1ba9ba4Schristos /* Given a virtual address in the DMAP address space, translate it
379a1ba9ba4Schristos into a physical address. */
380a1ba9ba4Schristos
381*b2396a7bSchristos static unsigned long
sim_d10v_translate_dmap_addr(SIM_DESC sd,SIM_CPU * cpu,unsigned long offset,int nr_bytes,unsigned long * phys,void * regcache,unsigned long (* dmap_register)(SIM_DESC,SIM_CPU *,void * regcache,int reg_nr))382*b2396a7bSchristos sim_d10v_translate_dmap_addr (SIM_DESC sd,
383*b2396a7bSchristos SIM_CPU *cpu,
384*b2396a7bSchristos unsigned long offset,
385a1ba9ba4Schristos int nr_bytes,
386a1ba9ba4Schristos unsigned long *phys,
387a1ba9ba4Schristos void *regcache,
388*b2396a7bSchristos unsigned long (*dmap_register) (SIM_DESC,
389*b2396a7bSchristos SIM_CPU *,
390*b2396a7bSchristos void *regcache,
391a1ba9ba4Schristos int reg_nr))
392a1ba9ba4Schristos {
393a1ba9ba4Schristos short map;
394a1ba9ba4Schristos int regno;
395a1ba9ba4Schristos last_from = "logical-data";
396a1ba9ba4Schristos if (offset >= DMAP_BLOCK_SIZE * SIM_D10V_NR_DMAP_REGS)
397a1ba9ba4Schristos {
398a1ba9ba4Schristos /* Logical address out side of data segments, not supported */
399a1ba9ba4Schristos return 0;
400a1ba9ba4Schristos }
401a1ba9ba4Schristos regno = (offset / DMAP_BLOCK_SIZE);
402a1ba9ba4Schristos offset = (offset % DMAP_BLOCK_SIZE);
403a1ba9ba4Schristos if ((offset % DMAP_BLOCK_SIZE) + nr_bytes > DMAP_BLOCK_SIZE)
404a1ba9ba4Schristos {
405a1ba9ba4Schristos /* Don't cross a BLOCK boundary */
406a1ba9ba4Schristos nr_bytes = DMAP_BLOCK_SIZE - (offset % DMAP_BLOCK_SIZE);
407a1ba9ba4Schristos }
408*b2396a7bSchristos map = dmap_register (sd, cpu, regcache, regno);
409a1ba9ba4Schristos if (regno == 3)
410a1ba9ba4Schristos {
411a1ba9ba4Schristos /* Always maps to data memory */
412a1ba9ba4Schristos int iospi = (offset / 0x1000) % 4;
413a1ba9ba4Schristos int iosp = (map >> (4 * (3 - iospi))) % 0x10;
414a1ba9ba4Schristos last_to = "io-space";
415a1ba9ba4Schristos *phys = (SIM_D10V_MEMORY_DATA + (iosp * 0x10000) + 0xc000 + offset);
416a1ba9ba4Schristos }
417a1ba9ba4Schristos else
418a1ba9ba4Schristos {
419a1ba9ba4Schristos int sp = ((map & 0x3000) >> 12);
420a1ba9ba4Schristos int segno = (map & 0x3ff);
421a1ba9ba4Schristos switch (sp)
422a1ba9ba4Schristos {
423a1ba9ba4Schristos case 0: /* 00: Unified memory */
424a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_UNIFIED + (segno * DMAP_BLOCK_SIZE) + offset;
425a1ba9ba4Schristos last_to = "unified";
426a1ba9ba4Schristos break;
427a1ba9ba4Schristos case 1: /* 01: Instruction Memory */
428a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_INSN + (segno * DMAP_BLOCK_SIZE) + offset;
429a1ba9ba4Schristos last_to = "chip-insn";
430a1ba9ba4Schristos break;
431a1ba9ba4Schristos case 2: /* 10: Internal data memory */
432a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_DATA + (segno << 16) + (regno * DMAP_BLOCK_SIZE) + offset;
433a1ba9ba4Schristos last_to = "chip-data";
434a1ba9ba4Schristos break;
435a1ba9ba4Schristos case 3: /* 11: Reserved */
436a1ba9ba4Schristos return 0;
437a1ba9ba4Schristos }
438a1ba9ba4Schristos }
439a1ba9ba4Schristos return nr_bytes;
440a1ba9ba4Schristos }
441a1ba9ba4Schristos
442a1ba9ba4Schristos /* Given a virtual address in the IMAP address space, translate it
443a1ba9ba4Schristos into a physical address. */
444a1ba9ba4Schristos
445*b2396a7bSchristos static unsigned long
sim_d10v_translate_imap_addr(SIM_DESC sd,SIM_CPU * cpu,unsigned long offset,int nr_bytes,unsigned long * phys,void * regcache,unsigned long (* imap_register)(SIM_DESC,SIM_CPU *,void * regcache,int reg_nr))446*b2396a7bSchristos sim_d10v_translate_imap_addr (SIM_DESC sd,
447*b2396a7bSchristos SIM_CPU *cpu,
448*b2396a7bSchristos unsigned long offset,
449a1ba9ba4Schristos int nr_bytes,
450a1ba9ba4Schristos unsigned long *phys,
451a1ba9ba4Schristos void *regcache,
452*b2396a7bSchristos unsigned long (*imap_register) (SIM_DESC,
453*b2396a7bSchristos SIM_CPU *,
454*b2396a7bSchristos void *regcache,
455a1ba9ba4Schristos int reg_nr))
456a1ba9ba4Schristos {
457a1ba9ba4Schristos short map;
458a1ba9ba4Schristos int regno;
459a1ba9ba4Schristos int sp;
460a1ba9ba4Schristos int segno;
461a1ba9ba4Schristos last_from = "logical-insn";
462a1ba9ba4Schristos if (offset >= (IMAP_BLOCK_SIZE * SIM_D10V_NR_IMAP_REGS))
463a1ba9ba4Schristos {
464a1ba9ba4Schristos /* Logical address outside of IMAP segments, not supported */
465a1ba9ba4Schristos return 0;
466a1ba9ba4Schristos }
467a1ba9ba4Schristos regno = (offset / IMAP_BLOCK_SIZE);
468a1ba9ba4Schristos offset = (offset % IMAP_BLOCK_SIZE);
469a1ba9ba4Schristos if (offset + nr_bytes > IMAP_BLOCK_SIZE)
470a1ba9ba4Schristos {
471a1ba9ba4Schristos /* Don't cross a BLOCK boundary */
472a1ba9ba4Schristos nr_bytes = IMAP_BLOCK_SIZE - offset;
473a1ba9ba4Schristos }
474*b2396a7bSchristos map = imap_register (sd, cpu, regcache, regno);
475a1ba9ba4Schristos sp = (map & 0x3000) >> 12;
476a1ba9ba4Schristos segno = (map & 0x007f);
477a1ba9ba4Schristos switch (sp)
478a1ba9ba4Schristos {
479a1ba9ba4Schristos case 0: /* 00: unified memory */
480a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_UNIFIED + (segno << 17) + offset;
481a1ba9ba4Schristos last_to = "unified";
482a1ba9ba4Schristos break;
483a1ba9ba4Schristos case 1: /* 01: instruction memory */
484a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_INSN + (IMAP_BLOCK_SIZE * regno) + offset;
485a1ba9ba4Schristos last_to = "chip-insn";
486a1ba9ba4Schristos break;
487a1ba9ba4Schristos case 2: /*10*/
488a1ba9ba4Schristos /* Reserved. */
489a1ba9ba4Schristos return 0;
490a1ba9ba4Schristos case 3: /* 11: for testing - instruction memory */
491a1ba9ba4Schristos offset = (offset % 0x800);
492a1ba9ba4Schristos *phys = SIM_D10V_MEMORY_INSN + offset;
493a1ba9ba4Schristos if (offset + nr_bytes > 0x800)
494a1ba9ba4Schristos /* don't cross VM boundary */
495a1ba9ba4Schristos nr_bytes = 0x800 - offset;
496a1ba9ba4Schristos last_to = "test-insn";
497a1ba9ba4Schristos break;
498a1ba9ba4Schristos }
499a1ba9ba4Schristos return nr_bytes;
500a1ba9ba4Schristos }
501a1ba9ba4Schristos
502*b2396a7bSchristos static unsigned long
sim_d10v_translate_addr(SIM_DESC sd,SIM_CPU * cpu,unsigned long memaddr,int nr_bytes,unsigned long * targ_addr,void * regcache,unsigned long (* dmap_register)(SIM_DESC,SIM_CPU *,void * regcache,int reg_nr),unsigned long (* imap_register)(SIM_DESC,SIM_CPU *,void * regcache,int reg_nr))503*b2396a7bSchristos sim_d10v_translate_addr (SIM_DESC sd,
504*b2396a7bSchristos SIM_CPU *cpu,
505*b2396a7bSchristos unsigned long memaddr,
506a1ba9ba4Schristos int nr_bytes,
507a1ba9ba4Schristos unsigned long *targ_addr,
508a1ba9ba4Schristos void *regcache,
509*b2396a7bSchristos unsigned long (*dmap_register) (SIM_DESC,
510*b2396a7bSchristos SIM_CPU *,
511*b2396a7bSchristos void *regcache,
512a1ba9ba4Schristos int reg_nr),
513*b2396a7bSchristos unsigned long (*imap_register) (SIM_DESC,
514*b2396a7bSchristos SIM_CPU *,
515*b2396a7bSchristos void *regcache,
516a1ba9ba4Schristos int reg_nr))
517a1ba9ba4Schristos {
518a1ba9ba4Schristos unsigned long phys;
519a1ba9ba4Schristos unsigned long seg;
520a1ba9ba4Schristos unsigned long off;
521a1ba9ba4Schristos
522a1ba9ba4Schristos last_from = "unknown";
523a1ba9ba4Schristos last_to = "unknown";
524a1ba9ba4Schristos
525a1ba9ba4Schristos seg = (memaddr >> 24);
526a1ba9ba4Schristos off = (memaddr & 0xffffffL);
527a1ba9ba4Schristos
528a1ba9ba4Schristos /* However, if we've asked to use the previous generation of segment
529a1ba9ba4Schristos mapping, rearrange the segments as follows. */
530a1ba9ba4Schristos
531a1ba9ba4Schristos if (old_segment_mapping)
532a1ba9ba4Schristos {
533a1ba9ba4Schristos switch (seg)
534a1ba9ba4Schristos {
535a1ba9ba4Schristos case 0x00: /* DMAP translated memory */
536a1ba9ba4Schristos seg = 0x10;
537a1ba9ba4Schristos break;
538a1ba9ba4Schristos case 0x01: /* IMAP translated memory */
539a1ba9ba4Schristos seg = 0x11;
540a1ba9ba4Schristos break;
541a1ba9ba4Schristos case 0x10: /* On-chip data memory */
542a1ba9ba4Schristos seg = 0x02;
543a1ba9ba4Schristos break;
544a1ba9ba4Schristos case 0x11: /* On-chip insn memory */
545a1ba9ba4Schristos seg = 0x01;
546a1ba9ba4Schristos break;
547a1ba9ba4Schristos case 0x12: /* Unified memory */
548a1ba9ba4Schristos seg = 0x00;
549a1ba9ba4Schristos break;
550a1ba9ba4Schristos }
551a1ba9ba4Schristos }
552a1ba9ba4Schristos
553a1ba9ba4Schristos switch (seg)
554a1ba9ba4Schristos {
555a1ba9ba4Schristos case 0x00: /* Physical unified memory */
556a1ba9ba4Schristos last_from = "phys-unified";
557a1ba9ba4Schristos last_to = "unified";
558a1ba9ba4Schristos phys = SIM_D10V_MEMORY_UNIFIED + off;
559a1ba9ba4Schristos if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
560a1ba9ba4Schristos nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
561a1ba9ba4Schristos break;
562a1ba9ba4Schristos
563a1ba9ba4Schristos case 0x01: /* Physical instruction memory */
564a1ba9ba4Schristos last_from = "phys-insn";
565a1ba9ba4Schristos last_to = "chip-insn";
566a1ba9ba4Schristos phys = SIM_D10V_MEMORY_INSN + off;
567a1ba9ba4Schristos if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
568a1ba9ba4Schristos nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
569a1ba9ba4Schristos break;
570a1ba9ba4Schristos
571a1ba9ba4Schristos case 0x02: /* Physical data memory segment */
572a1ba9ba4Schristos last_from = "phys-data";
573a1ba9ba4Schristos last_to = "chip-data";
574a1ba9ba4Schristos phys = SIM_D10V_MEMORY_DATA + off;
575a1ba9ba4Schristos if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
576a1ba9ba4Schristos nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
577a1ba9ba4Schristos break;
578a1ba9ba4Schristos
579a1ba9ba4Schristos case 0x10: /* in logical data address segment */
580*b2396a7bSchristos nr_bytes = sim_d10v_translate_dmap_addr (sd, cpu, off, nr_bytes, &phys,
581*b2396a7bSchristos regcache, dmap_register);
582a1ba9ba4Schristos break;
583a1ba9ba4Schristos
584a1ba9ba4Schristos case 0x11: /* in logical instruction address segment */
585*b2396a7bSchristos nr_bytes = sim_d10v_translate_imap_addr (sd, cpu, off, nr_bytes, &phys,
586*b2396a7bSchristos regcache, imap_register);
587a1ba9ba4Schristos break;
588a1ba9ba4Schristos
589a1ba9ba4Schristos default:
590a1ba9ba4Schristos return 0;
591a1ba9ba4Schristos }
592a1ba9ba4Schristos
593a1ba9ba4Schristos *targ_addr = phys;
594a1ba9ba4Schristos return nr_bytes;
595a1ba9ba4Schristos }
596a1ba9ba4Schristos
597a1ba9ba4Schristos /* Return a pointer into the raw buffer designated by phys_addr. It
598a1ba9ba4Schristos is assumed that the client has already ensured that the access
599a1ba9ba4Schristos isn't going to cross a segment boundary. */
600a1ba9ba4Schristos
601a1ba9ba4Schristos uint8 *
map_memory(SIM_DESC sd,SIM_CPU * cpu,unsigned phys_addr)602*b2396a7bSchristos map_memory (SIM_DESC sd, SIM_CPU *cpu, unsigned phys_addr)
603a1ba9ba4Schristos {
604a1ba9ba4Schristos uint8 **memory;
605a1ba9ba4Schristos uint8 *raw;
606a1ba9ba4Schristos unsigned offset;
607a1ba9ba4Schristos int segment = ((phys_addr >> 24) & 0xff);
608a1ba9ba4Schristos
609a1ba9ba4Schristos switch (segment)
610a1ba9ba4Schristos {
611a1ba9ba4Schristos
612a1ba9ba4Schristos case 0x00: /* Unified memory */
613a1ba9ba4Schristos {
614a1ba9ba4Schristos memory = &State.mem.unif[(phys_addr / SEGMENT_SIZE) % UMEM_SEGMENTS];
615a1ba9ba4Schristos last_segname = "umem";
616a1ba9ba4Schristos break;
617a1ba9ba4Schristos }
618a1ba9ba4Schristos
619a1ba9ba4Schristos case 0x01: /* On-chip insn memory */
620a1ba9ba4Schristos {
621a1ba9ba4Schristos memory = &State.mem.insn[(phys_addr / SEGMENT_SIZE) % IMEM_SEGMENTS];
622a1ba9ba4Schristos last_segname = "imem";
623a1ba9ba4Schristos break;
624a1ba9ba4Schristos }
625a1ba9ba4Schristos
626a1ba9ba4Schristos case 0x02: /* On-chip data memory */
627a1ba9ba4Schristos {
628a1ba9ba4Schristos if ((phys_addr & 0xff00) == 0xff00)
629a1ba9ba4Schristos {
630a1ba9ba4Schristos phys_addr = (phys_addr & 0xffff);
631a1ba9ba4Schristos if (phys_addr == DMAP2_SHADDOW)
632a1ba9ba4Schristos {
633a1ba9ba4Schristos phys_addr = DMAP2_OFFSET;
634a1ba9ba4Schristos last_segname = "dmap";
635a1ba9ba4Schristos }
636a1ba9ba4Schristos else
637a1ba9ba4Schristos last_segname = "reg";
638a1ba9ba4Schristos }
639a1ba9ba4Schristos else
640a1ba9ba4Schristos last_segname = "dmem";
641a1ba9ba4Schristos memory = &State.mem.data[(phys_addr / SEGMENT_SIZE) % DMEM_SEGMENTS];
642a1ba9ba4Schristos break;
643a1ba9ba4Schristos }
644a1ba9ba4Schristos
645a1ba9ba4Schristos default:
646a1ba9ba4Schristos /* OOPS! */
647a1ba9ba4Schristos last_segname = "scrap";
648*b2396a7bSchristos sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
649a1ba9ba4Schristos }
650a1ba9ba4Schristos
651a1ba9ba4Schristos if (*memory == NULL)
652*b2396a7bSchristos *memory = xcalloc (1, SEGMENT_SIZE);
653a1ba9ba4Schristos
654a1ba9ba4Schristos offset = (phys_addr % SEGMENT_SIZE);
655a1ba9ba4Schristos raw = *memory + offset;
656a1ba9ba4Schristos return raw;
657a1ba9ba4Schristos }
658a1ba9ba4Schristos
659a1ba9ba4Schristos /* Transfer data to/from simulated memory. Since a bug in either the
660a1ba9ba4Schristos simulated program or in gdb or the simulator itself may cause a
661a1ba9ba4Schristos bogus address to be passed in, we need to do some sanity checking
662a1ba9ba4Schristos on addresses to make sure they are within bounds. When an address
663a1ba9ba4Schristos fails the bounds check, treat it as a zero length read/write rather
664a1ba9ba4Schristos than aborting the entire run. */
665a1ba9ba4Schristos
666a1ba9ba4Schristos static int
xfer_mem(SIM_DESC sd,SIM_ADDR virt,unsigned char * buffer,int size,int write_p)667*b2396a7bSchristos xfer_mem (SIM_DESC sd,
668*b2396a7bSchristos SIM_ADDR virt,
669a1ba9ba4Schristos unsigned char *buffer,
670a1ba9ba4Schristos int size,
671a1ba9ba4Schristos int write_p)
672a1ba9ba4Schristos {
673a1ba9ba4Schristos uint8 *memory;
674a1ba9ba4Schristos unsigned long phys;
675a1ba9ba4Schristos int phys_size;
676*b2396a7bSchristos phys_size = sim_d10v_translate_addr (sd, NULL, virt, size, &phys, NULL,
677a1ba9ba4Schristos dmap_register, imap_register);
678a1ba9ba4Schristos if (phys_size == 0)
679a1ba9ba4Schristos return 0;
680a1ba9ba4Schristos
681*b2396a7bSchristos memory = map_memory (sd, NULL, phys);
682a1ba9ba4Schristos
683a1ba9ba4Schristos #ifdef DEBUG
684a1ba9ba4Schristos if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
685a1ba9ba4Schristos {
686*b2396a7bSchristos sim_io_printf
687*b2396a7bSchristos (sd,
688a1ba9ba4Schristos "sim_%s %d bytes: 0x%08lx (%s) -> 0x%08lx (%s) -> 0x%08lx (%s)\n",
689*b2396a7bSchristos write_p ? "write" : "read",
690a1ba9ba4Schristos phys_size, virt, last_from,
691a1ba9ba4Schristos phys, last_to,
692a1ba9ba4Schristos (long) memory, last_segname);
693a1ba9ba4Schristos }
694a1ba9ba4Schristos #endif
695a1ba9ba4Schristos
696a1ba9ba4Schristos if (write_p)
697a1ba9ba4Schristos {
698a1ba9ba4Schristos memcpy (memory, buffer, phys_size);
699a1ba9ba4Schristos }
700a1ba9ba4Schristos else
701a1ba9ba4Schristos {
702a1ba9ba4Schristos memcpy (buffer, memory, phys_size);
703a1ba9ba4Schristos }
704a1ba9ba4Schristos
705a1ba9ba4Schristos return phys_size;
706a1ba9ba4Schristos }
707a1ba9ba4Schristos
708a1ba9ba4Schristos
709a1ba9ba4Schristos int
sim_write(SIM_DESC sd,SIM_ADDR addr,const unsigned char * buffer,int size)710a1ba9ba4Schristos sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
711a1ba9ba4Schristos {
712a1ba9ba4Schristos /* FIXME: this should be performing a virtual transfer */
713*b2396a7bSchristos return xfer_mem (sd, addr, buffer, size, 1);
714a1ba9ba4Schristos }
715a1ba9ba4Schristos
716a1ba9ba4Schristos int
sim_read(SIM_DESC sd,SIM_ADDR addr,unsigned char * buffer,int size)717a1ba9ba4Schristos sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
718a1ba9ba4Schristos {
719a1ba9ba4Schristos /* FIXME: this should be performing a virtual transfer */
720*b2396a7bSchristos return xfer_mem (sd, addr, buffer, size, 0);
721a1ba9ba4Schristos }
722a1ba9ba4Schristos
723a1ba9ba4Schristos static sim_cia
d10v_pc_get(sim_cpu * cpu)724a1ba9ba4Schristos d10v_pc_get (sim_cpu *cpu)
725a1ba9ba4Schristos {
726a1ba9ba4Schristos return PC;
727a1ba9ba4Schristos }
728a1ba9ba4Schristos
729a1ba9ba4Schristos static void
d10v_pc_set(sim_cpu * cpu,sim_cia pc)730a1ba9ba4Schristos d10v_pc_set (sim_cpu *cpu, sim_cia pc)
731a1ba9ba4Schristos {
732*b2396a7bSchristos SIM_DESC sd = CPU_STATE (cpu);
733a1ba9ba4Schristos SET_PC (pc);
734a1ba9ba4Schristos }
735a1ba9ba4Schristos
736a1ba9ba4Schristos static void
free_state(SIM_DESC sd)737a1ba9ba4Schristos free_state (SIM_DESC sd)
738a1ba9ba4Schristos {
739a1ba9ba4Schristos if (STATE_MODULES (sd) != NULL)
740a1ba9ba4Schristos sim_module_uninstall (sd);
741a1ba9ba4Schristos sim_cpu_free_all (sd);
742a1ba9ba4Schristos sim_state_free (sd);
743a1ba9ba4Schristos }
744a1ba9ba4Schristos
745*b2396a7bSchristos static int d10v_reg_fetch (SIM_CPU *, int, unsigned char *, int);
746*b2396a7bSchristos static int d10v_reg_store (SIM_CPU *, int, unsigned char *, int);
747a1ba9ba4Schristos
748a1ba9ba4Schristos SIM_DESC
sim_open(SIM_OPEN_KIND kind,host_callback * cb,struct bfd * abfd,char * const * argv)749*b2396a7bSchristos sim_open (SIM_OPEN_KIND kind, host_callback *cb,
750*b2396a7bSchristos struct bfd *abfd, char * const *argv)
751a1ba9ba4Schristos {
752a1ba9ba4Schristos struct simops *s;
753a1ba9ba4Schristos struct hash_entry *h;
754a1ba9ba4Schristos static int init_p = 0;
755a1ba9ba4Schristos char **p;
756a1ba9ba4Schristos int i;
757a1ba9ba4Schristos SIM_DESC sd = sim_state_alloc (kind, cb);
758a1ba9ba4Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
759a1ba9ba4Schristos
760a1ba9ba4Schristos /* The cpu data is kept in a separately allocated chunk of memory. */
761a1ba9ba4Schristos if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
762a1ba9ba4Schristos {
763a1ba9ba4Schristos free_state (sd);
764a1ba9ba4Schristos return 0;
765a1ba9ba4Schristos }
766a1ba9ba4Schristos
767a1ba9ba4Schristos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
768a1ba9ba4Schristos {
769a1ba9ba4Schristos free_state (sd);
770a1ba9ba4Schristos return 0;
771a1ba9ba4Schristos }
772a1ba9ba4Schristos
773*b2396a7bSchristos /* The parser will print an error message for us, so we silently return. */
774a1ba9ba4Schristos if (sim_parse_args (sd, argv) != SIM_RC_OK)
775a1ba9ba4Schristos {
776a1ba9ba4Schristos free_state (sd);
777a1ba9ba4Schristos return 0;
778a1ba9ba4Schristos }
779a1ba9ba4Schristos
780a1ba9ba4Schristos /* Check for/establish the a reference program image. */
781a1ba9ba4Schristos if (sim_analyze_program (sd,
782a1ba9ba4Schristos (STATE_PROG_ARGV (sd) != NULL
783a1ba9ba4Schristos ? *STATE_PROG_ARGV (sd)
784a1ba9ba4Schristos : NULL), abfd) != SIM_RC_OK)
785a1ba9ba4Schristos {
786a1ba9ba4Schristos free_state (sd);
787a1ba9ba4Schristos return 0;
788a1ba9ba4Schristos }
789a1ba9ba4Schristos
790a1ba9ba4Schristos /* Configure/verify the target byte order and other runtime
791a1ba9ba4Schristos configuration options. */
792a1ba9ba4Schristos if (sim_config (sd) != SIM_RC_OK)
793a1ba9ba4Schristos {
794a1ba9ba4Schristos sim_module_uninstall (sd);
795a1ba9ba4Schristos return 0;
796a1ba9ba4Schristos }
797a1ba9ba4Schristos
798a1ba9ba4Schristos if (sim_post_argv_init (sd) != SIM_RC_OK)
799a1ba9ba4Schristos {
800a1ba9ba4Schristos /* Uninstall the modules to avoid memory leaks,
801a1ba9ba4Schristos file descriptor leaks, etc. */
802a1ba9ba4Schristos sim_module_uninstall (sd);
803a1ba9ba4Schristos return 0;
804a1ba9ba4Schristos }
805a1ba9ba4Schristos
806a1ba9ba4Schristos /* CPU specific initialization. */
807a1ba9ba4Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
808a1ba9ba4Schristos {
809a1ba9ba4Schristos SIM_CPU *cpu = STATE_CPU (sd, i);
810a1ba9ba4Schristos
811*b2396a7bSchristos CPU_REG_FETCH (cpu) = d10v_reg_fetch;
812*b2396a7bSchristos CPU_REG_STORE (cpu) = d10v_reg_store;
813a1ba9ba4Schristos CPU_PC_FETCH (cpu) = d10v_pc_get;
814a1ba9ba4Schristos CPU_PC_STORE (cpu) = d10v_pc_set;
815a1ba9ba4Schristos }
816a1ba9ba4Schristos
817a1ba9ba4Schristos old_segment_mapping = 0;
818a1ba9ba4Schristos
819a1ba9ba4Schristos /* NOTE: This argument parsing is only effective when this function
820a1ba9ba4Schristos is called by GDB. Standalone argument parsing is handled by
821a1ba9ba4Schristos sim/common/run.c. */
822a1ba9ba4Schristos for (p = argv + 1; *p; ++p)
823a1ba9ba4Schristos {
824a1ba9ba4Schristos if (strcmp (*p, "-oldseg") == 0)
825a1ba9ba4Schristos old_segment_mapping = 1;
826a1ba9ba4Schristos #ifdef DEBUG
827a1ba9ba4Schristos else if (strcmp (*p, "-t") == 0)
828a1ba9ba4Schristos d10v_debug = DEBUG;
829a1ba9ba4Schristos else if (strncmp (*p, "-t", 2) == 0)
830a1ba9ba4Schristos d10v_debug = atoi (*p + 2);
831a1ba9ba4Schristos #endif
832a1ba9ba4Schristos }
833a1ba9ba4Schristos
834a1ba9ba4Schristos /* put all the opcodes in the hash table */
835a1ba9ba4Schristos if (!init_p++)
836a1ba9ba4Schristos {
837a1ba9ba4Schristos for (s = Simops; s->func; s++)
838a1ba9ba4Schristos {
839a1ba9ba4Schristos h = &hash_table[hash(s->opcode,s->format)];
840a1ba9ba4Schristos
841a1ba9ba4Schristos /* go to the last entry in the chain */
842a1ba9ba4Schristos while (h->next)
843a1ba9ba4Schristos h = h->next;
844a1ba9ba4Schristos
845a1ba9ba4Schristos if (h->ops)
846a1ba9ba4Schristos {
847a1ba9ba4Schristos h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
848a1ba9ba4Schristos if (!h->next)
849a1ba9ba4Schristos perror ("malloc failure");
850a1ba9ba4Schristos
851a1ba9ba4Schristos h = h->next;
852a1ba9ba4Schristos }
853a1ba9ba4Schristos h->ops = s;
854a1ba9ba4Schristos h->mask = s->mask;
855a1ba9ba4Schristos h->opcode = s->opcode;
856a1ba9ba4Schristos h->size = s->is_long;
857a1ba9ba4Schristos }
858a1ba9ba4Schristos }
859a1ba9ba4Schristos
860a1ba9ba4Schristos /* reset the processor state */
861a1ba9ba4Schristos if (!State.mem.data[0])
862a1ba9ba4Schristos sim_size (1);
863a1ba9ba4Schristos
864a1ba9ba4Schristos return sd;
865a1ba9ba4Schristos }
866a1ba9ba4Schristos
867a1ba9ba4Schristos uint8 *
dmem_addr(SIM_DESC sd,SIM_CPU * cpu,uint16 offset)868*b2396a7bSchristos dmem_addr (SIM_DESC sd, SIM_CPU *cpu, uint16 offset)
869a1ba9ba4Schristos {
870a1ba9ba4Schristos unsigned long phys;
871a1ba9ba4Schristos uint8 *mem;
872a1ba9ba4Schristos int phys_size;
873a1ba9ba4Schristos
874a1ba9ba4Schristos /* Note: DMEM address range is 0..0x10000. Calling code can compute
875a1ba9ba4Schristos things like ``0xfffe + 0x0e60 == 0x10e5d''. Since offset's type
876a1ba9ba4Schristos is uint16 this is modulo'ed onto 0x0e5d. */
877a1ba9ba4Schristos
878*b2396a7bSchristos phys_size = sim_d10v_translate_dmap_addr (sd, cpu, offset, 1, &phys, NULL,
879a1ba9ba4Schristos dmap_register);
880a1ba9ba4Schristos if (phys_size == 0)
881*b2396a7bSchristos sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
882*b2396a7bSchristos mem = map_memory (sd, cpu, phys);
883a1ba9ba4Schristos #ifdef DEBUG
884a1ba9ba4Schristos if ((d10v_debug & DEBUG_MEMORY))
885a1ba9ba4Schristos {
886*b2396a7bSchristos sim_io_printf
887*b2396a7bSchristos (sd,
888a1ba9ba4Schristos "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n",
889a1ba9ba4Schristos offset, last_from,
890a1ba9ba4Schristos phys, phys_size, last_to,
891a1ba9ba4Schristos (long) mem, last_segname);
892a1ba9ba4Schristos }
893a1ba9ba4Schristos #endif
894a1ba9ba4Schristos return mem;
895a1ba9ba4Schristos }
896a1ba9ba4Schristos
897a1ba9ba4Schristos uint8 *
imem_addr(SIM_DESC sd,SIM_CPU * cpu,uint32 offset)898*b2396a7bSchristos imem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset)
899a1ba9ba4Schristos {
900a1ba9ba4Schristos unsigned long phys;
901a1ba9ba4Schristos uint8 *mem;
902*b2396a7bSchristos int phys_size = sim_d10v_translate_imap_addr (sd, cpu, offset, 1, &phys, NULL,
903a1ba9ba4Schristos imap_register);
904a1ba9ba4Schristos if (phys_size == 0)
905*b2396a7bSchristos sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
906*b2396a7bSchristos mem = map_memory (sd, cpu, phys);
907a1ba9ba4Schristos #ifdef DEBUG
908a1ba9ba4Schristos if ((d10v_debug & DEBUG_MEMORY))
909a1ba9ba4Schristos {
910*b2396a7bSchristos sim_io_printf
911*b2396a7bSchristos (sd,
912a1ba9ba4Schristos "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n",
913a1ba9ba4Schristos offset, last_from,
914a1ba9ba4Schristos phys, phys_size, last_to,
915a1ba9ba4Schristos (long) mem, last_segname);
916a1ba9ba4Schristos }
917a1ba9ba4Schristos #endif
918a1ba9ba4Schristos return mem;
919a1ba9ba4Schristos }
920a1ba9ba4Schristos
921*b2396a7bSchristos static void
step_once(SIM_DESC sd,SIM_CPU * cpu)922*b2396a7bSchristos step_once (SIM_DESC sd, SIM_CPU *cpu)
923a1ba9ba4Schristos {
924a1ba9ba4Schristos uint32 inst;
925a1ba9ba4Schristos uint8 *iaddr;
926a1ba9ba4Schristos
927*b2396a7bSchristos /* TODO: Unindent this block. */
928a1ba9ba4Schristos {
929*b2396a7bSchristos iaddr = imem_addr (sd, cpu, (uint32)PC << 2);
930a1ba9ba4Schristos
931a1ba9ba4Schristos inst = get_longword( iaddr );
932a1ba9ba4Schristos
933a1ba9ba4Schristos State.pc_changed = 0;
934a1ba9ba4Schristos ins_type_counters[ (int)INS_CYCLES ]++;
935a1ba9ba4Schristos
936a1ba9ba4Schristos switch (inst & 0xC0000000)
937a1ba9ba4Schristos {
938a1ba9ba4Schristos case 0xC0000000:
939a1ba9ba4Schristos /* long instruction */
940*b2396a7bSchristos do_long (sd, cpu, inst & 0x3FFFFFFF);
941a1ba9ba4Schristos break;
942a1ba9ba4Schristos case 0x80000000:
943a1ba9ba4Schristos /* R -> L */
944*b2396a7bSchristos do_2_short (sd, cpu, inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST);
945a1ba9ba4Schristos break;
946a1ba9ba4Schristos case 0x40000000:
947a1ba9ba4Schristos /* L -> R */
948*b2396a7bSchristos do_2_short (sd, cpu, (inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST);
949a1ba9ba4Schristos break;
950a1ba9ba4Schristos case 0:
951*b2396a7bSchristos do_parallel (sd, cpu, (inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
952a1ba9ba4Schristos break;
953a1ba9ba4Schristos }
954a1ba9ba4Schristos
955a1ba9ba4Schristos /* If the PC of the current instruction matches RPT_E then
956a1ba9ba4Schristos schedule a branch to the loop start. If one of those
957a1ba9ba4Schristos instructions happens to be a branch, than that instruction
958a1ba9ba4Schristos will be ignored */
959a1ba9ba4Schristos if (!State.pc_changed)
960a1ba9ba4Schristos {
961a1ba9ba4Schristos if (PSW_RP && PC == RPT_E)
962a1ba9ba4Schristos {
963a1ba9ba4Schristos /* Note: The behavour of a branch instruction at RPT_E
964a1ba9ba4Schristos is implementation dependant, this simulator takes the
965a1ba9ba4Schristos branch. Branching to RPT_E is valid, the instruction
966a1ba9ba4Schristos must be executed before the loop is taken. */
967a1ba9ba4Schristos if (RPT_C == 1)
968a1ba9ba4Schristos {
969a1ba9ba4Schristos SET_PSW_RP (0);
970a1ba9ba4Schristos SET_RPT_C (0);
971a1ba9ba4Schristos SET_PC (PC + 1);
972a1ba9ba4Schristos }
973a1ba9ba4Schristos else
974a1ba9ba4Schristos {
975a1ba9ba4Schristos SET_RPT_C (RPT_C - 1);
976a1ba9ba4Schristos SET_PC (RPT_S);
977a1ba9ba4Schristos }
978a1ba9ba4Schristos }
979a1ba9ba4Schristos else
980a1ba9ba4Schristos SET_PC (PC + 1);
981a1ba9ba4Schristos }
982a1ba9ba4Schristos
983a1ba9ba4Schristos /* Check for a breakpoint trap on this instruction. This
984a1ba9ba4Schristos overrides any pending branches or loops */
985a1ba9ba4Schristos if (PSW_DB && PC == IBA)
986a1ba9ba4Schristos {
987a1ba9ba4Schristos SET_BPC (PC);
988a1ba9ba4Schristos SET_BPSW (PSW);
989a1ba9ba4Schristos SET_PSW (PSW & PSW_SM_BIT);
990a1ba9ba4Schristos SET_PC (SDBT_VECTOR_START);
991a1ba9ba4Schristos }
992a1ba9ba4Schristos
993a1ba9ba4Schristos /* Writeback all the DATA / PC changes */
994a1ba9ba4Schristos SLOT_FLUSH ();
995a1ba9ba4Schristos }
996*b2396a7bSchristos }
997a1ba9ba4Schristos
998*b2396a7bSchristos void
sim_engine_run(SIM_DESC sd,int next_cpu_nr,int nr_cpus,int siggnal)999*b2396a7bSchristos sim_engine_run (SIM_DESC sd,
1000*b2396a7bSchristos int next_cpu_nr, /* ignore */
1001*b2396a7bSchristos int nr_cpus, /* ignore */
1002*b2396a7bSchristos int siggnal)
1003*b2396a7bSchristos {
1004*b2396a7bSchristos sim_cpu *cpu;
1005*b2396a7bSchristos
1006*b2396a7bSchristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1007*b2396a7bSchristos
1008*b2396a7bSchristos cpu = STATE_CPU (sd, 0);
1009*b2396a7bSchristos
1010*b2396a7bSchristos switch (siggnal)
1011*b2396a7bSchristos {
1012*b2396a7bSchristos case 0:
1013*b2396a7bSchristos break;
1014*b2396a7bSchristos case GDB_SIGNAL_BUS:
1015*b2396a7bSchristos SET_BPC (PC);
1016*b2396a7bSchristos SET_BPSW (PSW);
1017*b2396a7bSchristos SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
1018*b2396a7bSchristos JMP (AE_VECTOR_START);
1019*b2396a7bSchristos SLOT_FLUSH ();
1020*b2396a7bSchristos break;
1021*b2396a7bSchristos case GDB_SIGNAL_ILL:
1022*b2396a7bSchristos SET_BPC (PC);
1023*b2396a7bSchristos SET_BPSW (PSW);
1024*b2396a7bSchristos SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
1025*b2396a7bSchristos JMP (RIE_VECTOR_START);
1026*b2396a7bSchristos SLOT_FLUSH ();
1027*b2396a7bSchristos break;
1028*b2396a7bSchristos default:
1029*b2396a7bSchristos /* just ignore it */
1030*b2396a7bSchristos break;
1031*b2396a7bSchristos }
1032*b2396a7bSchristos
1033*b2396a7bSchristos while (1)
1034*b2396a7bSchristos {
1035*b2396a7bSchristos step_once (sd, cpu);
1036*b2396a7bSchristos if (sim_events_tick (sd))
1037*b2396a7bSchristos sim_events_process (sd);
1038*b2396a7bSchristos }
1039a1ba9ba4Schristos }
1040a1ba9ba4Schristos
1041a1ba9ba4Schristos void
sim_info(SIM_DESC sd,int verbose)1042a1ba9ba4Schristos sim_info (SIM_DESC sd, int verbose)
1043a1ba9ba4Schristos {
1044a1ba9ba4Schristos char buf1[40];
1045a1ba9ba4Schristos char buf2[40];
1046a1ba9ba4Schristos char buf3[40];
1047a1ba9ba4Schristos char buf4[40];
1048a1ba9ba4Schristos char buf5[40];
1049a1ba9ba4Schristos unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ];
1050a1ba9ba4Schristos unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ];
1051a1ba9ba4Schristos unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ];
1052a1ba9ba4Schristos unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ];
1053a1ba9ba4Schristos unsigned long left_total = left + left_parallel + left_cond + left_nops;
1054a1ba9ba4Schristos
1055a1ba9ba4Schristos unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ];
1056a1ba9ba4Schristos unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ];
1057a1ba9ba4Schristos unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ];
1058a1ba9ba4Schristos unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ];
1059a1ba9ba4Schristos unsigned long right_total = right + right_parallel + right_cond + right_nops;
1060a1ba9ba4Schristos
1061a1ba9ba4Schristos unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ];
1062a1ba9ba4Schristos unsigned long ins_long = ins_type_counters[ (int)INS_LONG ];
1063a1ba9ba4Schristos unsigned long parallel = ins_type_counters[ (int)INS_PARALLEL ];
1064a1ba9ba4Schristos unsigned long leftright = ins_type_counters[ (int)INS_LEFTRIGHT ];
1065a1ba9ba4Schristos unsigned long rightleft = ins_type_counters[ (int)INS_RIGHTLEFT ];
1066a1ba9ba4Schristos unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ];
1067a1ba9ba4Schristos unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ];
1068a1ba9ba4Schristos unsigned long cond_jump = ins_type_counters[ (int)INS_COND_JUMP ];
1069a1ba9ba4Schristos unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ];
1070a1ba9ba4Schristos unsigned long total = (unknown + left_total + right_total + ins_long);
1071a1ba9ba4Schristos
1072a1ba9ba4Schristos int size = strlen (add_commas (buf1, sizeof (buf1), total));
1073a1ba9ba4Schristos int parallel_size = strlen (add_commas (buf1, sizeof (buf1),
1074a1ba9ba4Schristos (left_parallel > right_parallel) ? left_parallel : right_parallel));
1075a1ba9ba4Schristos int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond));
1076a1ba9ba4Schristos int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops));
1077a1ba9ba4Schristos int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right));
1078a1ba9ba4Schristos
1079*b2396a7bSchristos sim_io_printf (sd,
1080a1ba9ba4Schristos "executed %*s left instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
1081a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), left_total),
1082a1ba9ba4Schristos normal_size, add_commas (buf2, sizeof (buf2), left),
1083a1ba9ba4Schristos parallel_size, add_commas (buf3, sizeof (buf3), left_parallel),
1084a1ba9ba4Schristos cond_size, add_commas (buf4, sizeof (buf4), left_cond),
1085a1ba9ba4Schristos nop_size, add_commas (buf5, sizeof (buf5), left_nops));
1086a1ba9ba4Schristos
1087*b2396a7bSchristos sim_io_printf (sd,
1088a1ba9ba4Schristos "executed %*s right instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
1089a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), right_total),
1090a1ba9ba4Schristos normal_size, add_commas (buf2, sizeof (buf2), right),
1091a1ba9ba4Schristos parallel_size, add_commas (buf3, sizeof (buf3), right_parallel),
1092a1ba9ba4Schristos cond_size, add_commas (buf4, sizeof (buf4), right_cond),
1093a1ba9ba4Schristos nop_size, add_commas (buf5, sizeof (buf5), right_nops));
1094a1ba9ba4Schristos
1095a1ba9ba4Schristos if (ins_long)
1096*b2396a7bSchristos sim_io_printf (sd,
1097a1ba9ba4Schristos "executed %*s long instruction(s)\n",
1098a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), ins_long));
1099a1ba9ba4Schristos
1100a1ba9ba4Schristos if (parallel)
1101*b2396a7bSchristos sim_io_printf (sd,
1102a1ba9ba4Schristos "executed %*s parallel instruction(s)\n",
1103a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), parallel));
1104a1ba9ba4Schristos
1105a1ba9ba4Schristos if (leftright)
1106*b2396a7bSchristos sim_io_printf (sd,
1107a1ba9ba4Schristos "executed %*s instruction(s) encoded L->R\n",
1108a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), leftright));
1109a1ba9ba4Schristos
1110a1ba9ba4Schristos if (rightleft)
1111*b2396a7bSchristos sim_io_printf (sd,
1112a1ba9ba4Schristos "executed %*s instruction(s) encoded R->L\n",
1113a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), rightleft));
1114a1ba9ba4Schristos
1115a1ba9ba4Schristos if (unknown)
1116*b2396a7bSchristos sim_io_printf (sd,
1117a1ba9ba4Schristos "executed %*s unknown instruction(s)\n",
1118a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), unknown));
1119a1ba9ba4Schristos
1120a1ba9ba4Schristos if (cond_true)
1121*b2396a7bSchristos sim_io_printf (sd,
1122a1ba9ba4Schristos "executed %*s instruction(s) due to EXExxx condition being true\n",
1123a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), cond_true));
1124a1ba9ba4Schristos
1125a1ba9ba4Schristos if (cond_false)
1126*b2396a7bSchristos sim_io_printf (sd,
1127a1ba9ba4Schristos "skipped %*s instruction(s) due to EXExxx condition being false\n",
1128a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), cond_false));
1129a1ba9ba4Schristos
1130a1ba9ba4Schristos if (cond_jump)
1131*b2396a7bSchristos sim_io_printf (sd,
1132a1ba9ba4Schristos "skipped %*s instruction(s) due to conditional branch succeeding\n",
1133a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), cond_jump));
1134a1ba9ba4Schristos
1135*b2396a7bSchristos sim_io_printf (sd,
1136a1ba9ba4Schristos "executed %*s cycle(s)\n",
1137a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), cycles));
1138a1ba9ba4Schristos
1139*b2396a7bSchristos sim_io_printf (sd,
1140a1ba9ba4Schristos "executed %*s total instructions\n",
1141a1ba9ba4Schristos size, add_commas (buf1, sizeof (buf1), total));
1142a1ba9ba4Schristos }
1143a1ba9ba4Schristos
1144a1ba9ba4Schristos SIM_RC
sim_create_inferior(SIM_DESC sd,struct bfd * abfd,char * const * argv,char * const * env)1145*b2396a7bSchristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1146*b2396a7bSchristos char * const *argv, char * const *env)
1147a1ba9ba4Schristos {
1148a1ba9ba4Schristos bfd_vma start_address;
1149a1ba9ba4Schristos
1150a1ba9ba4Schristos /* reset all state information */
1151a1ba9ba4Schristos memset (&State.regs, 0, (uintptr_t)&State.mem - (uintptr_t)&State.regs);
1152a1ba9ba4Schristos
1153a1ba9ba4Schristos /* There was a hack here to copy the values of argc and argv into r0
1154a1ba9ba4Schristos and r1. The values were also saved into some high memory that
1155a1ba9ba4Schristos won't be overwritten by the stack (0x7C00). The reason for doing
1156a1ba9ba4Schristos this was to allow the 'run' program to accept arguments. Without
1157a1ba9ba4Schristos the hack, this is not possible anymore. If the simulator is run
1158a1ba9ba4Schristos from the debugger, arguments cannot be passed in, so this makes
1159a1ba9ba4Schristos no difference. */
1160a1ba9ba4Schristos
1161a1ba9ba4Schristos /* set PC */
1162a1ba9ba4Schristos if (abfd != NULL)
1163a1ba9ba4Schristos start_address = bfd_get_start_address (abfd);
1164a1ba9ba4Schristos else
1165a1ba9ba4Schristos start_address = 0xffc0 << 2;
1166a1ba9ba4Schristos #ifdef DEBUG
1167a1ba9ba4Schristos if (d10v_debug)
1168*b2396a7bSchristos sim_io_printf (sd, "sim_create_inferior: PC=0x%lx\n", (long) start_address);
1169a1ba9ba4Schristos #endif
1170*b2396a7bSchristos {
1171*b2396a7bSchristos SIM_CPU *cpu = STATE_CPU (sd, 0);
1172a1ba9ba4Schristos SET_CREG (PC_CR, start_address >> 2);
1173*b2396a7bSchristos }
1174a1ba9ba4Schristos
1175a1ba9ba4Schristos /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board
1176a1ba9ba4Schristos initializes imap0 and imap1 to 0x1000 as part of its ROM
1177a1ba9ba4Schristos initialization. */
1178a1ba9ba4Schristos if (old_segment_mapping)
1179a1ba9ba4Schristos {
1180a1ba9ba4Schristos /* External memory startup. This is the HARD reset state. */
1181*b2396a7bSchristos set_imap_register (sd, 0, 0x0000);
1182*b2396a7bSchristos set_imap_register (sd, 1, 0x007f);
1183*b2396a7bSchristos set_dmap_register (sd, 0, 0x2000);
1184*b2396a7bSchristos set_dmap_register (sd, 1, 0x2000);
1185*b2396a7bSchristos set_dmap_register (sd, 2, 0x0000); /* Old DMAP */
1186*b2396a7bSchristos set_dmap_register (sd, 3, 0x0000);
1187a1ba9ba4Schristos }
1188a1ba9ba4Schristos else
1189a1ba9ba4Schristos {
1190a1ba9ba4Schristos /* Internal memory startup. This is the ROM intialized state. */
1191*b2396a7bSchristos set_imap_register (sd, 0, 0x1000);
1192*b2396a7bSchristos set_imap_register (sd, 1, 0x1000);
1193*b2396a7bSchristos set_dmap_register (sd, 0, 0x2000);
1194*b2396a7bSchristos set_dmap_register (sd, 1, 0x2000);
1195*b2396a7bSchristos set_dmap_register (sd, 2, 0x2000); /* DMAP2 initial internal value is
1196a1ba9ba4Schristos 0x2000 on the new board. */
1197*b2396a7bSchristos set_dmap_register (sd, 3, 0x0000);
1198a1ba9ba4Schristos }
1199a1ba9ba4Schristos
1200a1ba9ba4Schristos SLOT_FLUSH ();
1201a1ba9ba4Schristos return SIM_RC_OK;
1202a1ba9ba4Schristos }
1203a1ba9ba4Schristos
1204*b2396a7bSchristos static int
d10v_reg_fetch(SIM_CPU * cpu,int rn,unsigned char * memory,int length)1205*b2396a7bSchristos d10v_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
1206a1ba9ba4Schristos {
1207*b2396a7bSchristos SIM_DESC sd = CPU_STATE (cpu);
1208a1ba9ba4Schristos int size;
1209a1ba9ba4Schristos switch ((enum sim_d10v_regs) rn)
1210a1ba9ba4Schristos {
1211a1ba9ba4Schristos case SIM_D10V_R0_REGNUM:
1212a1ba9ba4Schristos case SIM_D10V_R1_REGNUM:
1213a1ba9ba4Schristos case SIM_D10V_R2_REGNUM:
1214a1ba9ba4Schristos case SIM_D10V_R3_REGNUM:
1215a1ba9ba4Schristos case SIM_D10V_R4_REGNUM:
1216a1ba9ba4Schristos case SIM_D10V_R5_REGNUM:
1217a1ba9ba4Schristos case SIM_D10V_R6_REGNUM:
1218a1ba9ba4Schristos case SIM_D10V_R7_REGNUM:
1219a1ba9ba4Schristos case SIM_D10V_R8_REGNUM:
1220a1ba9ba4Schristos case SIM_D10V_R9_REGNUM:
1221a1ba9ba4Schristos case SIM_D10V_R10_REGNUM:
1222a1ba9ba4Schristos case SIM_D10V_R11_REGNUM:
1223a1ba9ba4Schristos case SIM_D10V_R12_REGNUM:
1224a1ba9ba4Schristos case SIM_D10V_R13_REGNUM:
1225a1ba9ba4Schristos case SIM_D10V_R14_REGNUM:
1226a1ba9ba4Schristos case SIM_D10V_R15_REGNUM:
1227a1ba9ba4Schristos WRITE_16 (memory, GPR (rn - SIM_D10V_R0_REGNUM));
1228a1ba9ba4Schristos size = 2;
1229a1ba9ba4Schristos break;
1230a1ba9ba4Schristos case SIM_D10V_CR0_REGNUM:
1231a1ba9ba4Schristos case SIM_D10V_CR1_REGNUM:
1232a1ba9ba4Schristos case SIM_D10V_CR2_REGNUM:
1233a1ba9ba4Schristos case SIM_D10V_CR3_REGNUM:
1234a1ba9ba4Schristos case SIM_D10V_CR4_REGNUM:
1235a1ba9ba4Schristos case SIM_D10V_CR5_REGNUM:
1236a1ba9ba4Schristos case SIM_D10V_CR6_REGNUM:
1237a1ba9ba4Schristos case SIM_D10V_CR7_REGNUM:
1238a1ba9ba4Schristos case SIM_D10V_CR8_REGNUM:
1239a1ba9ba4Schristos case SIM_D10V_CR9_REGNUM:
1240a1ba9ba4Schristos case SIM_D10V_CR10_REGNUM:
1241a1ba9ba4Schristos case SIM_D10V_CR11_REGNUM:
1242a1ba9ba4Schristos case SIM_D10V_CR12_REGNUM:
1243a1ba9ba4Schristos case SIM_D10V_CR13_REGNUM:
1244a1ba9ba4Schristos case SIM_D10V_CR14_REGNUM:
1245a1ba9ba4Schristos case SIM_D10V_CR15_REGNUM:
1246a1ba9ba4Schristos WRITE_16 (memory, CREG (rn - SIM_D10V_CR0_REGNUM));
1247a1ba9ba4Schristos size = 2;
1248a1ba9ba4Schristos break;
1249a1ba9ba4Schristos case SIM_D10V_A0_REGNUM:
1250a1ba9ba4Schristos case SIM_D10V_A1_REGNUM:
1251a1ba9ba4Schristos WRITE_64 (memory, ACC (rn - SIM_D10V_A0_REGNUM));
1252a1ba9ba4Schristos size = 8;
1253a1ba9ba4Schristos break;
1254a1ba9ba4Schristos case SIM_D10V_SPI_REGNUM:
1255a1ba9ba4Schristos /* PSW_SM indicates that the current SP is the USER
1256a1ba9ba4Schristos stack-pointer. */
1257a1ba9ba4Schristos WRITE_16 (memory, spi_register ());
1258a1ba9ba4Schristos size = 2;
1259a1ba9ba4Schristos break;
1260a1ba9ba4Schristos case SIM_D10V_SPU_REGNUM:
1261a1ba9ba4Schristos /* PSW_SM indicates that the current SP is the USER
1262a1ba9ba4Schristos stack-pointer. */
1263a1ba9ba4Schristos WRITE_16 (memory, spu_register ());
1264a1ba9ba4Schristos size = 2;
1265a1ba9ba4Schristos break;
1266a1ba9ba4Schristos case SIM_D10V_IMAP0_REGNUM:
1267a1ba9ba4Schristos case SIM_D10V_IMAP1_REGNUM:
1268*b2396a7bSchristos WRITE_16 (memory, imap_register (sd, cpu, NULL, rn - SIM_D10V_IMAP0_REGNUM));
1269a1ba9ba4Schristos size = 2;
1270a1ba9ba4Schristos break;
1271a1ba9ba4Schristos case SIM_D10V_DMAP0_REGNUM:
1272a1ba9ba4Schristos case SIM_D10V_DMAP1_REGNUM:
1273a1ba9ba4Schristos case SIM_D10V_DMAP2_REGNUM:
1274a1ba9ba4Schristos case SIM_D10V_DMAP3_REGNUM:
1275*b2396a7bSchristos WRITE_16 (memory, dmap_register (sd, cpu, NULL, rn - SIM_D10V_DMAP0_REGNUM));
1276a1ba9ba4Schristos size = 2;
1277a1ba9ba4Schristos break;
1278a1ba9ba4Schristos case SIM_D10V_TS2_DMAP_REGNUM:
1279a1ba9ba4Schristos size = 0;
1280a1ba9ba4Schristos break;
1281a1ba9ba4Schristos default:
1282a1ba9ba4Schristos size = 0;
1283a1ba9ba4Schristos break;
1284a1ba9ba4Schristos }
1285a1ba9ba4Schristos return size;
1286a1ba9ba4Schristos }
1287a1ba9ba4Schristos
1288*b2396a7bSchristos static int
d10v_reg_store(SIM_CPU * cpu,int rn,unsigned char * memory,int length)1289*b2396a7bSchristos d10v_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
1290a1ba9ba4Schristos {
1291*b2396a7bSchristos SIM_DESC sd = CPU_STATE (cpu);
1292a1ba9ba4Schristos int size;
1293a1ba9ba4Schristos switch ((enum sim_d10v_regs) rn)
1294a1ba9ba4Schristos {
1295a1ba9ba4Schristos case SIM_D10V_R0_REGNUM:
1296a1ba9ba4Schristos case SIM_D10V_R1_REGNUM:
1297a1ba9ba4Schristos case SIM_D10V_R2_REGNUM:
1298a1ba9ba4Schristos case SIM_D10V_R3_REGNUM:
1299a1ba9ba4Schristos case SIM_D10V_R4_REGNUM:
1300a1ba9ba4Schristos case SIM_D10V_R5_REGNUM:
1301a1ba9ba4Schristos case SIM_D10V_R6_REGNUM:
1302a1ba9ba4Schristos case SIM_D10V_R7_REGNUM:
1303a1ba9ba4Schristos case SIM_D10V_R8_REGNUM:
1304a1ba9ba4Schristos case SIM_D10V_R9_REGNUM:
1305a1ba9ba4Schristos case SIM_D10V_R10_REGNUM:
1306a1ba9ba4Schristos case SIM_D10V_R11_REGNUM:
1307a1ba9ba4Schristos case SIM_D10V_R12_REGNUM:
1308a1ba9ba4Schristos case SIM_D10V_R13_REGNUM:
1309a1ba9ba4Schristos case SIM_D10V_R14_REGNUM:
1310a1ba9ba4Schristos case SIM_D10V_R15_REGNUM:
1311a1ba9ba4Schristos SET_GPR (rn - SIM_D10V_R0_REGNUM, READ_16 (memory));
1312a1ba9ba4Schristos size = 2;
1313a1ba9ba4Schristos break;
1314a1ba9ba4Schristos case SIM_D10V_CR0_REGNUM:
1315a1ba9ba4Schristos case SIM_D10V_CR1_REGNUM:
1316a1ba9ba4Schristos case SIM_D10V_CR2_REGNUM:
1317a1ba9ba4Schristos case SIM_D10V_CR3_REGNUM:
1318a1ba9ba4Schristos case SIM_D10V_CR4_REGNUM:
1319a1ba9ba4Schristos case SIM_D10V_CR5_REGNUM:
1320a1ba9ba4Schristos case SIM_D10V_CR6_REGNUM:
1321a1ba9ba4Schristos case SIM_D10V_CR7_REGNUM:
1322a1ba9ba4Schristos case SIM_D10V_CR8_REGNUM:
1323a1ba9ba4Schristos case SIM_D10V_CR9_REGNUM:
1324a1ba9ba4Schristos case SIM_D10V_CR10_REGNUM:
1325a1ba9ba4Schristos case SIM_D10V_CR11_REGNUM:
1326a1ba9ba4Schristos case SIM_D10V_CR12_REGNUM:
1327a1ba9ba4Schristos case SIM_D10V_CR13_REGNUM:
1328a1ba9ba4Schristos case SIM_D10V_CR14_REGNUM:
1329a1ba9ba4Schristos case SIM_D10V_CR15_REGNUM:
1330a1ba9ba4Schristos SET_CREG (rn - SIM_D10V_CR0_REGNUM, READ_16 (memory));
1331a1ba9ba4Schristos size = 2;
1332a1ba9ba4Schristos break;
1333a1ba9ba4Schristos case SIM_D10V_A0_REGNUM:
1334a1ba9ba4Schristos case SIM_D10V_A1_REGNUM:
1335a1ba9ba4Schristos SET_ACC (rn - SIM_D10V_A0_REGNUM, READ_64 (memory) & MASK40);
1336a1ba9ba4Schristos size = 8;
1337a1ba9ba4Schristos break;
1338a1ba9ba4Schristos case SIM_D10V_SPI_REGNUM:
1339a1ba9ba4Schristos /* PSW_SM indicates that the current SP is the USER
1340a1ba9ba4Schristos stack-pointer. */
1341a1ba9ba4Schristos set_spi_register (READ_16 (memory));
1342a1ba9ba4Schristos size = 2;
1343a1ba9ba4Schristos break;
1344a1ba9ba4Schristos case SIM_D10V_SPU_REGNUM:
1345a1ba9ba4Schristos set_spu_register (READ_16 (memory));
1346a1ba9ba4Schristos size = 2;
1347a1ba9ba4Schristos break;
1348a1ba9ba4Schristos case SIM_D10V_IMAP0_REGNUM:
1349a1ba9ba4Schristos case SIM_D10V_IMAP1_REGNUM:
1350*b2396a7bSchristos set_imap_register (sd, rn - SIM_D10V_IMAP0_REGNUM, READ_16(memory));
1351a1ba9ba4Schristos size = 2;
1352a1ba9ba4Schristos break;
1353a1ba9ba4Schristos case SIM_D10V_DMAP0_REGNUM:
1354a1ba9ba4Schristos case SIM_D10V_DMAP1_REGNUM:
1355a1ba9ba4Schristos case SIM_D10V_DMAP2_REGNUM:
1356a1ba9ba4Schristos case SIM_D10V_DMAP3_REGNUM:
1357*b2396a7bSchristos set_dmap_register (sd, rn - SIM_D10V_DMAP0_REGNUM, READ_16(memory));
1358a1ba9ba4Schristos size = 2;
1359a1ba9ba4Schristos break;
1360a1ba9ba4Schristos case SIM_D10V_TS2_DMAP_REGNUM:
1361a1ba9ba4Schristos size = 0;
1362a1ba9ba4Schristos break;
1363a1ba9ba4Schristos default:
1364a1ba9ba4Schristos size = 0;
1365a1ba9ba4Schristos break;
1366a1ba9ba4Schristos }
1367a1ba9ba4Schristos SLOT_FLUSH ();
1368a1ba9ba4Schristos return size;
1369a1ba9ba4Schristos }
1370