1 /* Simulator for Motorolla's MCore processor
2 Copyright (C) 1999 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
5 This file is part of GDB, the GNU debugger.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <netinet/in.h> /* for byte ordering macros */
28 #include "libiberty.h"
29 #include "remote-sim.h"
32 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
36 typedef long int word
;
37 typedef unsigned long int uword
;
39 static unsigned long heap_ptr
= 0;
40 host_callback
* callback
;
43 #define TARGET_BYTE_ORDER BIG_ENDIAN /* XXX */
46 mcore_extract_unsigned_integer (addr
, len
)
52 unsigned char * startaddr
= (unsigned char *)addr
;
53 unsigned char * endaddr
= startaddr
+ len
;
55 if (len
> (int) sizeof (unsigned long))
56 printf ("That operation is not available on integers of more than %d bytes.",
57 sizeof (unsigned long));
59 /* Start at the most significant end of the integer, and work towards
60 the least significant. */
62 for (p
= startaddr
; p
< endaddr
; ++p
)
63 retval
= (retval
<< 8) | * p
;
69 mcore_store_unsigned_integer (addr
, len
, val
)
75 unsigned char * startaddr
= (unsigned char *)addr
;
76 unsigned char * endaddr
= startaddr
+ len
;
78 /* Start at the least significant end of the integer, and work towards
79 the most significant. */
80 for (p
= endaddr
- 1; p
>= startaddr
; --p
)
88 This state is maintained in host byte order. The
89 fetch/store register functions must translate between host
90 byte order and the target processor byte order (for MCore this
91 is big-endian). Since we know that the MCore is always big-endian,
92 we cheat a bit and use the ntohl() and htonl() macros to
95 Keeping this data in target byte order simplifies the register
96 read/write functions. Keeping this data in native order improves
97 the performance of the simulator. Simulation speed is deemed more
100 /* The ordering of the mcore_regset structure is matched in the
101 gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro. */
104 word gregs
[16]; /* primary registers */
105 word alt_gregs
[16]; /* alt register file */
106 word cregs
[32]; /* control registers */
107 word pc
; /* the pc */
114 unsigned char * memory
;
120 struct mcore_regset asregs
;
121 word asints
[1]; /* but accessed larger... */
124 #define LAST_VALID_CREG 12 /* only 0..12 implemented */
125 #define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG)
129 static SIM_OPEN_KIND sim_kind
;
130 static char * myname
;
132 static int issue_messages
= 0;
134 #define gr asregs.active_gregs
135 #define cr asregs.cregs
136 #define sr asregs.cregs[0]
137 #define vbr asregs.cregs[1]
138 #define esr asregs.cregs[2]
139 #define fsr asregs.cregs[3]
140 #define epc asregs.cregs[4]
141 #define fpc asregs.cregs[5]
142 #define ss0 asregs.cregs[6]
143 #define ss1 asregs.cregs[7]
144 #define ss2 asregs.cregs[8]
145 #define ss3 asregs.cregs[9]
146 #define ss4 asregs.cregs[10]
147 #define gcr asregs.cregs[11]
148 #define gsr asregs.cregs[12]
149 #define mem asregs.memory
151 /* maniuplate the carry bit */
152 #define C_ON() (cpu.sr & 1)
153 #define C_VALUE() (cpu.sr & 1)
154 #define C_OFF() ((cpu.sr & 1) == 0)
155 #define SET_C() {cpu.sr |= 1;}
156 #define CLR_C() {cpu.sr &= 0xfffffffe;}
157 #define NEW_C(v){CLR_C(); cpu.sr |= ((v) & 1);}
159 #define SR_AF() ((cpu.sr >> 1) & 1)
161 #define TRAPCODE 1 /* r1 holds which function we want */
162 #define PARM1 2 /* first parameter */
166 #define RET1 2 /* register for return values. */
176 heap_ptr
+= inc_bytes
;
178 if (issue_messages
&& heap_ptr
>cpu
.gr
[0])
179 fprintf (stderr
, "Warning: heap_ptr overlaps stack!\n");
188 if (((uword
)x
) >= cpu
.asregs
.msize
)
191 fprintf (stderr
, "byte write to 0x%x outside memory range\n", x
);
193 cpu
.asregs
.exception
= SIGSEGV
;
197 unsigned char *p
= cpu
.mem
+ x
;
206 if (((uword
)x
) >= cpu
.asregs
.msize
)
209 fprintf (stderr
, "word write to 0x%x outside memory range\n", x
);
211 cpu
.asregs
.exception
= SIGSEGV
;
218 fprintf (stderr
, "word write to unaligned memory address: 0x%x\n", x
);
220 cpu
.asregs
.exception
= SIGBUS
;
224 unsigned char * p
= cpu
.mem
+ x
;
237 if (((uword
)x
) >= cpu
.asregs
.msize
)
240 fprintf (stderr
, "short write to 0x%x outside memory range\n", x
);
242 cpu
.asregs
.exception
= SIGSEGV
;
249 fprintf (stderr
, "short write to unaligned memory address: 0x%x\n", x
);
251 cpu
.asregs
.exception
= SIGBUS
;
255 unsigned char * p
= cpu
.mem
+ x
;
267 if (((uword
)x
) >= cpu
.asregs
.msize
)
270 fprintf (stderr
, "byte read from 0x%x outside memory range\n", x
);
272 cpu
.asregs
.exception
= SIGSEGV
;
277 unsigned char * p
= cpu
.mem
+ x
;
286 if (((uword
) x
) >= cpu
.asregs
.msize
)
289 fprintf (stderr
, "word read from 0x%x outside memory range\n", x
);
291 cpu
.asregs
.exception
= SIGSEGV
;
299 fprintf (stderr
, "word read from unaligned address: 0x%x\n", x
);
301 cpu
.asregs
.exception
= SIGBUS
;
306 unsigned char * p
= cpu
.mem
+ x
;
307 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
316 if (((uword
)x
) >= cpu
.asregs
.msize
)
319 fprintf (stderr
, "short read from 0x%x outside memory range\n", x
);
321 cpu
.asregs
.exception
= SIGSEGV
;
329 fprintf (stderr
, "short read from unaligned address: 0x%x\n", x
);
331 cpu
.asregs
.exception
= SIGBUS
;
336 unsigned char * p
= cpu
.mem
+ x
;
337 return (p
[0] << 8) | p
[1];
343 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
344 #define SEXTW(y) ((int)((short)y))
347 IOMEM (addr
, write
, value
)
354 /* default to a 8 Mbyte (== 2^23) memory space */
355 static int sim_memory_size
= 23;
357 #define MEM_SIZE_FLOOR 64
362 sim_memory_size
= power
;
363 cpu
.asregs
.msize
= 1 << sim_memory_size
;
368 /* watch out for the '0 count' problem. There's probably a better
369 way.. e.g., why do we use 64 here? */
370 if (cpu
.asregs
.msize
< 64) /* ensure a boundary */
371 cpu
.mem
= (unsigned char *) calloc (64, (64 + cpu
.asregs
.msize
) / 64);
373 cpu
.mem
= (unsigned char *) calloc (64, cpu
.asregs
.msize
/ 64);
379 "Not enough VM for simulation of %d bytes of RAM\n", cpu
.asregs
.msize
);
381 cpu
.asregs
.msize
= 1;
382 cpu
.mem
= (unsigned char *) calloc (1, 1);
389 if (cpu
.asregs
.msize
!= (1 << sim_memory_size
))
390 sim_size (sim_memory_size
);
398 unsigned long memsize
;
402 /* Set up machine just out of reset. */
406 memsize
= cpu
.asregs
.msize
/ (1024 * 1024);
408 if (issue_messages
> 1)
409 fprintf (stderr
, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
410 memsize
, cpu
.asregs
.msize
- 1);
412 /* Clean out the GPRs and alternate GPRs. */
413 for (i
= 0; i
< 16; i
++)
415 cpu
.asregs
.gregs
[i
] = 0;
416 cpu
.asregs
.alt_gregs
[i
] = 0;
419 /* Make our register set point to the right place. */
421 cpu
.asregs
.active_gregs
= &cpu
.asregs
.alt_gregs
[0];
423 cpu
.asregs
.active_gregs
= &cpu
.asregs
.gregs
[0];
425 /* ABI specifies initial values for these registers. */
426 cpu
.gr
[0] = cpu
.asregs
.msize
- 4;
428 /* dac fix, the stack address must be 8-byte aligned! */
429 cpu
.gr
[0] = cpu
.gr
[0] - cpu
.gr
[0] % 8;
433 cpu
.gr
[PARM4
] = cpu
.gr
[0];
439 cpu
.asregs
.exception
= SIGINT
;
442 /* Functions so that trapped open/close don't interfere with the
443 parent's functions. We say that we can't close the descriptors
444 that we didn't open. exit() and cleanup() get in trouble here,
445 to some extent. That's the price of emulation. */
447 unsigned char opened
[100];
453 if (fd
< 0 || fd
> NUM_ELEM (opened
))
463 if (fd
< 0 || fd
> NUM_ELEM (opened
))
473 if (fd
< 0 || fd
> NUM_ELEM (opened
))
484 switch ((unsigned long) (cpu
.gr
[TRAPCODE
]))
487 a
[0] = (unsigned long) (cpu
.gr
[PARM1
]);
488 a
[1] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM2
]);
489 a
[2] = (unsigned long) (cpu
.gr
[PARM3
]);
490 cpu
.gr
[RET1
] = callback
->read (callback
, a
[0], (char *) a
[1], a
[2]);
494 a
[0] = (unsigned long) (cpu
.gr
[PARM1
]);
495 a
[1] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM2
]);
496 a
[2] = (unsigned long) (cpu
.gr
[PARM3
]);
497 cpu
.gr
[RET1
] = (int)callback
->write (callback
, a
[0], (char *) a
[1], a
[2]);
501 a
[0] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM1
]);
502 a
[1] = (unsigned long) (cpu
.gr
[PARM2
]);
503 /* a[2] = (unsigned long) (cpu.gr[PARM3]); */
504 cpu
.gr
[RET1
] = callback
->open (callback
, (char *) a
[0], a
[1]);
505 log_open (cpu
.gr
[RET1
]);
509 a
[0] = (unsigned long) (cpu
.gr
[4]);
510 /* Watch out for debugger's files. */
511 if (is_opened (a
[0]))
514 cpu
.gr
[RET1
] = callback
->close (callback
, a
[0]);
518 /* Don't let him close it. */
524 a
[0] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM1
]);
525 a
[1] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM2
]);
526 cpu
.gr
[RET1
] = link ((char *) a
[0], (char *) a
[1]);
530 a
[0] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM1
]);
531 cpu
.gr
[RET1
] = callback
->unlink (callback
, (char *) a
[0]);
535 /* handle time(0) vs time(&var) */
536 a
[0] = (unsigned long) (cpu
.gr
[PARM1
]);
538 a
[0] += (unsigned long) cpu
.mem
;
539 cpu
.gr
[RET1
] = callback
->time (callback
, (time_t *) a
[0]);
543 a
[0] = (unsigned long) (cpu
.gr
[PARM1
]);
544 a
[1] = (unsigned long) (cpu
.gr
[PARM2
]);
545 a
[2] = (unsigned long) (cpu
.gr
[PARM3
]);
546 cpu
.gr
[RET1
] = callback
->lseek (callback
, a
[0], a
[1], a
[2]);
550 a
[0] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM1
]);
551 a
[1] = (unsigned long) (cpu
.gr
[PARM2
]);
552 cpu
.gr
[RET1
] = access ((char *) a
[0], a
[1]);
556 a
[0] = (unsigned long) (cpu
.mem
+ cpu
.gr
[PARM1
]);
558 cpu
.gr
[RET1
] = times ((char *)a
[0]);
561 /* Give him simulated cycles for utime
562 and an instruction count for stime. */
571 t
.tms_utime
= cpu
.asregs
.cycles
;
572 t
.tms_stime
= cpu
.asregs
.insts
;
573 t
.tms_cutime
= t
.tms_utime
;
574 t
.tms_cstime
= t
.tms_stime
;
576 memcpy ((struct tms
*)(a
[0]), &t
, sizeof (t
));
578 cpu
.gr
[RET1
] = cpu
.asregs
.cycles
;
584 a
[0] = (unsigned long) (cpu
.gr
[PARM1
]);
585 cpu
.gr
[RET1
] = int_sbrk (a
[0]);
590 fprintf (stderr
, "WARNING: sys call %d unimplemented\n", cpu
.gr
[TRAPCODE
]);
599 /* These values should match those in libgloss/mcore/syscalls.s. */
605 case 10: /* _unlink */
606 case 19: /* _lseek */
607 case 43: /* _times */
608 cpu
.gr
[TRAPCODE
] = what
;
614 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
626 cpu
.asregs
.exception
= SIGQUIT
;
635 a
[0] = (unsigned long)(cpu
.mem
+ cpu
.gr
[PARM1
]);
637 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
642 a
[i
] = (unsigned long)(cpu
.mem
+ cpu
.gr
[PARM1
+i
]);
644 a
[i
] = cpu
.gr
[i
+PARM1
];
649 cpu
.gr
[RET1
] = printf ((char *)a
[0], a
[1], a
[2], a
[3], a
[4], a
[5]);
655 fprintf (stderr
, "WARNING: scanf unimplemented\n");
659 cpu
.gr
[RET1
] = cpu
.asregs
.insts
;
668 fprintf (stderr
, "Unhandled util code: %x\n", what
);
673 /* For figuring out whether we carried; addc/subc use this. */
682 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
683 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
689 #define WATCHFUNCTIONS 1
690 #ifdef WATCHFUNCTIONS
707 #define RD (inst & 0xF)
708 #define RS ((inst >> 4) & 0xF)
709 #define RX ((inst >> 8) & 0xF)
710 #define IMM5 ((inst >> 4) & 0x1F)
711 #define IMM4 ((inst) & 0xF)
713 static int tracing
= 0;
716 sim_resume (sd
, step
, siggnal
)
732 sigsave
= signal (SIGINT
, interrupt
);
733 cpu
.asregs
.exception
= step
? SIGTRAP
: 0;
736 /* fetch the initial instructions that we'll decode */
737 ibuf
= rlat (pc
& 0xFFFFFFFC);
744 /* make our register set point to the right place */
746 cpu
.asregs
.active_gregs
= & cpu
.asregs
.alt_gregs
[0];
748 cpu
.asregs
.active_gregs
= & cpu
.asregs
.gregs
[0];
750 /* make a hash to speed exec loop, hope it's nonzero */
753 for (w
= 1; w
<= ENDWL
; w
++)
754 WLhash
= WLhash
& WL
[w
];
762 inst
= ibuf
& 0xFFFF;
770 #ifdef WATCHFUNCTIONS
771 /* now scan list of watch addresses, if match, count it and
772 note return address and count cycles until pc=return address */
774 if ((WLincyc
== 1) && (pc
== WLendpc
))
776 cycs
= (cpu
.asregs
.cycles
+ (insts
+ bonus_cycles
+
777 (memops
* memcycles
)) - WLbcyc
);
779 if (WLcnts
[WLW
] == 1)
786 if (cycs
> WLmax
[WLW
])
791 if (cycs
< WLmin
[WLW
])
801 /* optimize with a hash to speed loop */
804 if ((WLhash
== 0) || ((WLhash
& pc
) != 0))
806 for (w
=1; w
<= ENDWL
; w
++)
811 WLbcyc
= cpu
.asregs
.cycles
+ insts
812 + bonus_cycles
+ (memops
* memcycles
);
813 WLendpc
= cpu
.gr
[15];
824 fprintf (stderr
, "%.4x: inst = %.4x ", pc
, inst
);
837 cpu
.asregs
.exception
= SIGTRAP
;
849 cpu
.asregs
.active_gregs
= & cpu
.asregs
.alt_gregs
[0];
851 cpu
.asregs
.active_gregs
= & cpu
.asregs
.gregs
[0];
860 cpu
.asregs
.active_gregs
= &cpu
.asregs
.alt_gregs
[0];
862 cpu
.asregs
.active_gregs
= &cpu
.asregs
.gregs
[0];
867 fprintf (stderr
, "WARNING: stop unimplemented\n");
872 fprintf (stderr
, "WARNING: wait unimplemented\n");
877 fprintf (stderr
, "WARNING: oze unimplemented\n");
881 cpu
.asregs
.exception
= SIGILL
; /* illegal */
884 case 0x8: /* trap 0 */
885 case 0xA: /* trap 2 */
886 case 0xB: /* trap 3 */
887 cpu
.asregs
.exception
= SIGTRAP
;
890 case 0xC: /* trap 4 */
891 case 0xD: /* trap 5 */
892 case 0xE: /* trap 6 */
893 cpu
.asregs
.exception
= SIGILL
; /* illegal */
896 case 0xF: /* trap 7 */
897 cpu
.asregs
.exception
= SIGTRAP
; /* integer div-by-0 */
900 case 0x9: /* trap 1 */
907 cpu
.asregs
.exception
= SIGILL
; /* illegal */
911 cpu
.gr
[RD
] = C_VALUE();
914 cpu
.gr
[RD
] = C_OFF();
918 char *addr
= (char *)cpu
.gr
[RD
];
919 int regno
= 4; /* always r4-r7 */
925 cpu
.gr
[regno
] = rlat(addr
);
929 while ((regno
&0x3) != 0);
934 char *addr
= (char *)cpu
.gr
[RD
];
935 int regno
= 4; /* always r4-r7 */
941 wlat(addr
, cpu
.gr
[regno
]);
945 while ((regno
& 0x3) != 0);
950 char *addr
= (char *)cpu
.gr
[0];
953 /* bonus cycle is really only needed if
954 the next insn shifts the last reg loaded.
961 cpu
.gr
[regno
] = rlat(addr
);
969 char *addr
= (char *)cpu
.gr
[0];
972 /* this should be removed! */
973 /* bonus_cycles ++; */
975 memops
+= 16 - regno
;
978 wlat(addr
, cpu
.gr
[regno
]);
986 cpu
.gr
[RD
] -= C_VALUE();
989 cpu
.gr
[RD
] -= C_OFF();
992 cpu
.gr
[RD
] += C_VALUE();
995 cpu
.gr
[RD
] += C_OFF();
1012 for (i
= 0; !(tmp
& 0x80000000) && i
< 32; i
++)
1017 case 0xF: /* brev */
1021 tmp
= ((tmp
& 0xaaaaaaaa) >> 1) | ((tmp
& 0x55555555) << 1);
1022 tmp
= ((tmp
& 0xcccccccc) >> 2) | ((tmp
& 0x33333333) << 2);
1023 tmp
= ((tmp
& 0xf0f0f0f0) >> 4) | ((tmp
& 0x0f0f0f0f) << 4);
1024 tmp
= ((tmp
& 0xff00ff00) >> 8) | ((tmp
& 0x00ff00ff) << 8);
1025 cpu
.gr
[RD
] = ((tmp
& 0xffff0000) >> 16) | ((tmp
& 0x0000ffff) << 16);
1033 case 0x0: /* xtrb3 */
1034 cpu
.gr
[1] = (cpu
.gr
[RD
]) & 0xFF;
1035 NEW_C (cpu
.gr
[RD
] != 0);
1037 case 0x1: /* xtrb2 */
1038 cpu
.gr
[1] = (cpu
.gr
[RD
]>>8) & 0xFF;
1039 NEW_C (cpu
.gr
[RD
] != 0);
1041 case 0x2: /* xtrb1 */
1042 cpu
.gr
[1] = (cpu
.gr
[RD
]>>16) & 0xFF;
1043 NEW_C (cpu
.gr
[RD
] != 0);
1045 case 0x3: /* xtrb0 */
1046 cpu
.gr
[1] = (cpu
.gr
[RD
]>>24) & 0xFF;
1047 NEW_C (cpu
.gr
[RD
] != 0);
1049 case 0x4: /* zextb */
1050 cpu
.gr
[RD
] &= 0x000000FF;
1052 case 0x5: /* sextb */
1061 case 0x6: /* zexth */
1062 cpu
.gr
[RD
] &= 0x0000FFFF;
1064 case 0x7: /* sexth */
1073 case 0x8: /* declt */
1075 NEW_C ((long)cpu
.gr
[RD
] < 0);
1077 case 0x9: /* tstnbz */
1079 word tmp
= cpu
.gr
[RD
];
1080 NEW_C ((tmp
& 0xFF000000) != 0 &&
1081 (tmp
& 0x00FF0000) != 0 && (tmp
& 0x0000FF00) != 0 &&
1082 (tmp
& 0x000000FF) != 0);
1085 case 0xA: /* decgt */
1087 NEW_C ((long)cpu
.gr
[RD
] > 0);
1089 case 0xB: /* decne */
1091 NEW_C ((long)cpu
.gr
[RD
] != 0);
1093 case 0xC: /* clrt */
1097 case 0xD: /* clrf */
1102 if (cpu
.gr
[RD
] & 0x80000000)
1103 cpu
.gr
[RD
] = ~cpu
.gr
[RD
] + 1;
1106 cpu
.gr
[RD
] = ~cpu
.gr
[RD
];
1110 case 0x02: /* movt */
1112 cpu
.gr
[RD
] = cpu
.gr
[RS
];
1114 case 0x03: /* mult */
1115 /* consume 2 bits per cycle from rs, until rs is 0 */
1117 unsigned int t
= cpu
.gr
[RS
];
1119 for (ticks
= 0; t
!= 0 ; t
>>= 2)
1121 bonus_cycles
+= ticks
;
1123 bonus_cycles
+= 2; /* min. is 3, so add 2, plus ticks above */
1124 cpu
.gr
[RD
] = cpu
.gr
[RD
] * cpu
.gr
[RS
];
1126 case 0x04: /* loopt */
1129 pc
+= (IMM4
<< 1) - 32;
1133 --cpu
.gr
[RS
]; /* not RD! */
1134 NEW_C (((long)cpu
.gr
[RS
]) > 0);
1136 case 0x05: /* subu */
1137 cpu
.gr
[RD
] -= cpu
.gr
[RS
];
1139 case 0x06: /* addc */
1141 unsigned long tmp
, a
, b
;
1144 cpu
.gr
[RD
] = a
+ b
+ C_VALUE ();
1145 tmp
= iu_carry (a
, b
, C_VALUE ());
1149 case 0x07: /* subc */
1151 unsigned long tmp
, a
, b
;
1154 cpu
.gr
[RD
] = a
- b
+ C_VALUE () - 1;
1155 tmp
= iu_carry (a
,~b
, C_VALUE ());
1159 case 0x08: /* illegal */
1160 case 0x09: /* illegal*/
1161 cpu
.asregs
.exception
= SIGILL
;
1163 case 0x0A: /* movf */
1165 cpu
.gr
[RD
] = cpu
.gr
[RS
];
1167 case 0x0B: /* lsr */
1169 unsigned long dst
, src
;
1176 case 0x0C: /* cmphs */
1177 NEW_C ((unsigned long )cpu
.gr
[RD
] >=
1178 (unsigned long)cpu
.gr
[RS
]);
1180 case 0x0D: /* cmplt */
1181 NEW_C ((long)cpu
.gr
[RD
] < (long)cpu
.gr
[RS
]);
1183 case 0x0E: /* tst */
1184 NEW_C ((cpu
.gr
[RD
] & cpu
.gr
[RS
]) != 0);
1186 case 0x0F: /* cmpne */
1187 NEW_C (cpu
.gr
[RD
] != cpu
.gr
[RS
]);
1189 case 0x10: case 0x11: /* mfcr */
1193 if (r
<= LAST_VALID_CREG
)
1194 cpu
.gr
[RD
] = cpu
.cr
[r
];
1196 cpu
.asregs
.exception
= SIGILL
;
1200 case 0x12: /* mov */
1201 cpu
.gr
[RD
] = cpu
.gr
[RS
];
1204 case 0x13: /* bgenr */
1205 if (cpu
.gr
[RS
] & 0x20)
1208 cpu
.gr
[RD
] = 1 << (cpu
.gr
[RS
] & 0x1F);
1211 case 0x14: /* rsub */
1212 cpu
.gr
[RD
] = cpu
.gr
[RS
] - cpu
.gr
[RD
];
1215 case 0x15: /* ixw */
1216 cpu
.gr
[RD
] += cpu
.gr
[RS
]<<2;
1219 case 0x16: /* and */
1220 cpu
.gr
[RD
] &= cpu
.gr
[RS
];
1223 case 0x17: /* xor */
1224 cpu
.gr
[RD
] ^= cpu
.gr
[RS
];
1227 case 0x18: case 0x19: /* mtcr */
1231 if (r
<= LAST_VALID_CREG
)
1232 cpu
.cr
[r
] = cpu
.gr
[RD
];
1234 cpu
.asregs
.exception
= SIGILL
;
1236 /* we might have changed register sets... */
1238 cpu
.asregs
.active_gregs
= & cpu
.asregs
.alt_gregs
[0];
1240 cpu
.asregs
.active_gregs
= & cpu
.asregs
.gregs
[0];
1244 case 0x1A: /* asr */
1245 cpu
.gr
[RD
] = (long)cpu
.gr
[RD
] >> cpu
.gr
[RS
];
1248 case 0x1B: /* lsl */
1249 cpu
.gr
[RD
] = cpu
.gr
[RD
] << cpu
.gr
[RS
];
1252 case 0x1C: /* addu */
1253 cpu
.gr
[RD
] += cpu
.gr
[RS
];
1256 case 0x1D: /* ixh */
1257 cpu
.gr
[RD
] += cpu
.gr
[RS
] << 1;
1261 cpu
.gr
[RD
] |= cpu
.gr
[RS
];
1264 case 0x1F: /* andn */
1265 cpu
.gr
[RD
] &= ~cpu
.gr
[RS
];
1267 case 0x20: case 0x21: /* addi */
1269 cpu
.gr
[RD
] + (IMM5
+ 1);
1271 case 0x22: case 0x23: /* cmplti */
1273 int tmp
= (IMM5
+ 1);
1274 if (cpu
.gr
[RD
] < tmp
)
1284 case 0x24: case 0x25: /* subi */
1286 cpu
.gr
[RD
] - (IMM5
+ 1);
1288 case 0x26: case 0x27: /* illegal */
1289 cpu
.asregs
.exception
= SIGILL
;
1291 case 0x28: case 0x29: /* rsubi */
1295 case 0x2A: case 0x2B: /* cmpnei */
1296 if (cpu
.gr
[RD
] != IMM5
)
1306 case 0x2C: case 0x2D: /* bmaski, divu */
1308 unsigned imm
= IMM5
;
1314 unsigned int rx
, r1
;
1320 /* unsigned divide */
1321 cpu
.gr
[RD
] = (word
) ((unsigned int) cpu
.gr
[RD
] / (unsigned int)cpu
.gr
[1] );
1323 /* compute bonus_cycles for divu */
1324 for (r1nlz
= 0; ((r1
& 0x80000000) == 0) && (r1nlz
< 32); r1nlz
++)
1327 for (rxnlz
= 0; ((rx
& 0x80000000) == 0) && (rxnlz
< 32); rxnlz
++)
1333 exe
+= 5 + r1nlz
- rxnlz
;
1335 if (exe
>= (2 * memcycles
- 1))
1337 bonus_cycles
+= exe
- (2 * memcycles
) + 1;
1340 else if (imm
== 0 || imm
>= 8)
1346 cpu
.gr
[RD
] = (1 << imm
) - 1;
1351 cpu
.asregs
.exception
= SIGILL
;
1355 case 0x2E: case 0x2F: /* andi */
1356 cpu
.gr
[RD
] = cpu
.gr
[RD
] & IMM5
;
1358 case 0x30: case 0x31: /* bclri */
1359 cpu
.gr
[RD
] = cpu
.gr
[RD
] & ~(1<<IMM5
);
1361 case 0x32: case 0x33: /* bgeni, divs */
1363 unsigned imm
= IMM5
;
1370 /* compute bonus_cycles for divu */
1375 if (((rx
< 0) && (r1
> 0)) || ((rx
>= 0) && (r1
< 0)))
1383 /* signed divide, general registers are of type int, so / op is OK */
1384 cpu
.gr
[RD
] = cpu
.gr
[RD
] / cpu
.gr
[1];
1386 for (r1nlz
= 0; ((r1
& 0x80000000) == 0) && (r1nlz
< 32) ; r1nlz
++ )
1389 for (rxnlz
= 0; ((rx
& 0x80000000) == 0) && (rxnlz
< 32) ; rxnlz
++ )
1395 exe
+= 6 + r1nlz
- rxnlz
+ sc
;
1397 if (exe
>= (2 * memcycles
- 1))
1399 bonus_cycles
+= exe
- (2 * memcycles
) + 1;
1405 cpu
.gr
[RD
] = (1 << IMM5
);
1410 cpu
.asregs
.exception
= SIGILL
;
1414 case 0x34: case 0x35: /* bseti */
1415 cpu
.gr
[RD
] = cpu
.gr
[RD
] | (1 << IMM5
);
1417 case 0x36: case 0x37: /* btsti */
1418 NEW_C (cpu
.gr
[RD
] >> IMM5
);
1420 case 0x38: case 0x39: /* xsr, rotli */
1422 unsigned imm
= IMM5
;
1423 unsigned long tmp
= cpu
.gr
[RD
];
1429 cpu
.gr
[RD
] = (cbit
<< 31) | (tmp
>> 1);
1432 cpu
.gr
[RD
] = (tmp
<< imm
) | (tmp
>> (32 - imm
));
1435 case 0x3A: case 0x3B: /* asrc, asri */
1437 unsigned imm
= IMM5
;
1438 long tmp
= cpu
.gr
[RD
];
1442 cpu
.gr
[RD
] = tmp
>> 1;
1445 cpu
.gr
[RD
] = tmp
>> imm
;
1448 case 0x3C: case 0x3D: /* lslc, lsli */
1450 unsigned imm
= IMM5
;
1451 unsigned long tmp
= cpu
.gr
[RD
];
1455 cpu
.gr
[RD
] = tmp
<< 1;
1458 cpu
.gr
[RD
] = tmp
<< imm
;
1461 case 0x3E: case 0x3F: /* lsrc, lsri */
1463 unsigned imm
= IMM5
;
1464 unsigned long tmp
= cpu
.gr
[RD
];
1468 cpu
.gr
[RD
] = tmp
>> 1;
1471 cpu
.gr
[RD
] = tmp
>> imm
;
1474 case 0x40: case 0x41: case 0x42: case 0x43:
1475 case 0x44: case 0x45: case 0x46: case 0x47:
1476 case 0x48: case 0x49: case 0x4A: case 0x4B:
1477 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1478 cpu
.asregs
.exception
= SIGILL
;
1483 case 0x51: case 0x52: case 0x53:
1484 case 0x54: case 0x55: case 0x56: case 0x57:
1485 case 0x58: case 0x59: case 0x5A: case 0x5B:
1486 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1487 cpu
.asregs
.exception
= SIGILL
;
1489 case 0x60: case 0x61: case 0x62: case 0x63: /* movi */
1490 case 0x64: case 0x65: case 0x66: case 0x67:
1491 cpu
.gr
[RD
] = (inst
>> 4) & 0x7F;
1493 case 0x68: case 0x69: case 0x6A: case 0x6B:
1494 case 0x6C: case 0x6D: case 0x6E: case 0x6F: /* illegal */
1495 cpu
.asregs
.exception
= SIGILL
;
1497 case 0x71: case 0x72: case 0x73:
1498 case 0x74: case 0x75: case 0x76: case 0x77:
1499 case 0x78: case 0x79: case 0x7A: case 0x7B:
1500 case 0x7C: case 0x7D: case 0x7E: /* lrw */
1501 cpu
.gr
[RX
] = rlat ((pc
+ ((inst
& 0xFF) << 2)) & 0xFFFFFFFC);
1503 fprintf (stderr
, "LRW of 0x%x from 0x%x to reg %d",
1504 rlat ((pc
+ ((inst
& 0xFF) << 2)) & 0xFFFFFFFC),
1505 (pc
+ ((inst
& 0xFF) << 2)) & 0xFFFFFFFC, RX
);
1508 case 0x7F: /* jsri */
1510 case 0x70: /* jmpi */
1511 pc
= rlat ((pc
+ ((inst
& 0xFF) << 2)) & 0xFFFFFFFC);
1517 case 0x80: case 0x81: case 0x82: case 0x83:
1518 case 0x84: case 0x85: case 0x86: case 0x87:
1519 case 0x88: case 0x89: case 0x8A: case 0x8B:
1520 case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* ld */
1521 cpu
.gr
[RX
] = rlat (cpu
.gr
[RD
] + ((inst
>> 2) & 0x003C));
1523 fprintf (stderr
, "load reg %d from 0x%x with 0x%x",
1525 cpu
.gr
[RD
] + ((inst
>> 2) & 0x003C), cpu
.gr
[RX
]);
1528 case 0x90: case 0x91: case 0x92: case 0x93:
1529 case 0x94: case 0x95: case 0x96: case 0x97:
1530 case 0x98: case 0x99: case 0x9A: case 0x9B:
1531 case 0x9C: case 0x9D: case 0x9E: case 0x9F: /* st */
1532 wlat (cpu
.gr
[RD
] + ((inst
>> 2) & 0x003C), cpu
.gr
[RX
]);
1534 fprintf (stderr
, "store reg %d (containing 0x%x) to 0x%x",
1536 cpu
.gr
[RD
] + ((inst
>> 2) & 0x003C));
1539 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1540 case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1541 case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1542 case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* ld.b */
1543 cpu
.gr
[RX
] = rbat (cpu
.gr
[RD
] + RS
);
1546 case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1547 case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1548 case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1549 case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* st.b */
1550 wbat (cpu
.gr
[RD
] + RS
, cpu
.gr
[RX
]);
1553 case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1554 case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1555 case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1556 case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* ld.h */
1557 cpu
.gr
[RX
] = rhat (cpu
.gr
[RD
] + ((inst
>> 3) & 0x001E));
1560 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1561 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1562 case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1563 case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* st.h */
1564 what (cpu
.gr
[RD
] + ((inst
>> 3) & 0x001E), cpu
.gr
[RX
]);
1567 case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1568 case 0xEC: case 0xED: case 0xEE: case 0xEF: /* bf */
1572 disp
= inst
& 0x03FF;
1580 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1581 case 0xE4: case 0xE5: case 0xE6: case 0xE7: /* bt */
1585 disp
= inst
& 0x03FF;
1594 case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1595 case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* bsr */
1597 case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1598 case 0xF4: case 0xF5: case 0xF6: case 0xF7: /* br */
1601 disp
= inst
& 0x03FF;
1613 fprintf (stderr
, "\n");
1617 /* Do not let him fetch from a bad address! */
1618 if (((uword
)pc
) >= cpu
.asregs
.msize
)
1621 fprintf (stderr
, "PC outside of available memory! (%x)\n", pc
);
1623 cpu
.asregs
.exception
= SIGSEGV
;
1627 ibuf
= rlat (pc
& 0xFFFFFFFC);
1632 while (!cpu
.asregs
.exception
);
1634 /* Hide away the things we've cached while executing. */
1636 cpu
.asregs
.insts
+= insts
; /* instructions done ... */
1637 cpu
.asregs
.cycles
+= insts
; /* and each takes a cycle */
1638 cpu
.asregs
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
1639 cpu
.asregs
.cycles
+= memops
* memcycles
; /* and memop cycle delays */
1641 signal (SIGINT
, sigsave
);
1646 sim_write (sd
, addr
, buffer
, size
)
1649 unsigned char * buffer
;
1655 memcpy (& cpu
.mem
[addr
], buffer
, size
);
1661 sim_read (sd
, addr
, buffer
, size
)
1664 unsigned char * buffer
;
1670 memcpy (buffer
, & cpu
.mem
[addr
], size
);
1677 sim_store_register (sd
, rn
, memory
, length
)
1680 unsigned char * memory
;
1685 if (rn
< NUM_MCORE_REGS
&& rn
>= 0)
1689 /* ival is in 'target' order, which we know to be big-endian.
1690 Let's convert it to natural order. */
1693 ival
= mcore_extract_unsigned_integer (memory
, 4);/* misalignment safe */
1694 cpu
.asints
[rn
] = ival
;
1704 sim_fetch_register (sd
, rn
, memory
, length
)
1707 unsigned char * memory
;
1712 if (rn
< NUM_MCORE_REGS
&& rn
>= 0)
1716 /* caller expects 'target order', which is big-endian. Convert
1717 * the native order we used [to speed up simulation] to the
1718 * byte order expected by the caller. */
1719 long ival
= cpu
.asints
[rn
];
1720 mcore_store_unsigned_integer (memory
, 4, ival
);/* misalignment-safe */
1736 sim_resume (sd
, 0, 0);
1744 sim_stop_reason (sd
, reason
, sigrc
)
1746 enum sim_stop
* reason
;
1749 if (cpu
.asregs
.exception
== SIGQUIT
)
1751 * reason
= sim_exited
;
1752 * sigrc
= cpu
.gr
[PARM1
];
1756 * reason
= sim_stopped
;
1757 * sigrc
= cpu
.asregs
.exception
;
1766 cpu
.asregs
.exception
= SIGINT
;
1772 sim_info (sd
, verbose
)
1776 #ifdef WATCHFUNCTIONS
1779 double virttime
= cpu
.asregs
.cycles
/ 36.0e6
;
1781 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n", cpu
.asregs
.insts
);
1782 callback
->printf_filtered (callback
, "# cycles %10d\n", cpu
.asregs
.cycles
);
1783 callback
->printf_filtered (callback
, "# pipeline stalls %10d\n", cpu
.asregs
.stalls
);
1784 callback
->printf_filtered (callback
, "# virtual time taken %10.4f\n", virttime
);
1786 #ifdef WATCHFUNCTIONS
1787 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",ENDWL
);
1791 for (w
= 1; w
<= ENDWL
; w
++)
1793 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
1794 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n", WLcnts
[w
],WLcyc
[w
]);
1797 callback
->printf_filtered (callback
, " maxcpc = %d, mincpc = %d, avecpc = %d\n",WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
1801 callback
->printf_filtered (callback
, "Total cycles for watched functions: %d\n",wcyc
);
1807 unsigned char sa_machtype
[2];
1808 unsigned char sa_magic
[2];
1809 unsigned char sa_tsize
[4];
1810 unsigned char sa_dsize
[4];
1811 unsigned char sa_bsize
[4];
1812 unsigned char sa_syms
[4];
1813 unsigned char sa_entry
[4];
1814 unsigned char sa_trelo
[4];
1815 unsigned char sa_drelo
[4];
1818 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
1819 #define SHORT(x) (((x)[0]<<8)|(x)[1])
1822 sim_open (kind
, cb
, abfd
, argv
)
1828 int osize
= sim_memory_size
;
1832 if (kind
== SIM_OPEN_STANDALONE
)
1835 /* Discard and reacquire memory -- start with a clean slate. */
1836 sim_size (1); /* small */
1837 sim_size (osize
); /* and back again */
1839 set_initial_gprs (); /* Reset the GPR registers. */
1841 /* Fudge our descriptor for now. */
1842 return (SIM_DESC
) 1;
1846 sim_close (sd
, quitting
)
1854 sim_load (sd
, prog
, abfd
, from_tty
)
1860 /* Do the right thing for ELF executables; this turns out to be
1861 just about the right thing for any object format that:
1862 - we crack using BFD routines
1863 - follows the traditional UNIX text/data/bss layout
1864 - calls the bss section ".bss". */
1866 extern bfd
* sim_load_file (); /* ??? Don't know where this should live. */
1872 handle
= bfd_openr (prog
, 0); /* could be "mcore" */
1876 printf("``%s'' could not be opened.\n", prog
);
1880 /* Makes sure that we have an object file, also cleans gets the
1881 section headers in place. */
1882 if (!bfd_check_format (handle
, bfd_object
))
1884 /* wasn't an object file */
1886 printf ("``%s'' is not appropriate object file.\n", prog
);
1890 /* Look for that bss section. */
1891 s_bss
= bfd_get_section_by_name (handle
, ".bss");
1895 printf("``%s'' has no bss section.\n", prog
);
1899 /* Appropriately paranoid would check that we have
1900 a traditional text/data/bss ordering within memory. */
1902 /* figure the end of the bss section */
1904 printf ("bss section at 0x%08x for 0x%08x bytes\n",
1905 (unsigned long) s_bss
->vma
, (unsigned long) s_bss
->_cooked_size
);
1907 heap_ptr
= (unsigned long) s_bss
->vma
+ (unsigned long) s_bss
->_cooked_size
;
1909 /* Clean up after ourselves. */
1912 /* XXX: do we need to free the s_bss and handle structures? */
1915 /* from sh -- dac */
1916 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
1917 sim_kind
== SIM_OPEN_DEBUG
,
1919 if (prog_bfd
== NULL
)
1923 bfd_close (prog_bfd
);
1929 sim_create_inferior (sd
, prog_bfd
, argv
, env
)
1931 struct _bfd
* prog_bfd
;
1940 unsigned long strings
;
1941 unsigned long pointers
;
1942 unsigned long hi_stack
;
1945 /* Set the initial register set. */
1948 set_initial_gprs ();
1951 hi_stack
= cpu
.asregs
.msize
- 4;
1952 cpu
.asregs
.pc
= bfd_get_start_address (prog_bfd
);
1954 /* Calculate the argument and environment strings. */
1960 l
= strlen (*avp
) + 1; /* include the null */
1961 s_length
+= (l
+ 3) & ~3; /* make it a 4 byte boundary */
1969 l
= strlen (*avp
) + 1; /* include the null */
1970 s_length
+= (l
+ 3) & ~ 3;/* make it a 4 byte boundary */
1974 /* Claim some memory for the pointers and strings. */
1975 pointers
= hi_stack
- sizeof(word
) * (nenv
+1+nargs
+1);
1976 pointers
&= ~3; /* must be 4-byte aligned */
1977 cpu
.gr
[0] = pointers
;
1979 strings
= cpu
.gr
[0] - s_length
;
1980 strings
&= ~3; /* want to make it 4-byte aligned */
1981 cpu
.gr
[0] = strings
;
1982 /* dac fix, the stack address must be 8-byte aligned! */
1983 cpu
.gr
[0] = cpu
.gr
[0] - cpu
.gr
[0] % 8;
1985 /* Loop through the arguments and fill them in. */
1986 cpu
.gr
[PARM1
] = nargs
;
1989 /* No strings to fill in. */
1994 cpu
.gr
[PARM2
] = pointers
;
1998 /* Save where we're putting it. */
1999 wlat (pointers
, strings
);
2001 /* Copy the string. */
2002 l
= strlen (* avp
) + 1;
2003 strcpy ((char *)(cpu
.mem
+ strings
), *avp
);
2005 /* Bump the pointers. */
2011 /* A null to finish the list. */
2016 /* Now do the environment pointers. */
2019 /* No strings to fill in. */
2024 cpu
.gr
[PARM3
] = pointers
;
2029 /* Save where we're putting it. */
2030 wlat (pointers
, strings
);
2032 /* Copy the string. */
2033 l
= strlen (* avp
) + 1;
2034 strcpy ((char *)(cpu
.mem
+ strings
), *avp
);
2036 /* Bump the pointers. */
2042 /* A null to finish the list. */
2058 sim_do_command (sd
, cmd
)
2062 /* Nothing there yet; it's all an error. */
2066 char ** simargv
= buildargv (cmd
);
2068 if (strcmp (simargv
[0], "watch") == 0)
2070 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
2072 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
2078 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
2079 WLstr
[ENDWL
] = strdup (simargv
[1]);
2080 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
2084 else if (strcmp (simargv
[0], "dumpmem") == 0)
2089 if (simargv
[1] == NULL
)
2090 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
2092 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
2094 dumpfile
= fopen (simargv
[1], "w");
2096 fwrite (p
, cpu
.asregs
.msize
-1, 1, dumpfile
);
2099 fprintf (stderr
, "done.\n");
2101 else if (strcmp (simargv
[0], "clearstats") == 0)
2103 cpu
.asregs
.cycles
= 0;
2104 cpu
.asregs
.insts
= 0;
2105 cpu
.asregs
.stalls
= 0;
2108 else if (strcmp (simargv
[0], "verbose") == 0)
2114 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
2120 fprintf (stderr
, "M.CORE sim commands: \n");
2121 fprintf (stderr
, " watch <funcname> <addr>\n");
2122 fprintf (stderr
, " dumpmem <filename>\n");
2123 fprintf (stderr
, " clearstats\n");
2124 fprintf (stderr
, " verbose\n");
2129 sim_set_callbacks (ptr
)
2130 host_callback
* ptr
;
This page took 0.090926 seconds and 4 git commands to generate.