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