Commit | Line | Data |
---|---|---|
d70b4d42 | 1 | #include <signal.h> |
2934d1c9 MH |
2 | #include "sysdep.h" |
3 | #include "bfd.h" | |
4 | #include "remote-sim.h" | |
2934d1c9 MH |
5 | |
6 | #include "d10v_sim.h" | |
7 | ||
8 | #define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */ | |
9 | #define DMEM_SIZE 16 /* Data memory */ | |
10 | ||
87178dbd MM |
11 | enum _leftright { LEFT_FIRST, RIGHT_FIRST }; |
12 | ||
13 | host_callback *d10v_callback; | |
14 | ||
2934d1c9 MH |
15 | uint16 OP[4]; |
16 | ||
17 | static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); | |
18 | ||
19 | #define MAX_HASH 63 | |
20 | struct hash_entry | |
21 | { | |
22 | struct hash_entry *next; | |
23 | long opcode; | |
24 | long mask; | |
25 | struct simops *ops; | |
26 | }; | |
27 | ||
28 | struct hash_entry hash_table[MAX_HASH+1]; | |
29 | ||
30 | static long | |
31 | hash(insn, format) | |
32 | long insn; | |
33 | int format; | |
34 | { | |
35 | if (format & LONG_OPCODE) | |
36 | return ((insn & 0x3F000000) >> 24); | |
37 | else | |
38 | return((insn & 0x7E00) >> 9); | |
39 | } | |
40 | ||
41 | static struct hash_entry * | |
42 | lookup_hash (ins, size) | |
43 | uint32 ins; | |
44 | int size; | |
45 | { | |
46 | struct hash_entry *h; | |
47 | ||
48 | if (size) | |
49 | h = &hash_table[(ins & 0x3F000000) >> 24]; | |
50 | else | |
51 | h = &hash_table[(ins & 0x7E00) >> 9]; | |
52 | ||
53 | while ( (ins & h->mask) != h->opcode) | |
54 | { | |
55 | if (h->next == NULL) | |
56 | { | |
87178dbd | 57 | printf ("ERROR looking up hash for %x at PC %x\n",ins, PC); |
2934d1c9 MH |
58 | exit(1); |
59 | } | |
60 | h = h->next; | |
61 | } | |
62 | return (h); | |
63 | } | |
64 | ||
65 | uint32 | |
d70b4d42 MH |
66 | get_longword (x) |
67 | uint8 *x; | |
2934d1c9 | 68 | { |
d70b4d42 | 69 | uint8 *a = x; |
2934d1c9 MH |
70 | return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + (a[3]); |
71 | } | |
72 | ||
d70b4d42 MH |
73 | int64 |
74 | get_longlong (x) | |
75 | uint8 *x; | |
76 | { | |
77 | uint8 *a = x; | |
78 | return ((int64)a[0]<<56) + ((int64)a[1]<<48) + ((int64)a[2]<<40) + ((int64)a[3]<<32) + | |
79 | ((int64)a[4]<< 24) + ((int64)a[5]<<16) + ((int64)a[6]<<8) + (int64)a[7]; | |
80 | } | |
81 | ||
2934d1c9 | 82 | uint16 |
d70b4d42 MH |
83 | get_word (x) |
84 | uint8 *x; | |
2934d1c9 | 85 | { |
d70b4d42 MH |
86 | uint8 *a = x; |
87 | return ((uint16)a[0]<<8) + a[1]; | |
2934d1c9 MH |
88 | } |
89 | ||
87178dbd | 90 | |
2934d1c9 | 91 | void |
d70b4d42 MH |
92 | write_word (addr, data) |
93 | uint8 *addr; | |
94 | uint16 data; | |
2934d1c9 | 95 | { |
d70b4d42 | 96 | uint8 *a = addr; |
2934d1c9 MH |
97 | a[0] = data >> 8; |
98 | a[1] = data & 0xff; | |
99 | } | |
100 | ||
87178dbd MM |
101 | void |
102 | write_longword (addr, data) | |
103 | uint8 *addr; | |
104 | uint32 data; | |
105 | { | |
106 | addr[0] = (data >> 24) & 0xff; | |
107 | addr[1] = (data >> 16) & 0xff; | |
108 | addr[2] = (data >> 8) & 0xff; | |
109 | addr[3] = data & 0xff; | |
110 | } | |
111 | ||
d70b4d42 MH |
112 | void |
113 | write_longlong (addr, data) | |
114 | uint8 *addr; | |
115 | int64 data; | |
116 | { | |
117 | uint8 *a = addr; | |
118 | a[0] = data >> 56; | |
119 | a[1] = (data >> 48) & 0xff; | |
120 | a[2] = (data >> 40) & 0xff; | |
121 | a[3] = (data >> 32) & 0xff; | |
122 | a[4] = (data >> 24) & 0xff; | |
123 | a[5] = (data >> 16) & 0xff; | |
124 | a[6] = (data >> 8) & 0xff; | |
125 | a[7] = data & 0xff; | |
126 | } | |
127 | ||
2934d1c9 MH |
128 | static void |
129 | get_operands (struct simops *s, uint32 ins) | |
130 | { | |
131 | int i, shift, bits, flags; | |
132 | uint32 mask; | |
133 | for (i=0; i < s->numops; i++) | |
134 | { | |
135 | shift = s->operands[3*i]; | |
136 | bits = s->operands[3*i+1]; | |
137 | flags = s->operands[3*i+2]; | |
138 | mask = 0x7FFFFFFF >> (31 - bits); | |
139 | OP[i] = (ins >> shift) & mask; | |
140 | } | |
141 | } | |
142 | ||
143 | static void | |
144 | do_long (ins) | |
145 | uint32 ins; | |
146 | { | |
147 | struct hash_entry *h; | |
148 | /* printf ("do_long %x\n",ins); */ | |
149 | h = lookup_hash (ins, 1); | |
150 | get_operands (h->ops, ins); | |
87178dbd | 151 | State.ins_type = INS_LONG; |
2934d1c9 MH |
152 | (h->ops->func)(); |
153 | } | |
154 | static void | |
87178dbd | 155 | do_2_short (ins1, ins2, leftright) |
2934d1c9 | 156 | uint16 ins1, ins2; |
87178dbd | 157 | enum _leftright leftright; |
2934d1c9 MH |
158 | { |
159 | struct hash_entry *h; | |
160 | /* printf ("do_2_short %x -> %x\n",ins1,ins2); */ | |
161 | h = lookup_hash (ins1, 0); | |
162 | get_operands (h->ops, ins1); | |
87178dbd | 163 | State.ins_type = (leftright == LEFT_FIRST) ? INS_LEFT : INS_RIGHT; |
2934d1c9 MH |
164 | (h->ops->func)(); |
165 | h = lookup_hash (ins2, 0); | |
166 | get_operands (h->ops, ins2); | |
87178dbd | 167 | State.ins_type = (leftright == LEFT_FIRST) ? INS_RIGHT : INS_LEFT; |
2934d1c9 MH |
168 | (h->ops->func)(); |
169 | } | |
170 | static void | |
171 | do_parallel (ins1, ins2) | |
172 | uint16 ins1, ins2; | |
173 | { | |
174 | struct hash_entry *h1, *h2; | |
d70b4d42 | 175 | /* printf ("do_parallel %x || %x\n",ins1,ins2); */ |
2934d1c9 | 176 | h1 = lookup_hash (ins1, 0); |
2934d1c9 | 177 | h2 = lookup_hash (ins2, 0); |
d70b4d42 | 178 | |
2934d1c9 MH |
179 | if (h1->ops->exec_type == PARONLY) |
180 | { | |
d70b4d42 | 181 | get_operands (h1->ops, ins1); |
87178dbd | 182 | State.ins_type = INS_LEFT; |
2934d1c9 MH |
183 | (h1->ops->func)(); |
184 | if (State.exe) | |
d70b4d42 MH |
185 | { |
186 | get_operands (h2->ops, ins2); | |
87178dbd | 187 | State.ins_type = INS_RIGHT; |
d70b4d42 MH |
188 | (h2->ops->func)(); |
189 | } | |
2934d1c9 MH |
190 | } |
191 | else if (h2->ops->exec_type == PARONLY) | |
192 | { | |
d70b4d42 | 193 | get_operands (h2->ops, ins2); |
87178dbd | 194 | State.ins_type = INS_RIGHT; |
2934d1c9 MH |
195 | (h2->ops->func)(); |
196 | if (State.exe) | |
d70b4d42 MH |
197 | { |
198 | get_operands (h1->ops, ins1); | |
87178dbd | 199 | State.ins_type = INS_LEFT; |
d70b4d42 MH |
200 | (h1->ops->func)(); |
201 | } | |
2934d1c9 MH |
202 | } |
203 | else | |
204 | { | |
d70b4d42 | 205 | get_operands (h1->ops, ins1); |
87178dbd | 206 | State.ins_type = INS_LEFT_PARALLEL; |
2934d1c9 | 207 | (h1->ops->func)(); |
d70b4d42 | 208 | get_operands (h2->ops, ins2); |
87178dbd | 209 | State.ins_type = INS_RIGHT_PARALLEL; |
2934d1c9 MH |
210 | (h2->ops->func)(); |
211 | } | |
212 | } | |
213 | ||
214 | ||
215 | void | |
216 | sim_size (power) | |
217 | int power; | |
218 | ||
219 | { | |
220 | if (State.imem) | |
221 | { | |
222 | free (State.imem); | |
223 | free (State.dmem); | |
224 | } | |
225 | ||
226 | State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE); | |
227 | State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE); | |
228 | if (!State.imem || !State.dmem ) | |
229 | { | |
230 | fprintf (stderr,"Memory allocation failed.\n"); | |
231 | exit(1); | |
232 | } | |
87178dbd | 233 | #if (DEBUG & DEBUG_MEMSIZE) != 0 |
2934d1c9 MH |
234 | printf ("Allocated %d bytes instruction memory and\n",1<<IMEM_SIZE); |
235 | printf (" %d bytes data memory.\n",1<<DMEM_SIZE); | |
87178dbd | 236 | #endif |
2934d1c9 MH |
237 | } |
238 | ||
239 | static void | |
240 | init_system () | |
241 | { | |
242 | if (!State.imem) | |
243 | sim_size(1); | |
244 | } | |
245 | ||
246 | int | |
247 | sim_write (addr, buffer, size) | |
248 | SIM_ADDR addr; | |
249 | unsigned char *buffer; | |
250 | int size; | |
251 | { | |
252 | int i; | |
253 | init_system (); | |
254 | ||
d70b4d42 | 255 | /* printf ("sim_write %d bytes to 0x%x\n",size,addr); */ |
2934d1c9 MH |
256 | for (i = 0; i < size; i++) |
257 | { | |
258 | State.imem[i+addr] = buffer[i]; | |
259 | } | |
260 | return size; | |
261 | } | |
262 | ||
263 | void | |
264 | sim_open (args) | |
265 | char *args; | |
266 | { | |
267 | struct simops *s; | |
268 | struct hash_entry *h, *prev; | |
269 | if (args != NULL) | |
270 | printf ("sim_open %s\n",args); | |
271 | ||
272 | /* put all the opcodes in the hash table */ | |
273 | for (s = Simops; s->func; s++) | |
274 | { | |
275 | h = &hash_table[hash(s->opcode,s->format)]; | |
276 | ||
277 | /* go to the last entry in the chain */ | |
278 | while (h->next) | |
279 | h = h->next; | |
280 | ||
281 | if (h->ops) | |
282 | { | |
283 | h->next = calloc(1,sizeof(struct hash_entry)); | |
284 | h = h->next; | |
285 | } | |
286 | h->ops = s; | |
287 | h->mask = s->mask; | |
288 | h->opcode = s->opcode; | |
289 | } | |
290 | } | |
291 | ||
292 | ||
293 | void | |
294 | sim_close (quitting) | |
295 | int quitting; | |
296 | { | |
297 | /* nothing to do */ | |
298 | } | |
299 | ||
300 | void | |
301 | sim_set_profile (n) | |
302 | int n; | |
303 | { | |
304 | printf ("sim_set_profile %d\n",n); | |
305 | } | |
306 | ||
307 | void | |
308 | sim_set_profile_size (n) | |
309 | int n; | |
310 | { | |
311 | printf ("sim_set_profile_size %d\n",n); | |
312 | } | |
313 | ||
314 | void | |
315 | sim_resume (step, siggnal) | |
316 | int step, siggnal; | |
317 | { | |
318 | uint32 inst; | |
319 | int i; | |
320 | reg_t oldpc; | |
321 | ||
d70b4d42 | 322 | /* printf ("sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */ |
2934d1c9 | 323 | |
d70b4d42 MH |
324 | if (step) |
325 | State.exception = SIGTRAP; | |
326 | else | |
327 | State.exception = 0; | |
328 | ||
329 | do | |
330 | { | |
331 | inst = RLW (PC << 2); | |
332 | oldpc = PC; | |
333 | switch (inst & 0xC0000000) | |
334 | { | |
335 | case 0xC0000000: | |
336 | /* long instruction */ | |
337 | do_long (inst & 0x3FFFFFFF); | |
338 | break; | |
339 | case 0x80000000: | |
340 | /* R -> L */ | |
87178dbd | 341 | do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0); |
d70b4d42 MH |
342 | break; |
343 | case 0x40000000: | |
344 | /* L -> R */ | |
87178dbd | 345 | do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1); |
d70b4d42 MH |
346 | break; |
347 | case 0: | |
348 | do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); | |
349 | break; | |
350 | } | |
351 | ||
352 | if (State.RP && PC == RPT_E) | |
353 | { | |
354 | RPT_C -= 1; | |
355 | if (RPT_C == 0) | |
356 | State.RP = 0; | |
357 | else | |
358 | PC = RPT_S; | |
359 | } | |
360 | ||
361 | /* FIXME */ | |
362 | if (PC == oldpc) | |
363 | PC++; | |
364 | } | |
365 | while (!State.exception); | |
2934d1c9 MH |
366 | } |
367 | ||
368 | int | |
369 | sim_trace () | |
370 | { | |
371 | printf ("sim_trace\n"); | |
372 | return 0; | |
373 | } | |
374 | ||
375 | void | |
376 | sim_info (verbose) | |
377 | int verbose; | |
378 | { | |
d70b4d42 | 379 | printf ("sim_info\n"); |
2934d1c9 MH |
380 | } |
381 | ||
382 | void | |
383 | sim_create_inferior (start_address, argv, env) | |
384 | SIM_ADDR start_address; | |
385 | char **argv; | |
386 | char **env; | |
387 | { | |
388 | printf ("sim_create_inferior: PC=0x%x\n",start_address); | |
389 | PC = start_address >> 2; | |
390 | } | |
391 | ||
392 | ||
393 | void | |
394 | sim_kill () | |
395 | { | |
396 | /* nothing to do */ | |
397 | } | |
398 | ||
399 | void | |
400 | sim_set_callbacks(p) | |
401 | host_callback *p; | |
402 | { | |
87178dbd MM |
403 | /* printf ("sim_set_callbacks\n"); */ |
404 | d10v_callback = p; | |
2934d1c9 MH |
405 | } |
406 | ||
407 | void | |
408 | sim_stop_reason (reason, sigrc) | |
409 | enum sim_stop *reason; | |
410 | int *sigrc; | |
411 | { | |
d70b4d42 MH |
412 | /* printf ("sim_stop_reason: PC=0x%x\n",PC<<2); */ |
413 | ||
414 | if (State.exception == SIGQUIT) | |
415 | { | |
416 | *reason = sim_exited; | |
417 | *sigrc = State.exception; | |
418 | } | |
419 | else | |
420 | { | |
421 | *reason = sim_stopped; | |
422 | *sigrc = State.exception; | |
423 | } | |
424 | } | |
425 | ||
426 | void | |
427 | sim_fetch_register (rn, memory) | |
428 | int rn; | |
429 | unsigned char *memory; | |
430 | { | |
431 | if (rn > 31) | |
432 | { | |
433 | WRITE_64 (memory, State.a[rn-32]); | |
434 | /* printf ("sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */ | |
435 | } | |
436 | else | |
437 | { | |
438 | WRITE_16 (memory, State.regs[rn]); | |
439 | /* printf ("sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */ | |
440 | } | |
441 | } | |
442 | ||
443 | void | |
444 | sim_store_register (rn, memory) | |
445 | int rn; | |
446 | unsigned char *memory; | |
447 | { | |
448 | if (rn > 31) | |
449 | { | |
450 | State.a[rn-32] = READ_64 (memory) & MASK40; | |
451 | /* printf ("store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */ | |
452 | } | |
453 | else | |
454 | { | |
455 | State.regs[rn]= READ_16 (memory); | |
456 | /* printf ("store: r%d=0x%x\n",rn,State.regs[rn]); */ | |
457 | } | |
2934d1c9 | 458 | } |
d70b4d42 MH |
459 | |
460 | sim_read (addr, buffer, size) | |
461 | SIM_ADDR addr; | |
462 | unsigned char *buffer; | |
463 | int size; | |
464 | { | |
465 | int i; | |
466 | for (i = 0; i < size; i++) | |
467 | { | |
468 | buffer[i] = State.imem[addr + i]; | |
469 | } | |
470 | return size; | |
471 | } | |
472 | ||
473 | void | |
474 | sim_do_command (cmd) | |
475 | char *cmd; | |
476 | { | |
477 | printf("sim_do_command: %s\n",cmd); | |
478 | } | |
479 | ||
480 | int | |
481 | sim_load (prog, from_tty) | |
482 | char *prog; | |
483 | int from_tty; | |
484 | { | |
485 | /* Return nonzero so GDB will handle it. */ | |
486 | return 1; | |
487 | } |