xref: /netbsd/external/gpl3/gdb.old/dist/sim/d10v/interp.c (revision b2396a7b)
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