Increase simulated memory size. Support new system call ABI. Support exception...
[deliverable/binutils-gdb.git] / sim / moxie / interp.c
CommitLineData
fdd6fa61
AG
1/* Simulator for the moxie processor
2 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
3 Contributed by Anthony Green
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include <signal.h>
21#include <stdlib.h>
22#include "sysdep.h"
23#include <sys/times.h>
24#include <sys/param.h>
25#include <netinet/in.h> /* for byte ordering macros */
26#include "bfd.h"
27#include "gdb/callback.h"
28#include "libiberty.h"
29#include "gdb/remote-sim.h"
30
31typedef int word;
32typedef unsigned int uword;
33
34host_callback * callback;
35
36FILE *tracefile;
37
86566200
AG
38/* Extract the signed 10-bit offset from a 16-bit branch
39 instruction. */
40#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
41
fdd6fa61
AG
42#define EXTRACT_WORD(addr) (((addr)[0] << 24) \
43 + ((addr)[1] << 16) \
44 + ((addr)[2] << 8) \
45 + ((addr)[3]))
46
47unsigned long
48moxie_extract_unsigned_integer (addr, len)
49 unsigned char * addr;
50 int len;
51{
52 unsigned long retval;
53 unsigned char * p;
54 unsigned char * startaddr = (unsigned char *)addr;
55 unsigned char * endaddr = startaddr + len;
56
57 if (len > (int) sizeof (unsigned long))
58 printf ("That operation is not available on integers of more than %d bytes.",
59 sizeof (unsigned long));
60
61 /* Start at the most significant end of the integer, and work towards
62 the least significant. */
63 retval = 0;
64
65 for (p = endaddr; p > startaddr;)
66 retval = (retval << 8) | * -- p;
67
68 return retval;
69}
70
71void
72moxie_store_unsigned_integer (addr, len, val)
73 unsigned char * addr;
74 int len;
75 unsigned long val;
76{
77 unsigned char * p;
78 unsigned char * startaddr = (unsigned char *)addr;
79 unsigned char * endaddr = startaddr + len;
80
81 for (p = endaddr; p > startaddr;)
82 {
83 * -- p = val & 0xff;
84 val >>= 8;
85 }
86}
87
88/* moxie register names. */
89static const char *reg_names[16] =
90 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
91 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
92
93/* The machine state.
94
95 This state is maintained in host byte order. The fetch/store
96 register functions must translate between host byte order and the
97 target processor byte order. Keeping this data in target byte
98 order simplifies the register read/write functions. Keeping this
99 data in native order improves the performance of the simulator.
100 Simulation speed is deemed more important. */
101
102#define NUM_MOXIE_REGS 17 /* Including PC */
103#define NUM_MOXIE_SREGS 256 /* The special registers */
104#define PC_REGNO 16
105
106/* The ordering of the moxie_regset structure is matched in the
107 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
108struct moxie_regset
109{
110 word regs[NUM_MOXIE_REGS + 1]; /* primary registers */
111 word sregs[256]; /* special registers */
112 word cc; /* the condition code reg */
113 int exception;
114 unsigned long msize;
115 unsigned char * memory;
116 unsigned long long insts; /* instruction counter */
117};
118
119#define CC_GT 1<<0
120#define CC_LT 1<<1
121#define CC_EQ 1<<2
122#define CC_GTU 1<<3
123#define CC_LTU 1<<4
124
125union
126{
127 struct moxie_regset asregs;
128 word asints [1]; /* but accessed larger... */
129} cpu;
130
131static char *myname;
132static SIM_OPEN_KIND sim_kind;
133static int issue_messages = 0;
134
7a321525
AG
135/* Default to a 16 Mbyte (== 2^23) memory space. */
136static int sim_memory_size = 24;
fdd6fa61
AG
137
138#define MEM_SIZE_FLOOR 64
139void
140sim_size (power)
141 int power;
142{
143 sim_memory_size = power;
144 cpu.asregs.msize = 1 << sim_memory_size;
145
146 if (cpu.asregs.memory)
147 free (cpu.asregs.memory);
148
149 /* Watch out for the '0 count' problem. There's probably a better
150 way.. e.g., why do we use 64 here? */
151 if (cpu.asregs.msize < 64) /* Ensure a boundary. */
152 cpu.asregs.memory = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
153 else
154 cpu.asregs.memory = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
155
156 if (!cpu.asregs.memory)
157 {
158 if (issue_messages)
159 fprintf (stderr,
160 "Not enough VM for simulation of %d bytes of RAM\n",
161 cpu.asregs.msize);
162
163 cpu.asregs.msize = 1;
164 cpu.asregs.memory = (unsigned char *) calloc (1, 1);
165 }
166}
167
168static void
169init_pointers ()
170{
171 if (cpu.asregs.msize != (1 << sim_memory_size))
172 sim_size (sim_memory_size);
173}
174
175
176static void
177set_initial_gprs ()
178{
179 int i;
180 long space;
181 unsigned long memsize;
182
183 init_pointers ();
184
185 /* Set up machine just out of reset. */
186 cpu.asregs.regs[PC_REGNO] = 0;
187
188 memsize = cpu.asregs.msize / (1024 * 1024);
189
190 if (issue_messages > 1)
191 fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
192 memsize, cpu.asregs.msize - 1);
193
194 /* Clean out the register contents. */
195 for (i = 0; i < NUM_MOXIE_REGS; i++)
196 cpu.asregs.regs[i] = 0;
197 for (i = 0; i < NUM_MOXIE_SREGS; i++)
198 cpu.asregs.sregs[i] = 0;
199}
200
201static void
202interrupt ()
203{
204 cpu.asregs.exception = SIGINT;
205}
206
207/* Write a 1 byte value to memory. */
208
209static void INLINE
210wbat (pc, x, v)
211 word pc, x, v;
212{
213 if (((uword)x) >= cpu.asregs.msize)
214 {
215 if (issue_messages)
216 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
217
218 cpu.asregs.exception = SIGSEGV;
219 }
220 else
221 {
222 {
223 unsigned char * p = cpu.asregs.memory + x;
224 *p = v;
225 }
226 }
227}
228
229/* Write a 2 byte value to memory. */
230
231static void INLINE
232wsat (pc, x, v)
233 word pc, x, v;
234{
235 if (((uword)x) >= cpu.asregs.msize)
236 {
237 if (issue_messages)
238 fprintf (stderr, "short word write to 0x%x outside memory range\n", x);
239
240 cpu.asregs.exception = SIGSEGV;
241 }
242 else
243 {
244 if ((x & 1) != 0)
245 {
246 if (issue_messages)
247 fprintf (stderr, "short word write to unaligned memory address: 0x%x\n", x);
248
249 cpu.asregs.exception = SIGBUS;
250 }
251 {
252 unsigned char * p = cpu.asregs.memory + x;
253 p[0] = v >> 8;
254 p[1] = v;
255 }
256 }
257}
258
259/* Write a 4 byte value to memory. */
260
261static void INLINE
262wlat (pc, x, v)
263 word pc, x, v;
264{
265 if (((uword)x) >= cpu.asregs.msize)
266 {
267 if (issue_messages)
268 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
269
270 cpu.asregs.exception = SIGSEGV;
271 }
272 else
273 {
274 if ((x & 1) != 0)
275 {
276 if (issue_messages)
277 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
278
279 cpu.asregs.exception = SIGBUS;
280 }
281 {
282 unsigned char * p = cpu.asregs.memory + x;
283 p[0] = v >> 24;
284 p[1] = v >> 16;
285 p[2] = v >> 8;
286 p[3] = v;
287 }
288 }
289}
290
291/* Read 2 bytes from memory. */
292
293static int INLINE
294rsat (pc, x)
295 word pc, x;
296{
297 if (((uword) x) >= cpu.asregs.msize)
298 {
299 if (issue_messages)
300 fprintf (stderr, "short word read from 0x%x outside memory range\n", x);
301
302 cpu.asregs.exception = SIGSEGV;
303 return 0;
304 }
305 else
306 {
307 if ((x & 1) != 0)
308 {
309 if (issue_messages)
310 fprintf (stderr, "short word read from unaligned address: 0x%x\n", x);
311
312 cpu.asregs.exception = SIGBUS;
313 return 0;
314 }
315 {
316 unsigned char * p = cpu.asregs.memory + x;
317 return (p[0] << 8) | p[1];
318 }
319 }
320}
321
322/* Read 1 byte from memory. */
323
324static int INLINE
325rbat (pc, x)
326 word pc, x;
327{
328 if (((uword) x) >= cpu.asregs.msize)
329 {
330 if (issue_messages)
331 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
332
333 cpu.asregs.exception = SIGSEGV;
334 return 0;
335 }
336 else
337 {
338 unsigned char * p = cpu.asregs.memory + x;
339 return *p;
340 }
341}
342
343/* Read 4 bytes from memory. */
344
345static int INLINE
346rlat (pc, x)
347 word pc, x;
348{
349 if (((uword) x) >= cpu.asregs.msize)
350 {
351 if (issue_messages)
352 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
353
354 cpu.asregs.exception = SIGSEGV;
355 return 0;
356 }
357 else
358 {
359 if ((x & 3) != 0)
360 {
361 if (issue_messages)
362 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
363
364 cpu.asregs.exception = SIGBUS;
365 return 0;
366 }
367 {
368 unsigned char * p = cpu.asregs.memory + x;
369 return (EXTRACT_WORD(p));
370 }
371 }
372}
373
374#define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
375
376unsigned int
377convert_target_flags (unsigned int tflags)
378{
379 unsigned int hflags = 0x0;
380
381 CHECK_FLAG(0x0001, O_WRONLY);
382 CHECK_FLAG(0x0002, O_RDWR);
383 CHECK_FLAG(0x0008, O_APPEND);
384 CHECK_FLAG(0x0200, O_CREAT);
385 CHECK_FLAG(0x0400, O_TRUNC);
386 CHECK_FLAG(0x0800, O_EXCL);
387 CHECK_FLAG(0x2000, O_SYNC);
388
389 if (tflags != 0x0)
390 fprintf (stderr,
391 "Simulator Error: problem converting target open flags for host. 0x%x\n",
392 tflags);
393
394 return hflags;
395}
396
397#define TRACE(str) if (tracing) fprintf(tracefile,"0x%08x, %s, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], cpu.asregs.regs[14], cpu.asregs.regs[15]);
398
399static int tracing = 0;
400
401void
402sim_resume (sd, step, siggnal)
403 SIM_DESC sd;
404 int step, siggnal;
405{
406 word pc, opc;
407 unsigned long long insts;
408 unsigned short inst;
409 void (* sigsave)();
410
411 sigsave = signal (SIGINT, interrupt);
412 cpu.asregs.exception = step ? SIGTRAP: 0;
413 pc = cpu.asregs.regs[PC_REGNO];
414 insts = cpu.asregs.insts;
415 unsigned char *memory = cpu.asregs.memory;
416
417 /* Run instructions here. */
418 do
419 {
420 opc = pc;
421
422 /* Fetch the instruction at pc. */
423 inst = (memory[pc] << 8) + memory[pc + 1];
424
425 /* Decode instruction. */
426 if (inst & (1 << 15))
427 {
428 if (inst & (1 << 14))
429 {
430 /* This is a Form 3 instruction. */
86566200
AG
431 int opcode = (inst >> 10 & 0xf);
432
433 switch (opcode)
434 {
435 case 0x00: /* beq */
436 {
437 TRACE("beq");
438 if (cpu.asregs.cc & CC_EQ)
439 pc += INST2OFFSET(inst) - 2;
440 }
441 break;
442 case 0x01: /* bne */
443 {
444 TRACE("bne");
445 if (! (cpu.asregs.cc & CC_EQ))
446 pc += INST2OFFSET(inst) - 2;
447 }
448 break;
449 case 0x02: /* blt */
450 {
451 TRACE("blt");
452 if (cpu.asregs.cc & CC_LT)
453 pc += INST2OFFSET(inst) - 2;
454 } break;
455 case 0x03: /* bgt */
456 {
457 TRACE("bgt");
458 if (cpu.asregs.cc & CC_GT)
459 pc += INST2OFFSET(inst) - 2;
460 }
461 break;
462 case 0x04: /* bltu */
463 {
464 TRACE("bltu");
465 if (cpu.asregs.cc & CC_LTU)
466 pc += INST2OFFSET(inst) - 2;
467 }
468 break;
469 case 0x05: /* bgtu */
470 {
471 TRACE("bgtu");
472 if (cpu.asregs.cc & CC_GTU)
473 pc += INST2OFFSET(inst) - 2;
474 }
475 break;
476 case 0x06: /* bge */
477 {
478 TRACE("bge");
479 if (cpu.asregs.cc & (CC_GT | CC_EQ))
480 pc += INST2OFFSET(inst) - 2;
481 }
482 break;
483 case 0x07: /* ble */
484 {
485 TRACE("ble");
486 if (cpu.asregs.cc & (CC_LT | CC_EQ))
487 pc += INST2OFFSET(inst) - 2;
488 }
489 break;
490 case 0x08: /* bgeu */
491 {
492 TRACE("bgeu");
493 if (cpu.asregs.cc & (CC_GTU | CC_EQ))
494 pc += INST2OFFSET(inst) - 2;
495 }
496 break;
497 case 0x09: /* bleu */
498 {
499 TRACE("bleu");
500 if (cpu.asregs.cc & (CC_LTU | CC_EQ))
501 pc += INST2OFFSET(inst) - 2;
502 }
503 break;
504 default:
505 {
506 TRACE("SIGILL3");
507 cpu.asregs.exception = SIGILL;
508 break;
509 }
510 }
fdd6fa61
AG
511 }
512 else
513 {
514 /* This is a Form 2 instruction. */
515 int opcode = (inst >> 12 & 0x3);
516 switch (opcode)
517 {
518 case 0x00: /* inc */
519 {
520 int a = (inst >> 8) & 0xf;
521 unsigned av = cpu.asregs.regs[a];
522 unsigned v = (inst & 0xff);
523 TRACE("inc");
524 cpu.asregs.regs[a] = av + v;
525 }
526 break;
527 case 0x01: /* dec */
528 {
529 int a = (inst >> 8) & 0xf;
530 unsigned av = cpu.asregs.regs[a];
531 unsigned v = (inst & 0xff);
532 TRACE("dec");
533 cpu.asregs.regs[a] = av - v;
534 }
535 break;
536 case 0x02: /* gsr */
537 {
538 int a = (inst >> 8) & 0xf;
539 unsigned v = (inst & 0xff);
540 TRACE("gsr");
541 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
542 }
77176dfc 543 break;
fdd6fa61
AG
544 case 0x03: /* ssr */
545 {
546 int a = (inst >> 8) & 0xf;
547 unsigned v = (inst & 0xff);
548 TRACE("ssr");
549 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
550 }
77176dfc 551 break;
fdd6fa61
AG
552 default:
553 TRACE("SIGILL2");
554 cpu.asregs.exception = SIGILL;
555 break;
556 }
557 }
558 }
559 else
560 {
561 /* This is a Form 1 instruction. */
562 int opcode = inst >> 8;
563 switch (opcode)
564 {
565 case 0x00: /* nop */
566 break;
567 case 0x01: /* ldi.l (immediate) */
568 {
569 int reg = (inst >> 4) & 0xf;
570 TRACE("ldi.l");
571 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
572 cpu.asregs.regs[reg] = val;
573 pc += 4;
574 }
575 break;
576 case 0x02: /* mov (register-to-register) */
577 {
578 int dest = (inst >> 4) & 0xf;
579 int src = (inst ) & 0xf;
580 TRACE("mov");
581 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
582 }
583 break;
584 case 0x03: /* jsra */
585 {
586 unsigned int fn = EXTRACT_WORD(&(memory[pc + 2]));
587 unsigned int sp = cpu.asregs.regs[1];
588 TRACE("jsra");
589 /* Save a slot for the static chain. */
590 sp -= 4;
591
592 /* Push the return address. */
593 sp -= 4;
594 wlat (opc, sp, pc + 6);
595
596 /* Push the current frame pointer. */
597 sp -= 4;
598 wlat (opc, sp, cpu.asregs.regs[0]);
599
600 /* Uncache the stack pointer and set the pc and $fp. */
601 cpu.asregs.regs[1] = sp;
602 cpu.asregs.regs[0] = sp;
603 pc = fn - 2;
604 }
605 break;
606 case 0x04: /* ret */
607 {
608 unsigned int sp = cpu.asregs.regs[0];
609
610 TRACE("ret");
611
612 /* Pop the frame pointer. */
613 cpu.asregs.regs[0] = rlat (opc, sp);
614 sp += 4;
615
616 /* Pop the return address. */
617 pc = rlat (opc, sp) - 2;
618 sp += 4;
619
620 /* Skip over the static chain slot. */
621 sp += 4;
622
623 /* Uncache the stack pointer. */
624 cpu.asregs.regs[1] = sp;
625 }
626 break;
627 case 0x05: /* add.l */
628 {
629 int a = (inst >> 4) & 0xf;
630 int b = inst & 0xf;
631 unsigned av = cpu.asregs.regs[a];
632 unsigned bv = cpu.asregs.regs[b];
633 TRACE("add.l");
634 cpu.asregs.regs[a] = av + bv;
635 }
636 break;
637 case 0x06: /* push */
638 {
639 int a = (inst >> 4) & 0xf;
640 int b = inst & 0xf;
641 int sp = cpu.asregs.regs[a] - 4;
642 TRACE("push");
643 wlat (opc, sp, cpu.asregs.regs[b]);
644 cpu.asregs.regs[a] = sp;
645 }
646 break;
647 case 0x07: /* pop */
648 {
649 int a = (inst >> 4) & 0xf;
650 int b = inst & 0xf;
651 int sp = cpu.asregs.regs[a];
652 TRACE("pop");
653 cpu.asregs.regs[b] = rlat (opc, sp);
654 cpu.asregs.regs[a] = sp + 4;
655 }
656 break;
657 case 0x08: /* lda.l */
658 {
659 int reg = (inst >> 4) & 0xf;
660 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
661 TRACE("lda.l");
662 cpu.asregs.regs[reg] = rlat (opc, addr);
663 pc += 4;
664 }
665 break;
666 case 0x09: /* sta.l */
667 {
668 int reg = (inst >> 4) & 0xf;
669 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
670 TRACE("sta.l");
671 wlat (opc, addr, cpu.asregs.regs[reg]);
672 pc += 4;
673 }
674 break;
675 case 0x0a: /* ld.l (register indirect) */
676 {
677 int src = inst & 0xf;
678 int dest = (inst >> 4) & 0xf;
679 int xv;
680 TRACE("ld.l");
681 xv = cpu.asregs.regs[src];
682 cpu.asregs.regs[dest] = rlat (opc, xv);
683 }
684 break;
685 case 0x0b: /* st.l */
686 {
687 int dest = (inst >> 4) & 0xf;
688 int val = inst & 0xf;
689 TRACE("st.l");
690 wlat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
691 }
692 break;
693 case 0x0c: /* ldo.l */
694 {
695 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
696 int a = (inst >> 4) & 0xf;
697 int b = inst & 0xf;
698 TRACE("ldo.l");
699 addr += cpu.asregs.regs[b];
700 cpu.asregs.regs[a] = rlat(opc, addr);
701 pc += 4;
702 }
703 break;
704 case 0x0d: /* sto.l */
705 {
706 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
707 int a = (inst >> 4) & 0xf;
708 int b = inst & 0xf;
709 TRACE("sto.l");
710 addr += cpu.asregs.regs[a];
711 wlat(opc, addr, cpu.asregs.regs[b]);
712 pc += 4;
713 }
714 break;
715 case 0x0e: /* cmp */
716 {
717 int a = (inst >> 4) & 0xf;
718 int b = inst & 0xf;
719 int cc = 0;
720 int va = cpu.asregs.regs[a];
721 int vb = cpu.asregs.regs[b];
722
723 TRACE("cmp");
724
725 if (va == vb)
726 cc = CC_EQ;
727 else
728 {
729 cc |= (va < vb ? CC_LT : 0);
730 cc |= (va > vb ? CC_GT : 0);
731 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
732 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
733 }
734
735 cpu.asregs.cc = cc;
736 }
737 break;
86566200
AG
738 case 0x0f:
739 case 0x10:
740 case 0x11:
741 case 0x12:
742 case 0x13:
743 case 0x14:
744 case 0x15:
745 case 0x16:
746 case 0x17:
747 case 0x18:
fdd6fa61 748 {
86566200
AG
749 opc = opcode;
750 TRACE("SIGILL0");
751 cpu.asregs.exception = SIGILL;
752 break;
fdd6fa61 753 }
fdd6fa61
AG
754 case 0x19: /* jsr */
755 {
756 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
757 unsigned int sp = cpu.asregs.regs[1];
758
759 TRACE("jsr");
760
761 /* Save a slot for the static chain. */
762 sp -= 4;
763
764 /* Push the return address. */
765 sp -= 4;
766 wlat (opc, sp, pc + 2);
767
768 /* Push the current frame pointer. */
769 sp -= 4;
770 wlat (opc, sp, cpu.asregs.regs[0]);
771
772 /* Uncache the stack pointer and set the fp & pc. */
773 cpu.asregs.regs[1] = sp;
774 cpu.asregs.regs[0] = sp;
775 pc = fn - 2;
776 }
777 break;
778 case 0x1a: /* jmpa */
779 {
780 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
781 TRACE("jmpa");
782 pc = tgt - 2;
783 }
784 break;
785 case 0x1b: /* ldi.b (immediate) */
786 {
787 int reg = (inst >> 4) & 0xf;
788
789 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
790 TRACE("ldi.b");
791 cpu.asregs.regs[reg] = val;
792 pc += 4;
793 }
794 break;
795 case 0x1c: /* ld.b (register indirect) */
796 {
797 int src = inst & 0xf;
798 int dest = (inst >> 4) & 0xf;
799 int xv;
800 TRACE("ld.b");
801 xv = cpu.asregs.regs[src];
802 cpu.asregs.regs[dest] = rbat (opc, xv);
803 }
804 break;
805 case 0x1d: /* lda.b */
806 {
807 int reg = (inst >> 4) & 0xf;
808 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
809 TRACE("lda.b");
810 cpu.asregs.regs[reg] = rbat (opc, addr);
811 pc += 4;
812 }
813 break;
814 case 0x1e: /* st.b */
815 {
816 int dest = (inst >> 4) & 0xf;
817 int val = inst & 0xf;
818 TRACE("st.b");
819 wbat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
820 }
821 break;
822 case 0x1f: /* sta.b */
823 {
824 int reg = (inst >> 4) & 0xf;
825 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
826 TRACE("sta.b");
827 wbat (opc, addr, cpu.asregs.regs[reg]);
828 pc += 4;
829 }
830 break;
831 case 0x20: /* ldi.s (immediate) */
832 {
833 int reg = (inst >> 4) & 0xf;
834
835 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
836 TRACE("ldi.s");
837 cpu.asregs.regs[reg] = val;
838 pc += 4;
839 }
840 break;
841 case 0x21: /* ld.s (register indirect) */
842 {
843 int src = inst & 0xf;
844 int dest = (inst >> 4) & 0xf;
845 int xv;
846 TRACE("ld.s");
847 xv = cpu.asregs.regs[src];
848 cpu.asregs.regs[dest] = rsat (opc, xv);
849 }
850 break;
851 case 0x22: /* lda.s */
852 {
853 int reg = (inst >> 4) & 0xf;
854 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
855 TRACE("lda.s");
856 cpu.asregs.regs[reg] = rsat (opc, addr);
857 pc += 4;
858 }
859 break;
860 case 0x23: /* st.s */
861 {
862 int dest = (inst >> 4) & 0xf;
863 int val = inst & 0xf;
864 TRACE("st.s");
865 wsat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
866 }
867 break;
868 case 0x24: /* sta.s */
869 {
870 int reg = (inst >> 4) & 0xf;
871 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
872 TRACE("sta.s");
873 wsat (opc, addr, cpu.asregs.regs[reg]);
874 pc += 4;
875 }
876 break;
877 case 0x25: /* jmp */
878 {
879 int reg = (inst >> 4) & 0xf;
880 TRACE("jmp");
881 pc = cpu.asregs.regs[reg] - 2;
882 }
883 break;
884 case 0x26: /* and */
885 {
886 int a = (inst >> 4) & 0xf;
887 int b = inst & 0xf;
888 int av, bv;
889 TRACE("and");
890 av = cpu.asregs.regs[a];
891 bv = cpu.asregs.regs[b];
892 cpu.asregs.regs[a] = av & bv;
893 }
894 break;
895 case 0x27: /* lshr */
896 {
897 int a = (inst >> 4) & 0xf;
898 int b = inst & 0xf;
899 int av = cpu.asregs.regs[a];
900 int bv = cpu.asregs.regs[b];
901 TRACE("lshr");
902 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
903 }
904 break;
905 case 0x28: /* ashl */
906 {
907 int a = (inst >> 4) & 0xf;
908 int b = inst & 0xf;
909 int av = cpu.asregs.regs[a];
910 int bv = cpu.asregs.regs[b];
911 TRACE("ashl");
912 cpu.asregs.regs[a] = av << bv;
913 }
914 break;
915 case 0x29: /* sub.l */
916 {
917 int a = (inst >> 4) & 0xf;
918 int b = inst & 0xf;
919 unsigned av = cpu.asregs.regs[a];
920 unsigned bv = cpu.asregs.regs[b];
921 TRACE("sub.l");
922 cpu.asregs.regs[a] = av - bv;
923 }
924 break;
925 case 0x2a: /* neg */
926 {
927 int a = (inst >> 4) & 0xf;
928 int b = inst & 0xf;
929 int bv = cpu.asregs.regs[b];
930 TRACE("neg");
931 cpu.asregs.regs[a] = - bv;
932 }
933 break;
934 case 0x2b: /* or */
935 {
936 int a = (inst >> 4) & 0xf;
937 int b = inst & 0xf;
938 int av, bv;
939 TRACE("or");
940 av = cpu.asregs.regs[a];
941 bv = cpu.asregs.regs[b];
942 cpu.asregs.regs[a] = av | bv;
943 }
944 break;
945 case 0x2c: /* not */
946 {
947 int a = (inst >> 4) & 0xf;
948 int b = inst & 0xf;
949 int bv = cpu.asregs.regs[b];
950 TRACE("not");
951 cpu.asregs.regs[a] = 0xffffffff ^ bv;
952 }
953 break;
954 case 0x2d: /* ashr */
955 {
956 int a = (inst >> 4) & 0xf;
957 int b = inst & 0xf;
958 int av = cpu.asregs.regs[a];
959 int bv = cpu.asregs.regs[b];
960 TRACE("ashr");
961 cpu.asregs.regs[a] = av >> bv;
962 }
963 break;
964 case 0x2e: /* xor */
965 {
966 int a = (inst >> 4) & 0xf;
967 int b = inst & 0xf;
968 int av, bv;
969 TRACE("xor");
970 av = cpu.asregs.regs[a];
971 bv = cpu.asregs.regs[b];
972 cpu.asregs.regs[a] = av ^ bv;
973 }
974 break;
975 case 0x2f: /* mul.l */
976 {
977 int a = (inst >> 4) & 0xf;
978 int b = inst & 0xf;
979 unsigned av = cpu.asregs.regs[a];
980 unsigned bv = cpu.asregs.regs[b];
981 TRACE("mul.l");
982 cpu.asregs.regs[a] = av * bv;
983 }
984 break;
985 case 0x30: /* swi */
986 {
987 unsigned int inum = EXTRACT_WORD(&memory[pc+2]);
988 TRACE("swi");
989 switch (inum)
990 {
991 case 0x1: /* SYS_exit */
992 {
993 cpu.asregs.exception = SIGQUIT;
994 break;
995 }
996 case 0x2: /* SYS_open */
997 {
998 char *fname = &memory[cpu.asregs.regs[2]];
999 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
7a321525 1000 int perm = (int) cpu.asregs.regs[4];
fdd6fa61 1001 int fd = open (fname, mode, perm);
fdd6fa61
AG
1002 /* FIXME - set errno */
1003 cpu.asregs.regs[2] = fd;
1004 break;
1005 }
1006 case 0x4: /* SYS_read */
1007 {
1008 int fd = cpu.asregs.regs[2];
1009 char *buf = &memory[cpu.asregs.regs[3]];
7a321525 1010 unsigned len = (unsigned) cpu.asregs.regs[4];
fdd6fa61
AG
1011 cpu.asregs.regs[2] = read (fd, buf, len);
1012 break;
1013 }
1014 case 0x5: /* SYS_write */
1015 {
1016 char *str = &memory[cpu.asregs.regs[3]];
1017 /* String length is at 0x12($fp) */
7a321525 1018 unsigned count, len = (unsigned) cpu.asregs.regs[4];
fdd6fa61
AG
1019 count = write (cpu.asregs.regs[2], str, len);
1020 cpu.asregs.regs[2] = count;
1021 break;
1022 }
7a321525
AG
1023 case 0xffffffff: /* Linux System Call */
1024 {
1025 unsigned int handler = cpu.asregs.sregs[1];
1026 unsigned int sp = cpu.asregs.regs[1];
1027 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
1028
1029 /* Save a slot for the static chain. */
1030 sp -= 4;
1031
1032 /* Push the return address. */
1033 sp -= 4;
1034 wlat (opc, sp, pc + 6);
1035
1036 /* Push the current frame pointer. */
1037 sp -= 4;
1038 wlat (opc, sp, cpu.asregs.regs[0]);
1039
1040 /* Uncache the stack pointer and set the fp & pc. */
1041 cpu.asregs.regs[1] = sp;
1042 cpu.asregs.regs[0] = sp;
1043 pc = handler - 6;
1044 }
fdd6fa61
AG
1045 default:
1046 break;
1047 }
1048 pc += 4;
1049 }
1050 break;
1051 case 0x31: /* div.l */
1052 {
1053 int a = (inst >> 4) & 0xf;
1054 int b = inst & 0xf;
1055 int av = cpu.asregs.regs[a];
1056 int bv = cpu.asregs.regs[b];
1057 TRACE("div.l");
1058 cpu.asregs.regs[a] = av / bv;
1059 }
1060 break;
1061 case 0x32: /* udiv.l */
1062 {
1063 int a = (inst >> 4) & 0xf;
1064 int b = inst & 0xf;
1065 unsigned int av = cpu.asregs.regs[a];
1066 unsigned int bv = cpu.asregs.regs[b];
1067 TRACE("udiv.l");
1068 cpu.asregs.regs[a] = (av / bv);
1069 }
1070 break;
1071 case 0x33: /* mod.l */
1072 {
1073 int a = (inst >> 4) & 0xf;
1074 int b = inst & 0xf;
1075 int av = cpu.asregs.regs[a];
1076 int bv = cpu.asregs.regs[b];
1077 TRACE("mod.l");
1078 cpu.asregs.regs[a] = av % bv;
1079 }
1080 break;
1081 case 0x34: /* umod.l */
1082 {
1083 int a = (inst >> 4) & 0xf;
1084 int b = inst & 0xf;
1085 unsigned int av = cpu.asregs.regs[a];
1086 unsigned int bv = cpu.asregs.regs[b];
1087 TRACE("umod.l");
1088 cpu.asregs.regs[a] = (av % bv);
1089 }
1090 break;
1091 case 0x35: /* brk */
1092 TRACE("brk");
1093 cpu.asregs.exception = SIGTRAP;
1094 pc -= 2; /* Adjust pc */
1095 break;
1096 case 0x36: /* ldo.b */
1097 {
1098 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1099 int a = (inst >> 4) & 0xf;
1100 int b = inst & 0xf;
1101 TRACE("ldo.b");
1102 addr += cpu.asregs.regs[b];
1103 cpu.asregs.regs[a] = rbat(opc, addr);
1104 pc += 4;
1105 }
1106 break;
1107 case 0x37: /* sto.b */
1108 {
1109 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1110 int a = (inst >> 4) & 0xf;
1111 int b = inst & 0xf;
1112 TRACE("sto.b");
1113 addr += cpu.asregs.regs[a];
1114 wbat(opc, addr, cpu.asregs.regs[b]);
1115 pc += 4;
1116 }
1117 break;
1118 case 0x38: /* ldo.s */
1119 {
1120 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1121 int a = (inst >> 4) & 0xf;
1122 int b = inst & 0xf;
1123 TRACE("ldo.s");
1124 addr += cpu.asregs.regs[b];
1125 cpu.asregs.regs[a] = rsat(opc, addr);
1126 pc += 4;
1127 }
1128 break;
1129 case 0x39: /* sto.s */
1130 {
1131 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1132 int a = (inst >> 4) & 0xf;
1133 int b = inst & 0xf;
1134 TRACE("sto.s");
1135 addr += cpu.asregs.regs[a];
1136 wsat(opc, addr, cpu.asregs.regs[b]);
1137 pc += 4;
1138 }
1139 break;
1140 default:
1141 opc = opcode;
1142 TRACE("SIGILL1");
1143 cpu.asregs.exception = SIGILL;
1144 break;
1145 }
1146 }
1147
1148 insts++;
1149 pc += 2;
1150
1151 } while (!cpu.asregs.exception);
1152
1153 /* Hide away the things we've cached while executing. */
1154 cpu.asregs.regs[PC_REGNO] = pc;
1155 cpu.asregs.insts += insts; /* instructions done ... */
1156
1157 signal (SIGINT, sigsave);
1158}
1159
1160int
1161sim_write (sd, addr, buffer, size)
1162 SIM_DESC sd;
1163 SIM_ADDR addr;
1164 unsigned char * buffer;
1165 int size;
1166{
1167 int i;
1168 init_pointers ();
1169
1170 memcpy (& cpu.asregs.memory[addr], buffer, size);
1171
1172 return size;
1173}
1174
1175int
1176sim_read (sd, addr, buffer, size)
1177 SIM_DESC sd;
1178 SIM_ADDR addr;
1179 unsigned char * buffer;
1180 int size;
1181{
1182 int i;
1183 init_pointers ();
1184
1185 memcpy (buffer, & cpu.asregs.memory[addr], size);
1186
1187 return size;
1188}
1189
1190
1191int
1192sim_store_register (sd, rn, memory, length)
1193 SIM_DESC sd;
1194 int rn;
1195 unsigned char * memory;
1196 int length;
1197{
1198 init_pointers ();
1199
1200 if (rn < NUM_MOXIE_REGS && rn >= 0)
1201 {
1202 if (length == 4)
1203 {
1204 long ival;
1205
1206 /* misalignment safe */
1207 ival = moxie_extract_unsigned_integer (memory, 4);
1208 cpu.asints[rn] = ival;
1209 }
1210
1211 return 4;
1212 }
1213 else
1214 return 0;
1215}
1216
1217int
1218sim_fetch_register (sd, rn, memory, length)
1219 SIM_DESC sd;
1220 int rn;
1221 unsigned char * memory;
1222 int length;
1223{
1224 init_pointers ();
1225
1226 if (rn < NUM_MOXIE_REGS && rn >= 0)
1227 {
1228 if (length == 4)
1229 {
1230 long ival = cpu.asints[rn];
1231
1232 /* misalignment-safe */
1233 moxie_store_unsigned_integer (memory, 4, ival);
1234 }
1235
1236 return 4;
1237 }
1238 else
1239 return 0;
1240}
1241
1242
1243int
1244sim_trace (sd)
1245 SIM_DESC sd;
1246{
1247 if (tracefile == 0)
1248 tracefile = fopen("trace.csv", "wb");
1249
1250 tracing = 1;
1251
1252 sim_resume (sd, 0, 0);
1253
1254 tracing = 0;
1255
1256 return 1;
1257}
1258
1259void
1260sim_stop_reason (sd, reason, sigrc)
1261 SIM_DESC sd;
1262 enum sim_stop * reason;
1263 int * sigrc;
1264{
1265 if (cpu.asregs.exception == SIGQUIT)
1266 {
1267 * reason = sim_exited;
1268 * sigrc = cpu.asregs.regs[2];
1269 }
1270 else
1271 {
1272 * reason = sim_stopped;
1273 * sigrc = cpu.asregs.exception;
1274 }
1275}
1276
1277
1278int
1279sim_stop (sd)
1280 SIM_DESC sd;
1281{
1282 cpu.asregs.exception = SIGINT;
1283 return 1;
1284}
1285
1286
1287void
1288sim_info (sd, verbose)
1289 SIM_DESC sd;
1290 int verbose;
1291{
1292 callback->printf_filtered (callback, "\n\n# instructions executed %llu\n",
1293 cpu.asregs.insts);
1294}
1295
1296
1297SIM_DESC
1298sim_open (kind, cb, abfd, argv)
1299 SIM_OPEN_KIND kind;
1300 host_callback * cb;
1301 struct bfd * abfd;
1302 char ** argv;
1303{
1304 int osize = sim_memory_size;
1305 myname = argv[0];
1306 callback = cb;
1307
1308 if (kind == SIM_OPEN_STANDALONE)
1309 issue_messages = 1;
1310
1311 /* Discard and reacquire memory -- start with a clean slate. */
1312 sim_size (1); /* small */
1313 sim_size (osize); /* and back again */
1314
1315 set_initial_gprs (); /* Reset the GPR registers. */
1316
1317 /* Fudge our descriptor for now. */
1318 return (SIM_DESC) 1;
1319}
1320
1321void
1322sim_close (sd, quitting)
1323 SIM_DESC sd;
1324 int quitting;
1325{
1326 /* nothing to do */
1327}
1328
1329SIM_RC
1330sim_load (sd, prog, abfd, from_tty)
1331 SIM_DESC sd;
1332 char * prog;
1333 bfd * abfd;
1334 int from_tty;
1335{
1336
1337 /* Do the right thing for ELF executables; this turns out to be
1338 just about the right thing for any object format that:
1339 - we crack using BFD routines
1340 - follows the traditional UNIX text/data/bss layout
1341 - calls the bss section ".bss". */
1342
1343 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1344 bfd * prog_bfd;
1345
1346 {
1347 bfd * handle;
1348 handle = bfd_openr (prog, 0); /* could be "moxie" */
1349
1350 if (!handle)
1351 {
1352 printf("``%s'' could not be opened.\n", prog);
1353 return SIM_RC_FAIL;
1354 }
1355
1356 /* Makes sure that we have an object file, also cleans gets the
1357 section headers in place. */
1358 if (!bfd_check_format (handle, bfd_object))
1359 {
1360 /* wasn't an object file */
1361 bfd_close (handle);
1362 printf ("``%s'' is not appropriate object file.\n", prog);
1363 return SIM_RC_FAIL;
1364 }
1365
1366 /* Clean up after ourselves. */
1367 bfd_close (handle);
1368 }
1369
1370 /* from sh -- dac */
1371 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1372 sim_kind == SIM_OPEN_DEBUG,
1373 0, sim_write);
1374 if (prog_bfd == NULL)
1375 return SIM_RC_FAIL;
1376
1377 if (abfd == NULL)
1378 bfd_close (prog_bfd);
1379
1380 return SIM_RC_OK;
1381}
1382
1383SIM_RC
1384sim_create_inferior (sd, prog_bfd, argv, env)
1385 SIM_DESC sd;
1386 struct bfd * prog_bfd;
1387 char ** argv;
1388 char ** env;
1389{
1390 char ** avp;
1391 int l, argc, i, tp;
1392
1393 /* Set the initial register set. */
1394 l = issue_messages;
1395 issue_messages = 0;
1396 set_initial_gprs ();
1397 issue_messages = l;
1398
1399 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1400
1401 /* Copy args into target memory. */
1402 avp = argv;
1403 for (argc = 0; *avp; avp++)
1404 argc++;
1405
1406 /* Target memory looks like this:
1407 0x00000000 zero word
1408 0x00000004 argc word
1409 0x00000008 start of argv
1410 .
1411 0x0000???? end of argv
1412 0x0000???? zero word
1413 0x0000???? start of data pointed to by argv */
1414
1415 wlat (0, 0, 0);
1416 wlat (0, 4, argc);
1417
1418 /* tp is the offset of our first argv data. */
1419 tp = 4 + 4 + argc * 4 + 4;
1420
1421 for (i = 0; i < argc; i++)
1422 {
1423 /* Set the argv value. */
1424 wlat (0, 4 + 4 + i * 4, tp);
1425
1426 /* Store the string. */
1427 strcpy (&cpu.asregs.memory[tp], argv[i]);
1428 tp += strlen (argv[i]) + 1;
1429 }
1430
1431 wlat (0, 4 + 4 + i * 4, 0);
1432
1433 return SIM_RC_OK;
1434}
1435
1436void
1437sim_kill (sd)
1438 SIM_DESC sd;
1439{
1440 if (tracefile)
1441 fclose(tracefile);
1442}
1443
1444void
1445sim_do_command (sd, cmd)
1446 SIM_DESC sd;
1447 char * cmd;
1448{
1449 /* Nothing there yet; it's all an error. */
1450
1451 if (cmd != NULL)
1452 {
1453 char ** simargv = buildargv (cmd);
1454 if (strcmp (simargv[0], "verbose") == 0)
1455 {
1456 issue_messages = 2;
1457 }
1458 else
1459 {
1460 fprintf (stderr,"Error: \"%s\" is not a valid moxie simulator command.\n",
1461 cmd);
1462 }
1463 }
1464 else
1465 {
1466 fprintf (stderr, "moxie sim commands: \n");
1467 fprintf (stderr, " verbose\n");
1468 }
1469}
1470
1471void
1472sim_set_callbacks (ptr)
1473 host_callback * ptr;
1474{
1475 callback = ptr;
1476}
This page took 0.098197 seconds and 4 git commands to generate.