]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/sh/interp.c
sim: nrun: use lbasename
[thirdparty/binutils-gdb.git] / sim / sh / interp.c
CommitLineData
86bc60eb 1/* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture.
c906108c
SS
2
3 Written by Steve Chamberlain of Cygnus Support.
4 sac@cygnus.com
5
6 This file is part of SH sim
7
8
9 THIS SOFTWARE IS NOT COPYRIGHTED
10
11 Cygnus offers the following for use in the public domain. Cygnus
12 makes no warranty with regard to the software or it's performance
13 and the user accepts the software "AS IS" with all faults.
14
15 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
16 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
19*/
20
21#include "config.h"
22
5fa71a1b 23#include <ctype.h>
22e041e2
MM
24#include <stdio.h>
25#include <errno.h>
c906108c
SS
26#include <signal.h>
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
6a8492b5
JR
30#ifdef HAVE_MMAP
31#include <sys/mman.h>
32# ifndef MAP_FAILED
33# define MAP_FAILED -1
34# endif
35# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
36# define MAP_ANONYMOUS MAP_ANON
37# endif
38#endif
c906108c 39
22e041e2
MM
40#ifdef HAVE_STRING_H
41#include <string.h>
42#else
43#ifdef HAVE_STRINGS_H
44#include <strings.h>
45#endif
46#endif
47
48#ifdef HAVE_STDLIB_H
49#include <stdlib.h>
50#endif
51
52#ifdef HAVE_SYS_STAT_H
53#include <sys/stat.h>
54#endif
5fa71a1b
MF
55#ifdef HAVE_TIME_H
56#include <time.h>
57#endif
58#ifdef HAVE_SYS_TIME_H
59#include <sys/time.h>
60#endif
61#ifndef _WIN32
62#include <utime.h>
63#include <sys/wait.h>
64#endif
22e041e2 65
c906108c 66#include "bfd.h"
3c25f8c7
AC
67#include "gdb/callback.h"
68#include "gdb/remote-sim.h"
2f14585c 69#include "gdb/sim-sh.h"
62454d3d
MF
70
71#include "sim-main.h"
72#include "sim-base.h"
73#include "sim-options.h"
c906108c
SS
74
75/* This file is local - if newlib changes, then so should this. */
76#include "syscall.h"
77
78#include <math.h>
79
80#ifdef _WIN32
81#include <float.h> /* Needed for _isnan() */
82#define isnan _isnan
83#endif
84
85#ifndef SIGBUS
86#define SIGBUS SIGSEGV
87#endif
88
89#ifndef SIGQUIT
90#define SIGQUIT SIGTERM
91#endif
92
93#ifndef SIGTRAP
94#define SIGTRAP 5
95#endif
96
62454d3d
MF
97/* TODO: Stop using these names. */
98#undef SEXT
99#undef SEXT32
63978407 100
62454d3d 101extern unsigned short sh_jump_table[], sh_dsp_table[0x1000], ppi_table[];
de0492b6 102
c906108c
SS
103#define O_RECOMPILE 85
104#define DEFINE_TABLE
105#define DISASSEMBLER_TABLE
106
7a292a7a
SS
107/* Define the rate at which the simulator should poll the host
108 for a quit. */
109#define POLL_QUIT_INTERVAL 0x60000
110
62454d3d 111/* TODO: Move into sim_cpu. */
c906108c
SS
112saved_state_type saved_state;
113
63978407 114struct loop_bounds { unsigned char *start, *end; };
c906108c
SS
115
116/* These variables are at file scope so that functions other than
117 sim_resume can use the fetch/store macros */
118
1ac72f06 119#define target_little_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
63978407
JR
120static int global_endianw, endianb;
121static int target_dsp;
0cb8d851 122#define host_little_endian (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
c906108c 123
63978407 124static int maskw = 0;
d1789ace 125static int maskl = 0;
c906108c 126
c906108c
SS
127/* Short hand definitions of the registers */
128
129#define SBIT(x) ((x)&sbit)
130#define R0 saved_state.asregs.regs[0]
131#define Rn saved_state.asregs.regs[n]
132#define Rm saved_state.asregs.regs[m]
87acb4a7
MS
133#define UR0 (unsigned int) (saved_state.asregs.regs[0])
134#define UR (unsigned int) R
135#define UR (unsigned int) R
c906108c 136#define SR0 saved_state.asregs.regs[0]
63978407
JR
137#define CREG(n) (saved_state.asregs.cregs.i[(n)])
138#define GBR saved_state.asregs.cregs.named.gbr
139#define VBR saved_state.asregs.cregs.named.vbr
86bc60eb 140#define DBR saved_state.asregs.cregs.named.dbr
ae0a84af
CV
141#define TBR saved_state.asregs.cregs.named.tbr
142#define IBCR saved_state.asregs.cregs.named.ibcr
143#define IBNR saved_state.asregs.cregs.named.ibnr
144#define BANKN (saved_state.asregs.cregs.named.ibnr & 0x1ff)
145#define ME ((saved_state.asregs.cregs.named.ibnr >> 14) & 0x3)
63978407
JR
146#define SSR saved_state.asregs.cregs.named.ssr
147#define SPC saved_state.asregs.cregs.named.spc
86bc60eb 148#define SGR saved_state.asregs.cregs.named.sgr
63978407
JR
149#define SREG(n) (saved_state.asregs.sregs.i[(n)])
150#define MACH saved_state.asregs.sregs.named.mach
151#define MACL saved_state.asregs.sregs.named.macl
152#define PR saved_state.asregs.sregs.named.pr
153#define FPUL saved_state.asregs.sregs.named.fpul
c906108c 154
63978407 155#define PC insn_ptr
c906108c
SS
156
157
158
63978407 159/* Alternate bank of registers r0-r7 */
c906108c
SS
160
161/* Note: code controling SR handles flips between BANK0 and BANK1 */
63978407
JR
162#define Rn_BANK(n) (saved_state.asregs.cregs.named.bank[(n)])
163#define SET_Rn_BANK(n, EXP) do { saved_state.asregs.cregs.named.bank[(n)] = (EXP); } while (0)
c906108c
SS
164
165
166/* Manipulate SR */
167
ae0a84af
CV
168#define SR_MASK_BO (1 << 14)
169#define SR_MASK_CS (1 << 13)
63978407
JR
170#define SR_MASK_DMY (1 << 11)
171#define SR_MASK_DMX (1 << 10)
c906108c
SS
172#define SR_MASK_M (1 << 9)
173#define SR_MASK_Q (1 << 8)
174#define SR_MASK_I (0xf << 4)
175#define SR_MASK_S (1 << 1)
176#define SR_MASK_T (1 << 0)
177
178#define SR_MASK_BL (1 << 28)
179#define SR_MASK_RB (1 << 29)
180#define SR_MASK_MD (1 << 30)
63978407
JR
181#define SR_MASK_RC 0x0fff0000
182#define SR_RC_INCREMENT -0x00010000
c906108c 183
ae0a84af
CV
184#define BO ((saved_state.asregs.cregs.named.sr & SR_MASK_BO) != 0)
185#define CS ((saved_state.asregs.cregs.named.sr & SR_MASK_CS) != 0)
63978407
JR
186#define M ((saved_state.asregs.cregs.named.sr & SR_MASK_M) != 0)
187#define Q ((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0)
188#define S ((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0)
189#define T ((saved_state.asregs.cregs.named.sr & SR_MASK_T) != 0)
86bc60eb 190#define LDST ((saved_state.asregs.cregs.named.ldst) != 0)
c906108c 191
63978407
JR
192#define SR_BL ((saved_state.asregs.cregs.named.sr & SR_MASK_BL) != 0)
193#define SR_RB ((saved_state.asregs.cregs.named.sr & SR_MASK_RB) != 0)
194#define SR_MD ((saved_state.asregs.cregs.named.sr & SR_MASK_MD) != 0)
195#define SR_DMY ((saved_state.asregs.cregs.named.sr & SR_MASK_DMY) != 0)
196#define SR_DMX ((saved_state.asregs.cregs.named.sr & SR_MASK_DMX) != 0)
197#define SR_RC ((saved_state.asregs.cregs.named.sr & SR_MASK_RC))
c906108c
SS
198
199/* Note: don't use this for privileged bits */
200#define SET_SR_BIT(EXP, BIT) \
201do { \
202 if ((EXP) & 1) \
63978407 203 saved_state.asregs.cregs.named.sr |= (BIT); \
c906108c 204 else \
63978407 205 saved_state.asregs.cregs.named.sr &= ~(BIT); \
c906108c
SS
206} while (0)
207
ae0a84af
CV
208#define SET_SR_BO(EXP) SET_SR_BIT ((EXP), SR_MASK_BO)
209#define SET_SR_CS(EXP) SET_SR_BIT ((EXP), SR_MASK_CS)
210#define SET_BANKN(EXP) \
211do { \
212 IBNR = (IBNR & 0xfe00) | (EXP & 0x1f); \
213} while (0)
214#define SET_ME(EXP) \
215do { \
216 IBNR = (IBNR & 0x3fff) | ((EXP & 0x3) << 14); \
217} while (0)
c906108c
SS
218#define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M)
219#define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q)
220#define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S)
221#define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T)
86bc60eb 222#define SET_LDST(EXP) (saved_state.asregs.cregs.named.ldst = ((EXP) != 0))
c906108c 223
63978407
JR
224/* stc currently relies on being able to read SR without modifications. */
225#define GET_SR() (saved_state.asregs.cregs.named.sr - 0)
226
c906108c 227#define SET_SR(x) set_sr (x)
c906108c 228
63978407
JR
229#define SET_RC(x) \
230 (saved_state.asregs.cregs.named.sr \
231 = saved_state.asregs.cregs.named.sr & 0xf000ffff | ((x) & 0xfff) << 16)
c906108c
SS
232
233/* Manipulate FPSCR */
234
7a292a7a
SS
235#define FPSCR_MASK_FR (1 << 21)
236#define FPSCR_MASK_SZ (1 << 20)
237#define FPSCR_MASK_PR (1 << 19)
238
87acb4a7
MS
239#define FPSCR_FR ((GET_FPSCR () & FPSCR_MASK_FR) != 0)
240#define FPSCR_SZ ((GET_FPSCR () & FPSCR_MASK_SZ) != 0)
241#define FPSCR_PR ((GET_FPSCR () & FPSCR_MASK_PR) != 0)
7a292a7a 242
de0492b6
AO
243/* Count the number of arguments in an argv. */
244static int
245count_argc (char **argv)
246{
247 int i;
248
249 if (! argv)
250 return -1;
251
252 for (i = 0; argv[i] != NULL; ++i)
253 continue;
254 return i;
255}
256
7a292a7a 257static void
5fa71a1b 258set_fpscr1 (int x)
7a292a7a 259{
63978407
JR
260 int old = saved_state.asregs.sregs.named.fpscr;
261 saved_state.asregs.sregs.named.fpscr = (x);
7a292a7a 262 /* swap the floating point register banks */
63978407
JR
263 if ((saved_state.asregs.sregs.named.fpscr ^ old) & FPSCR_MASK_FR
264 /* Ignore bit change if simulating sh-dsp. */
265 && ! target_dsp)
7a292a7a
SS
266 {
267 union fregs_u tmpf = saved_state.asregs.fregs[0];
268 saved_state.asregs.fregs[0] = saved_state.asregs.fregs[1];
269 saved_state.asregs.fregs[1] = tmpf;
270 }
271}
272
63978407
JR
273/* sts relies on being able to read fpscr directly. */
274#define GET_FPSCR() (saved_state.asregs.sregs.named.fpscr)
7a292a7a
SS
275#define SET_FPSCR(x) \
276do { \
277 set_fpscr1 (x); \
278} while (0)
c906108c 279
63978407 280#define DSR (saved_state.asregs.sregs.named.fpscr)
c906108c 281
63978407
JR
282#define RAISE_EXCEPTION(x) \
283 (saved_state.asregs.exception = x, saved_state.asregs.insn_end = 0)
7a292a7a 284
ae0a84af
CV
285#define RAISE_EXCEPTION_IF_IN_DELAY_SLOT() \
286 if (in_delay_slot) RAISE_EXCEPTION (SIGILL)
287
63978407 288/* This function exists mainly for the purpose of setting a breakpoint to
c906108c
SS
289 catch simulated bus errors when running the simulator under GDB. */
290
5fa71a1b
MF
291static void
292raise_exception (int x)
63978407 293{
87acb4a7 294 RAISE_EXCEPTION (x);
63978407
JR
295}
296
5fa71a1b
MF
297static void
298raise_buserror (void)
c906108c 299{
63978407 300 raise_exception (SIGBUS);
c906108c
SS
301}
302
63978407
JR
303#define PROCESS_SPECIAL_ADDRESS(addr, endian, ptr, bits_written, \
304 forbidden_addr_bits, data, retval) \
305do { \
306 if (addr & forbidden_addr_bits) \
307 { \
308 raise_buserror (); \
309 return retval; \
310 } \
311 else if ((addr & saved_state.asregs.xyram_select) \
312 == saved_state.asregs.xram_start) \
313 ptr = (void *) &saved_state.asregs.xmem_offset[addr ^ endian]; \
314 else if ((addr & saved_state.asregs.xyram_select) \
315 == saved_state.asregs.yram_start) \
316 ptr = (void *) &saved_state.asregs.ymem_offset[addr ^ endian]; \
317 else if ((unsigned) addr >> 24 == 0xf0 \
318 && bits_written == 32 && (data & 1) == 0) \
319 /* This invalidates (if not associative) or might invalidate \
320 (if associative) an instruction cache line. This is used for \
321 trampolines. Since we don't simulate the cache, this is a no-op \
322 as far as the simulator is concerned. */ \
323 return retval; \
324 else \
325 { \
326 if (bits_written == 8 && addr > 0x5000000) \
327 IOMEM (addr, 1, data); \
328 /* We can't do anything useful with the other stuff, so fail. */ \
329 raise_buserror (); \
330 return retval; \
331 } \
332} while (0)
333
c906108c
SS
334/* FIXME: sim_resume should be renamed to sim_engine_run. sim_resume
335 being implemented by ../common/sim_resume.c and the below should
336 make a call to sim_engine_halt */
337
63978407
JR
338#define BUSERROR(addr, mask) ((addr) & (mask))
339
340#define WRITE_BUSERROR(addr, mask, data, addr_func) \
341 do \
7a292a7a 342 { \
63978407
JR
343 if (addr & mask) \
344 { \
345 addr_func (addr, data); \
346 return; \
347 } \
348 } \
349 while (0)
350
351#define READ_BUSERROR(addr, mask, addr_func) \
352 do \
353 { \
354 if (addr & mask) \
355 return addr_func (addr); \
356 } \
357 while (0)
c906108c
SS
358
359/* Define this to enable register lifetime checking.
360 The compiler generates "add #0,rn" insns to mark registers as invalid,
361 the simulator uses this info to call fail if it finds a ref to an invalid
362 register before a def
363
364 #define PARANOID
365*/
366
367#ifdef PARANOID
368int valid[16];
87acb4a7 369#define CREF(x) if (!valid[x]) fail ();
c906108c
SS
370#define CDEF(x) valid[x] = 1;
371#define UNDEF(x) valid[x] = 0;
372#else
373#define CREF(x)
374#define CDEF(x)
375#define UNDEF(x)
376#endif
377
6cc98856 378static void parse_and_set_memory_size (SIM_DESC sd, const char *str);
bdca5ee4
TT
379static int IOMEM (int addr, int write, int value);
380static struct loop_bounds get_loop_bounds (int, int, unsigned char *,
381 unsigned char *, int, int);
382static void process_wlat_addr (int, int);
383static void process_wwat_addr (int, int);
384static void process_wbat_addr (int, int);
385static int process_rlat_addr (int);
386static int process_rwat_addr (int);
387static int process_rbat_addr (int);
c906108c 388
c906108c
SS
389/* Floating point registers */
390
7a292a7a
SS
391#define DR(n) (get_dr (n))
392static double
5fa71a1b 393get_dr (int n)
7a292a7a
SS
394{
395 n = (n & ~1);
396 if (host_little_endian)
397 {
398 union
399 {
400 int i[2];
401 double d;
402 } dr;
403 dr.i[1] = saved_state.asregs.fregs[0].i[n + 0];
404 dr.i[0] = saved_state.asregs.fregs[0].i[n + 1];
405 return dr.d;
406 }
407 else
408 return (saved_state.asregs.fregs[0].d[n >> 1]);
409}
410
411#define SET_DR(n, EXP) set_dr ((n), (EXP))
412static void
5fa71a1b 413set_dr (int n, double exp)
7a292a7a
SS
414{
415 n = (n & ~1);
416 if (host_little_endian)
417 {
418 union
419 {
420 int i[2];
421 double d;
422 } dr;
423 dr.d = exp;
424 saved_state.asregs.fregs[0].i[n + 0] = dr.i[1];
425 saved_state.asregs.fregs[0].i[n + 1] = dr.i[0];
426 }
427 else
428 saved_state.asregs.fregs[0].d[n >> 1] = exp;
429}
430
431#define SET_FI(n,EXP) (saved_state.asregs.fregs[0].i[(n)] = (EXP))
432#define FI(n) (saved_state.asregs.fregs[0].i[(n)])
c906108c 433
7a292a7a
SS
434#define FR(n) (saved_state.asregs.fregs[0].f[(n)])
435#define SET_FR(n,EXP) (saved_state.asregs.fregs[0].f[(n)] = (EXP))
c906108c 436
7a292a7a
SS
437#define XD_TO_XF(n) ((((n) & 1) << 5) | ((n) & 0x1e))
438#define XF(n) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f])
439#define SET_XF(n,EXP) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f] = (EXP))
440
63978407
JR
441#define RS saved_state.asregs.cregs.named.rs
442#define RE saved_state.asregs.cregs.named.re
443#define MOD (saved_state.asregs.cregs.named.mod)
444#define SET_MOD(i) \
445(MOD = (i), \
446 MOD_ME = (unsigned) MOD >> 16 | (SR_DMY ? ~0xffff : (SR_DMX ? 0 : 0x10000)), \
447 MOD_DELTA = (MOD & 0xffff) - ((unsigned) MOD >> 16))
448
449#define DSP_R(n) saved_state.asregs.sregs.i[(n)]
450#define DSP_GRD(n) DSP_R ((n) + 8)
451#define GET_DSP_GRD(n) ((n | 2) == 7 ? SEXT (DSP_GRD (n)) : SIGN32 (DSP_R (n)))
452#define A1 DSP_R (5)
453#define A0 DSP_R (7)
454#define X0 DSP_R (8)
455#define X1 DSP_R (9)
456#define Y0 DSP_R (10)
457#define Y1 DSP_R (11)
458#define M0 DSP_R (12)
459#define A1G DSP_R (13)
460#define M1 DSP_R (14)
461#define A0G DSP_R (15)
462/* DSP_R (16) / DSP_GRD (16) are used as a fake destination for pcmp. */
463#define MOD_ME DSP_GRD (17)
464#define MOD_DELTA DSP_GRD (18)
7a292a7a
SS
465
466#define FP_OP(n, OP, m) \
467{ \
468 if (FPSCR_PR) \
469 { \
470 if (((n) & 1) || ((m) & 1)) \
63978407 471 RAISE_EXCEPTION (SIGILL); \
7a292a7a 472 else \
87acb4a7 473 SET_DR (n, (DR (n) OP DR (m))); \
7a292a7a
SS
474 } \
475 else \
87acb4a7 476 SET_FR (n, (FR (n) OP FR (m))); \
7a292a7a
SS
477} while (0)
478
479#define FP_UNARY(n, OP) \
480{ \
481 if (FPSCR_PR) \
482 { \
483 if ((n) & 1) \
63978407 484 RAISE_EXCEPTION (SIGILL); \
7a292a7a 485 else \
87acb4a7 486 SET_DR (n, (OP (DR (n)))); \
7a292a7a
SS
487 } \
488 else \
87acb4a7 489 SET_FR (n, (OP (FR (n)))); \
7a292a7a
SS
490} while (0)
491
492#define FP_CMP(n, OP, m) \
493{ \
494 if (FPSCR_PR) \
495 { \
496 if (((n) & 1) || ((m) & 1)) \
63978407 497 RAISE_EXCEPTION (SIGILL); \
7a292a7a 498 else \
87acb4a7 499 SET_SR_T (DR (n) OP DR (m)); \
7a292a7a
SS
500 } \
501 else \
87acb4a7 502 SET_SR_T (FR (n) OP FR (m)); \
7a292a7a 503} while (0)
c906108c 504
63978407 505static void
5fa71a1b 506set_sr (int new_sr)
c906108c 507{
63978407
JR
508 /* do we need to swap banks */
509 int old_gpr = SR_MD && SR_RB;
510 int new_gpr = (new_sr & SR_MASK_MD) && (new_sr & SR_MASK_RB);
511 if (old_gpr != new_gpr)
512 {
513 int i, tmp;
514 for (i = 0; i < 8; i++)
515 {
516 tmp = saved_state.asregs.cregs.named.bank[i];
517 saved_state.asregs.cregs.named.bank[i] = saved_state.asregs.regs[i];
518 saved_state.asregs.regs[i] = tmp;
519 }
520 }
521 saved_state.asregs.cregs.named.sr = new_sr;
522 SET_MOD (MOD);
c906108c
SS
523}
524
5fa71a1b
MF
525static INLINE void
526wlat_fast (unsigned char *memory, int x, int value, int maskl)
c906108c
SS
527{
528 int v = value;
87acb4a7 529 unsigned int *p = (unsigned int *) (memory + x);
63978407
JR
530 WRITE_BUSERROR (x, maskl, v, process_wlat_addr);
531 *p = v;
c906108c
SS
532}
533
5fa71a1b
MF
534static INLINE void
535wwat_fast (unsigned char *memory, int x, int value, int maskw, int endianw)
c906108c
SS
536{
537 int v = value;
87acb4a7 538 unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
63978407
JR
539 WRITE_BUSERROR (x, maskw, v, process_wwat_addr);
540 *p = v;
c906108c
SS
541}
542
5fa71a1b
MF
543static INLINE void
544wbat_fast (unsigned char *memory, int x, int value, int maskb)
c906108c 545{
63978407
JR
546 unsigned char *p = memory + (x ^ endianb);
547 WRITE_BUSERROR (x, maskb, value, process_wbat_addr);
c906108c 548
c906108c
SS
549 p[0] = value;
550}
551
552/* Read functions */
553
5fa71a1b
MF
554static INLINE int
555rlat_fast (unsigned char *memory, int x, int maskl)
c906108c 556{
87acb4a7 557 unsigned int *p = (unsigned int *) (memory + x);
63978407 558 READ_BUSERROR (x, maskl, process_rlat_addr);
c906108c 559
63978407 560 return *p;
c906108c
SS
561}
562
5fa71a1b
MF
563static INLINE int
564rwat_fast (unsigned char *memory, int x, int maskw, int endianw)
c906108c 565{
87acb4a7 566 unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
63978407 567 READ_BUSERROR (x, maskw, process_rwat_addr);
c906108c 568
63978407 569 return *p;
c906108c
SS
570}
571
5fa71a1b
MF
572static INLINE int
573riat_fast (unsigned char *insn_ptr, int endianw)
c906108c 574{
87acb4a7 575 unsigned short *p = (unsigned short *) ((size_t) insn_ptr ^ endianw);
c906108c 576
63978407 577 return *p;
c906108c
SS
578}
579
5fa71a1b
MF
580static INLINE int
581rbat_fast (unsigned char *memory, int x, int maskb)
c906108c 582{
63978407
JR
583 unsigned char *p = memory + (x ^ endianb);
584 READ_BUSERROR (x, maskb, process_rbat_addr);
c906108c 585
63978407 586 return *p;
c906108c
SS
587}
588
63978407
JR
589#define RWAT(x) (rwat_fast (memory, x, maskw, endianw))
590#define RLAT(x) (rlat_fast (memory, x, maskl))
591#define RBAT(x) (rbat_fast (memory, x, maskb))
592#define RIAT(p) (riat_fast ((p), endianw))
593#define WWAT(x,v) (wwat_fast (memory, x, v, maskw, endianw))
594#define WLAT(x,v) (wlat_fast (memory, x, v, maskl))
595#define WBAT(x,v) (wbat_fast (memory, x, v, maskb))
c906108c 596
87acb4a7
MS
597#define RUWAT(x) (RWAT (x) & 0xffff)
598#define RSWAT(x) ((short) (RWAT (x)))
599#define RSLAT(x) ((long) (RLAT (x)))
600#define RSBAT(x) (SEXT (RBAT (x)))
c906108c 601
63978407 602#define RDAT(x, n) (do_rdat (memory, (x), (n), (maskl)))
7a292a7a 603static int
5fa71a1b 604do_rdat (unsigned char *memory, int x, int n, int maskl)
7a292a7a
SS
605{
606 int f0;
607 int f1;
608 int i = (n & 1);
609 int j = (n & ~1);
63978407
JR
610 f0 = rlat_fast (memory, x + 0, maskl);
611 f1 = rlat_fast (memory, x + 4, maskl);
7a292a7a
SS
612 saved_state.asregs.fregs[i].i[(j + 0)] = f0;
613 saved_state.asregs.fregs[i].i[(j + 1)] = f1;
614 return 0;
615}
c906108c 616
63978407 617#define WDAT(x, n) (do_wdat (memory, (x), (n), (maskl)))
7a292a7a 618static int
5fa71a1b 619do_wdat (unsigned char *memory, int x, int n, int maskl)
7a292a7a
SS
620{
621 int f0;
622 int f1;
623 int i = (n & 1);
624 int j = (n & ~1);
625 f0 = saved_state.asregs.fregs[i].i[(j + 0)];
626 f1 = saved_state.asregs.fregs[i].i[(j + 1)];
63978407
JR
627 wlat_fast (memory, (x + 0), f0, maskl);
628 wlat_fast (memory, (x + 4), f1, maskl);
7a292a7a
SS
629 return 0;
630}
c906108c 631
63978407 632static void
5fa71a1b 633process_wlat_addr (int addr, int value)
63978407
JR
634{
635 unsigned int *ptr;
636
637 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 32, 3, value, );
638 *ptr = value;
639}
640
641static void
5fa71a1b 642process_wwat_addr (int addr, int value)
63978407
JR
643{
644 unsigned short *ptr;
645
646 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 16, 1, value, );
647 *ptr = value;
648}
649
650static void
5fa71a1b 651process_wbat_addr (int addr, int value)
63978407
JR
652{
653 unsigned char *ptr;
654
655 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 8, 0, value, );
656 *ptr = value;
657}
c906108c 658
63978407 659static int
5fa71a1b 660process_rlat_addr (int addr)
63978407
JR
661{
662 unsigned char *ptr;
663
664 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -32, 3, -1, 0);
665 return *ptr;
666}
667
668static int
5fa71a1b 669process_rwat_addr (int addr)
63978407
JR
670{
671 unsigned char *ptr;
672
673 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -16, 1, -1, 0);
674 return *ptr;
675}
676
677static int
5fa71a1b 678process_rbat_addr (int addr)
63978407
JR
679{
680 unsigned char *ptr;
681
682 PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -8, 0, -1, 0);
683 return *ptr;
684}
c906108c
SS
685
686#define SEXT(x) (((x & 0xff) ^ (~0x7f))+0x80)
687#define SEXT12(x) (((x & 0xfff) ^ 0x800) - 0x800)
87acb4a7 688#define SEXTW(y) ((int) ((short) y))
63978407 689#if 0
87acb4a7 690#define SEXT32(x) ((int) ((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1)
63978407 691#else
87acb4a7 692#define SEXT32(x) ((int) (x))
63978407
JR
693#endif
694#define SIGN32(x) (SEXT32 (x) >> 31)
695
696/* convert pointer from target to host value. */
697#define PT2H(x) ((x) + memory)
698/* convert pointer from host to target value. */
699#define PH2T(x) ((x) - memory)
700
701#define SKIP_INSN(p) ((p) += ((RIAT (p) & 0xfc00) == 0xf800 ? 4 : 2))
c906108c 702
63978407 703#define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip);
c906108c 704
ae0a84af
CV
705static int in_delay_slot = 0;
706#define Delay_Slot(TEMPPC) iword = RIAT (TEMPPC); in_delay_slot = 1; goto top;
63978407
JR
707
708#define CHECK_INSN_PTR(p) \
709do { \
710 if (saved_state.asregs.exception || PH2T (p) & maskw) \
711 saved_state.asregs.insn_end = 0; \
712 else if (p < loop.end) \
713 saved_state.asregs.insn_end = loop.end; \
714 else \
715 saved_state.asregs.insn_end = mem_end; \
716} while (0)
717
718#ifdef ACE_FAST
719
720#define MA(n)
721#define L(x)
722#define TL(x)
723#define TB(x)
724
725#else
726
727#define MA(n) \
f95586a4 728 do { memstalls += ((((long) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
c906108c
SS
729
730#define L(x) thislock = x;
731#define TL(x) if ((x) == prevlock) stalls++;
87acb4a7 732#define TB(x,y) if ((x) == prevlock || (y) == prevlock) stalls++;
c906108c 733
63978407
JR
734#endif
735
72a37d8d 736#if defined(__GO32__)
c906108c
SS
737int sim_memory_size = 19;
738#else
739int sim_memory_size = 24;
740#endif
741
742static int sim_profile_size = 17;
743static int nsamples;
744
745#undef TB
746#define TB(x,y)
747
748#define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */
749#define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */
750#define SCR1 (0x05FFFECA) /* Channel 1 serial control register */
751#define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */
752#define SSR1 (0x05FFFECC) /* Channel 1 serial status register */
753#define RDR1 (0x05FFFECD) /* Channel 1 receive data register */
754
755#define SCI_RDRF 0x40 /* Recieve data register full */
756#define SCI_TDRE 0x80 /* Transmit data register empty */
757
758static int
5fa71a1b 759IOMEM (int addr, int write, int value)
c906108c
SS
760{
761 if (write)
762 {
763 switch (addr)
764 {
765 case TDR1:
766 if (value != '\r')
767 {
768 putchar (value);
769 fflush (stdout);
770 }
771 break;
772 }
773 }
774 else
775 {
776 switch (addr)
777 {
778 case RDR1:
779 return getchar ();
780 }
781 }
782 return 0;
783}
784
785static int
5fa71a1b 786get_now (void)
c906108c
SS
787{
788 return time ((long *) 0);
789}
790
791static int
5fa71a1b 792now_persec (void)
c906108c
SS
793{
794 return 1;
795}
796
797static FILE *profile_file;
798
5fa71a1b
MF
799static INLINE unsigned
800swap (unsigned n)
c906108c 801{
63978407
JR
802 if (endianb)
803 n = (n << 24 | (n & 0xff00) << 8
804 | (n & 0xff0000) >> 8 | (n & 0xff000000) >> 24);
805 return n;
c906108c
SS
806}
807
5fa71a1b
MF
808static INLINE unsigned short
809swap16 (unsigned short n)
c906108c 810{
63978407
JR
811 if (endianb)
812 n = n << 8 | (n & 0xff00) >> 8;
813 return n;
c906108c
SS
814}
815
816static void
5fa71a1b 817swapout (int n)
c906108c
SS
818{
819 if (profile_file)
820 {
63978407
JR
821 union { char b[4]; int n; } u;
822 u.n = swap (n);
823 fwrite (u.b, 4, 1, profile_file);
c906108c
SS
824 }
825}
826
827static void
5fa71a1b 828swapout16 (int n)
c906108c 829{
63978407
JR
830 union { char b[4]; int n; } u;
831 u.n = swap16 (n);
832 fwrite (u.b, 2, 1, profile_file);
c906108c
SS
833}
834
835/* Turn a pointer in a register into a pointer into real memory. */
836
837static char *
5fa71a1b 838ptr (int x)
c906108c
SS
839{
840 return (char *) (x + saved_state.asregs.memory);
841}
842
63bee803
JR
843/* STR points to a zero-terminated string in target byte order. Return
844 the number of bytes that need to be converted to host byte order in order
845 to use this string as a zero-terminated string on the host.
846 (Not counting the rounding up needed to operate on entire words.) */
63978407 847static int
5fa71a1b 848strswaplen (int str)
63978407
JR
849{
850 unsigned char *memory = saved_state.asregs.memory;
851 int start, end;
852 int endian = endianb;
853
854 if (! endian)
855 return 0;
856 end = str;
857 for (end = str; memory[end ^ endian]; end++) ;
63bee803 858 return end - str + 1;
63978407
JR
859}
860
861static void
5fa71a1b 862strnswap (int str, int len)
63978407
JR
863{
864 int *start, *end;
865
866 if (! endianb || ! len)
867 return;
868 start = (int *) ptr (str & ~3);
869 end = (int *) ptr (str + len);
870 do
871 {
872 int old = *start;
873 *start = (old << 24 | (old & 0xff00) << 8
874 | (old & 0xff0000) >> 8 | (old & 0xff000000) >> 24);
875 start++;
876 }
877 while (start < end);
878}
879
fd8f4948
JR
880/* Simulate a monitor trap, put the result into r0 and errno into r1
881 return offset by which to adjust pc. */
c906108c 882
fd8f4948 883static int
6cc98856
MF
884trap (SIM_DESC sd, int i, int *regs, unsigned char *insn_ptr,
885 unsigned char *memory, int maskl, int maskw, int endianw)
c906108c 886{
6cc98856
MF
887 host_callback *callback = STATE_CALLBACK (sd);
888 char **prog_argv = STATE_PROG_ARGV (sd);
889
c906108c
SS
890 switch (i)
891 {
892 case 1:
893 printf ("%c", regs[0]);
894 break;
895 case 2:
63978407 896 raise_exception (SIGQUIT);
c906108c
SS
897 break;
898 case 3: /* FIXME: for backwards compat, should be removed */
fd8f4948
JR
899 case 33:
900 {
901 unsigned int countp = * (unsigned int *) (insn_ptr + 4);
902
903 WLAT (countp, RLAT (countp) + 1);
904 return 6;
905 }
c906108c
SS
906 case 34:
907 {
908 extern int errno;
909 int perrno = errno;
910 errno = 0;
911
912 switch (regs[4])
913 {
914
915#if !defined(__GO32__) && !defined(_WIN32)
916 case SYS_fork:
917 regs[0] = fork ();
918 break;
63978407
JR
919/* This would work only if endianness matched between host and target.
920 Besides, it's quite dangerous. */
921#if 0
c906108c 922 case SYS_execve:
87acb4a7
MS
923 regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]),
924 (char **) ptr (regs[7]));
c906108c
SS
925 break;
926 case SYS_execv:
87acb4a7 927 regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), 0);
c906108c 928 break;
63978407 929#endif
c906108c
SS
930 case SYS_pipe:
931 {
63978407
JR
932 regs[0] = (BUSERROR (regs[5], maskl)
933 ? -EINVAL
934 : pipe ((int *) ptr (regs[5])));
c906108c
SS
935 }
936 break;
937
938 case SYS_wait:
5fa71a1b 939 regs[0] = wait ((int *) ptr (regs[5]));
c906108c 940 break;
63978407 941#endif /* !defined(__GO32__) && !defined(_WIN32) */
c906108c
SS
942
943 case SYS_read:
63978407
JR
944 strnswap (regs[6], regs[7]);
945 regs[0]
946 = callback->read (callback, regs[5], ptr (regs[6]), regs[7]);
947 strnswap (regs[6], regs[7]);
c906108c
SS
948 break;
949 case SYS_write:
63978407 950 strnswap (regs[6], regs[7]);
c906108c 951 if (regs[5] == 1)
87acb4a7
MS
952 regs[0] = (int) callback->write_stdout (callback,
953 ptr (regs[6]), regs[7]);
c906108c 954 else
87acb4a7
MS
955 regs[0] = (int) callback->write (callback, regs[5],
956 ptr (regs[6]), regs[7]);
63978407 957 strnswap (regs[6], regs[7]);
c906108c
SS
958 break;
959 case SYS_lseek:
960 regs[0] = callback->lseek (callback,regs[5], regs[6], regs[7]);
961 break;
962 case SYS_close:
963 regs[0] = callback->close (callback,regs[5]);
964 break;
965 case SYS_open:
63978407
JR
966 {
967 int len = strswaplen (regs[5]);
968 strnswap (regs[5], len);
87acb4a7 969 regs[0] = callback->open (callback, ptr (regs[5]), regs[6]);
63978407
JR
970 strnswap (regs[5], len);
971 break;
972 }
c906108c
SS
973 case SYS_exit:
974 /* EXIT - caller can look in r5 to work out the reason */
63978407 975 raise_exception (SIGQUIT);
c906108c
SS
976 regs[0] = regs[5];
977 break;
978
979 case SYS_stat: /* added at hmsi */
980 /* stat system call */
981 {
982 struct stat host_stat;
63978407
JR
983 int buf;
984 int len = strswaplen (regs[5]);
c906108c 985
63978407 986 strnswap (regs[5], len);
c906108c 987 regs[0] = stat (ptr (regs[5]), &host_stat);
63978407 988 strnswap (regs[5], len);
c906108c 989
63978407 990 buf = regs[6];
c906108c
SS
991
992 WWAT (buf, host_stat.st_dev);
993 buf += 2;
994 WWAT (buf, host_stat.st_ino);
995 buf += 2;
996 WLAT (buf, host_stat.st_mode);
997 buf += 4;
998 WWAT (buf, host_stat.st_nlink);
999 buf += 2;
1000 WWAT (buf, host_stat.st_uid);
1001 buf += 2;
1002 WWAT (buf, host_stat.st_gid);
1003 buf += 2;
1004 WWAT (buf, host_stat.st_rdev);
1005 buf += 2;
1006 WLAT (buf, host_stat.st_size);
1007 buf += 4;
1008 WLAT (buf, host_stat.st_atime);
1009 buf += 4;
1010 WLAT (buf, 0);
1011 buf += 4;
1012 WLAT (buf, host_stat.st_mtime);
1013 buf += 4;
1014 WLAT (buf, 0);
1015 buf += 4;
1016 WLAT (buf, host_stat.st_ctime);
1017 buf += 4;
1018 WLAT (buf, 0);
1019 buf += 4;
1020 WLAT (buf, 0);
1021 buf += 4;
1022 WLAT (buf, 0);
1023 buf += 4;
1024 }
1025 break;
1026
1027#ifndef _WIN32
1028 case SYS_chown:
63978407
JR
1029 {
1030 int len = strswaplen (regs[5]);
1031
1032 strnswap (regs[5], len);
1033 regs[0] = chown (ptr (regs[5]), regs[6], regs[7]);
1034 strnswap (regs[5], len);
1035 break;
1036 }
c906108c
SS
1037#endif /* _WIN32 */
1038 case SYS_chmod:
63978407
JR
1039 {
1040 int len = strswaplen (regs[5]);
1041
1042 strnswap (regs[5], len);
1043 regs[0] = chmod (ptr (regs[5]), regs[6]);
1044 strnswap (regs[5], len);
1045 break;
1046 }
c906108c 1047 case SYS_utime:
63978407
JR
1048 {
1049 /* Cast the second argument to void *, to avoid type mismatch
1050 if a prototype is present. */
1051 int len = strswaplen (regs[5]);
1052
1053 strnswap (regs[5], len);
1054 regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6]));
1055 strnswap (regs[5], len);
1056 break;
1057 }
de0492b6
AO
1058 case SYS_argc:
1059 regs[0] = count_argc (prog_argv);
1060 break;
1061 case SYS_argnlen:
1062 if (regs[5] < count_argc (prog_argv))
1063 regs[0] = strlen (prog_argv[regs[5]]);
1064 else
1065 regs[0] = -1;
1066 break;
1067 case SYS_argn:
1068 if (regs[5] < count_argc (prog_argv))
1069 {
1070 /* Include the termination byte. */
1071 int i = strlen (prog_argv[regs[5]]) + 1;
5fa71a1b 1072 regs[0] = sim_write (0, regs[6], (void *) prog_argv[regs[5]], i);
de0492b6
AO
1073 }
1074 else
1075 regs[0] = -1;
1076 break;
55406459
AO
1077 case SYS_time:
1078 regs[0] = get_now ();
1079 break;
8822d001
JR
1080 case SYS_ftruncate:
1081 regs[0] = callback->ftruncate (callback, regs[5], regs[6]);
1082 break;
1083 case SYS_truncate:
1084 {
1085 int len = strswaplen (regs[5]);
1086 strnswap (regs[5], len);
1087 regs[0] = callback->truncate (callback, ptr (regs[5]), regs[6]);
1088 strnswap (regs[5], len);
1089 break;
1090 }
c906108c 1091 default:
de0492b6
AO
1092 regs[0] = -1;
1093 break;
c906108c
SS
1094 }
1095 regs[1] = callback->get_errno (callback);
1096 errno = perrno;
1097 }
1098 break;
1099
ae0a84af
CV
1100 case 13: /* Set IBNR */
1101 IBNR = regs[0] & 0xffff;
1102 break;
1103 case 14: /* Set IBCR */
1104 IBCR = regs[0] & 0xffff;
1105 break;
c906108c
SS
1106 case 0xc3:
1107 case 255:
63978407 1108 raise_exception (SIGTRAP);
fd8f4948
JR
1109 if (i == 0xc3)
1110 return -2;
c906108c
SS
1111 break;
1112 }
fd8f4948 1113 return 0;
c906108c
SS
1114}
1115
5fa71a1b
MF
1116static void
1117div1 (int *R, int iRn2, int iRn1/*, int T*/)
c906108c
SS
1118{
1119 unsigned long tmp0;
1120 unsigned char old_q, tmp1;
1121
1122 old_q = Q;
1123 SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0));
1124 R[iRn1] <<= 1;
1125 R[iRn1] |= (unsigned long) T;
1126
1127 switch (old_q)
1128 {
1129 case 0:
1130 switch (M)
1131 {
1132 case 0:
1133 tmp0 = R[iRn1];
1134 R[iRn1] -= R[iRn2];
1135 tmp1 = (R[iRn1] > tmp0);
1136 switch (Q)
1137 {
1138 case 0:
1139 SET_SR_Q (tmp1);
1140 break;
1141 case 1:
1142 SET_SR_Q ((unsigned char) (tmp1 == 0));
1143 break;
1144 }
1145 break;
1146 case 1:
1147 tmp0 = R[iRn1];
1148 R[iRn1] += R[iRn2];
1149 tmp1 = (R[iRn1] < tmp0);
1150 switch (Q)
1151 {
1152 case 0:
1153 SET_SR_Q ((unsigned char) (tmp1 == 0));
1154 break;
1155 case 1:
1156 SET_SR_Q (tmp1);
1157 break;
1158 }
1159 break;
1160 }
1161 break;
1162 case 1:
1163 switch (M)
1164 {
1165 case 0:
1166 tmp0 = R[iRn1];
1167 R[iRn1] += R[iRn2];
1168 tmp1 = (R[iRn1] < tmp0);
1169 switch (Q)
1170 {
1171 case 0:
1172 SET_SR_Q (tmp1);
1173 break;
1174 case 1:
1175 SET_SR_Q ((unsigned char) (tmp1 == 0));
1176 break;
1177 }
1178 break;
1179 case 1:
1180 tmp0 = R[iRn1];
1181 R[iRn1] -= R[iRn2];
1182 tmp1 = (R[iRn1] > tmp0);
1183 switch (Q)
1184 {
1185 case 0:
1186 SET_SR_Q ((unsigned char) (tmp1 == 0));
1187 break;
1188 case 1:
1189 SET_SR_Q (tmp1);
1190 break;
1191 }
1192 break;
1193 }
1194 break;
1195 }
1196 /*T = (Q == M);*/
1197 SET_SR_T (Q == M);
1198 /*return T;*/
1199}
1200
1201static void
5fa71a1b 1202dmul (int sign, unsigned int rm, unsigned int rn)
c906108c
SS
1203{
1204 unsigned long RnL, RnH;
1205 unsigned long RmL, RmH;
1206 unsigned long temp0, temp1, temp2, temp3;
1207 unsigned long Res2, Res1, Res0;
1208
1209 RnL = rn & 0xffff;
1210 RnH = (rn >> 16) & 0xffff;
1211 RmL = rm & 0xffff;
1212 RmH = (rm >> 16) & 0xffff;
1213 temp0 = RmL * RnL;
1214 temp1 = RmH * RnL;
1215 temp2 = RmL * RnH;
1216 temp3 = RmH * RnH;
1217 Res2 = 0;
1218 Res1 = temp1 + temp2;
1219 if (Res1 < temp1)
1220 Res2 += 0x00010000;
1221 temp1 = (Res1 << 16) & 0xffff0000;
1222 Res0 = temp0 + temp1;
1223 if (Res0 < temp0)
1224 Res2 += 1;
1225 Res2 += ((Res1 >> 16) & 0xffff) + temp3;
1226
1227 if (sign)
1228 {
1229 if (rn & 0x80000000)
1230 Res2 -= rm;
1231 if (rm & 0x80000000)
1232 Res2 -= rn;
1233 }
1234
1235 MACH = Res2;
1236 MACL = Res0;
1237}
1238
1239static void
5fa71a1b 1240macw (int *regs, unsigned char *memory, int n, int m, int endianw)
c906108c 1241{
c906108c
SS
1242 long tempm, tempn;
1243 long prod, macl, sum;
1244
87acb4a7
MS
1245 tempm=RSWAT (regs[m]); regs[m]+=2;
1246 tempn=RSWAT (regs[n]); regs[n]+=2;
c906108c
SS
1247
1248 macl = MACL;
87acb4a7 1249 prod = (long) (short) tempm * (long) (short) tempn;
c906108c
SS
1250 sum = prod + macl;
1251 if (S)
1252 {
1253 if ((~(prod ^ macl) & (sum ^ prod)) < 0)
1254 {
1255 /* MACH's lsb is a sticky overflow bit. */
1256 MACH |= 1;
1257 /* Store the smallest negative number in MACL if prod is
1258 negative, and the largest positive number otherwise. */
1259 sum = 0x7fffffff + (prod < 0);
1260 }
1261 }
1262 else
1263 {
1264 long mach;
1265 /* Add to MACH the sign extended product, and carry from low sum. */
1266 mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod);
1267 /* Sign extend at 10:th bit in MACH. */
1268 MACH = (mach & 0x1ff) | -(mach & 0x200);
1269 }
1270 MACL = sum;
1271}
1272
d1789ace 1273static void
5fa71a1b 1274macl (int *regs, unsigned char *memory, int n, int m)
d1789ace
MS
1275{
1276 long tempm, tempn;
f3876f69
AS
1277 long macl, mach;
1278 long long ans;
1279 long long mac64;
d1789ace 1280
87acb4a7 1281 tempm = RSLAT (regs[m]);
d1789ace
MS
1282 regs[m] += 4;
1283
87acb4a7 1284 tempn = RSLAT (regs[n]);
d1789ace
MS
1285 regs[n] += 4;
1286
1287 mach = MACH;
1288 macl = MACL;
1289
f3876f69
AS
1290 mac64 = ((long long) macl & 0xffffffff) |
1291 ((long long) mach & 0xffffffff) << 32;
d1789ace 1292
87acb4a7 1293 ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */
d1789ace 1294
f3876f69 1295 mac64 += ans; /* Accumulate 64bit + 64 bit */
d1789ace 1296
f3876f69
AS
1297 macl = (long) (mac64 & 0xffffffff);
1298 mach = (long) ((mac64 >> 32) & 0xffffffff);
d1789ace
MS
1299
1300 if (S) /* Store only 48 bits of the result */
1301 {
1302 if (mach < 0) /* Result is negative */
1303 {
1304 mach = mach & 0x0000ffff; /* Mask higher 16 bits */
1305 mach |= 0xffff8000; /* Sign extend higher 16 bits */
1306 }
1307 else
1308 mach = mach & 0x00007fff; /* Postive Result */
1309 }
1310
1311 MACL = macl;
1312 MACH = mach;
1313}
1314
ae0a84af
CV
1315enum {
1316 B_BCLR = 0,
1317 B_BSET = 1,
1318 B_BST = 2,
1319 B_BLD = 3,
1320 B_BAND = 4,
1321 B_BOR = 5,
1322 B_BXOR = 6,
1323 B_BLDNOT = 11,
1324 B_BANDNOT = 12,
1325 B_BORNOT = 13,
1326
1327 MOVB_RM = 0x0000,
1328 MOVW_RM = 0x1000,
1329 MOVL_RM = 0x2000,
1330 FMOV_RM = 0x3000,
1331 MOVB_MR = 0x4000,
1332 MOVW_MR = 0x5000,
1333 MOVL_MR = 0x6000,
1334 FMOV_MR = 0x7000,
1335 MOVU_BMR = 0x8000,
1336 MOVU_WMR = 0x9000,
1337};
1338
1339/* Do extended displacement move instructions. */
5fa71a1b 1340static void
ae0a84af 1341do_long_move_insn (int op, int disp12, int m, int n, int *thatlock)
86bc60eb 1342{
ae0a84af
CV
1343 int memstalls = 0;
1344 int thislock = *thatlock;
1345 int endianw = global_endianw;
1346 int *R = &(saved_state.asregs.regs[0]);
1347 unsigned char *memory = saved_state.asregs.memory;
1348 int maskb = ~((saved_state.asregs.msize - 1) & ~0);
1349 unsigned char *insn_ptr = PT2H (saved_state.asregs.pc);
1350
1351 switch (op) {
1352 case MOVB_RM: /* signed */
1353 WBAT (disp12 * 1 + R[n], R[m]);
1354 break;
1355 case MOVW_RM:
1356 WWAT (disp12 * 2 + R[n], R[m]);
1357 break;
1358 case MOVL_RM:
1359 WLAT (disp12 * 4 + R[n], R[m]);
1360 break;
1361 case FMOV_RM: /* floating point */
1362 if (FPSCR_SZ)
1363 {
1364 MA (1);
1365 WDAT (R[n] + 8 * disp12, m);
1366 }
1367 else
1368 WLAT (R[n] + 4 * disp12, FI (m));
1369 break;
1370 case MOVB_MR:
1371 R[n] = RSBAT (disp12 * 1 + R[m]);
1372 L (n);
1373 break;
1374 case MOVW_MR:
1375 R[n] = RSWAT (disp12 * 2 + R[m]);
1376 L (n);
1377 break;
1378 case MOVL_MR:
1379 R[n] = RLAT (disp12 * 4 + R[m]);
1380 L (n);
1381 break;
1382 case FMOV_MR:
1383 if (FPSCR_SZ) {
1384 MA (1);
1385 RDAT (R[m] + 8 * disp12, n);
1386 }
1387 else
1388 SET_FI (n, RLAT (R[m] + 4 * disp12));
1389 break;
1390 case MOVU_BMR: /* unsigned */
1391 R[n] = RBAT (disp12 * 1 + R[m]);
1392 L (n);
1393 break;
1394 case MOVU_WMR:
1395 R[n] = RWAT (disp12 * 2 + R[m]);
1396 L (n);
1397 break;
1398 default:
1399 RAISE_EXCEPTION (SIGINT);
1400 exit (1);
1401 }
1402 saved_state.asregs.memstalls += memstalls;
1403 *thatlock = thislock;
86bc60eb
MS
1404}
1405
ae0a84af 1406/* Do binary logical bit-manipulation insns. */
5fa71a1b 1407static void
ae0a84af
CV
1408do_blog_insn (int imm, int addr, int binop,
1409 unsigned char *memory, int maskb)
1410{
1411 int oldval = RBAT (addr);
1412
1413 switch (binop) {
1414 case B_BCLR: /* bclr.b */
1415 WBAT (addr, oldval & ~imm);
1416 break;
1417 case B_BSET: /* bset.b */
1418 WBAT (addr, oldval | imm);
1419 break;
1420 case B_BST: /* bst.b */
1421 if (T)
1422 WBAT (addr, oldval | imm);
1423 else
1424 WBAT (addr, oldval & ~imm);
1425 break;
1426 case B_BLD: /* bld.b */
1427 SET_SR_T ((oldval & imm) != 0);
1428 break;
1429 case B_BAND: /* band.b */
1430 SET_SR_T (T && ((oldval & imm) != 0));
1431 break;
1432 case B_BOR: /* bor.b */
1433 SET_SR_T (T || ((oldval & imm) != 0));
1434 break;
1435 case B_BXOR: /* bxor.b */
1436 SET_SR_T (T ^ ((oldval & imm) != 0));
1437 break;
1438 case B_BLDNOT: /* bldnot.b */
1439 SET_SR_T ((oldval & imm) == 0);
1440 break;
1441 case B_BANDNOT: /* bandnot.b */
1442 SET_SR_T (T && ((oldval & imm) == 0));
1443 break;
1444 case B_BORNOT: /* bornot.b */
1445 SET_SR_T (T || ((oldval & imm) == 0));
1446 break;
1447 }
1448}
5fa71a1b
MF
1449
1450static float
794cd17b
JR
1451fsca_s (int in, double (*f) (double))
1452{
1453 double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
1454 double result = (*f) (rad);
1455 double error, upper, lower, frac;
1456 int exp;
1457
1458 /* Search the value with the maximum error that is still within the
1459 architectural spec. */
1460 error = ldexp (1., -21);
1461 /* compensate for calculation inaccuracy by reducing error. */
1462 error = error - ldexp (1., -50);
1463 upper = result + error;
1464 frac = frexp (upper, &exp);
1465 upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
1466 lower = result - error;
1467 frac = frexp (lower, &exp);
1468 lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
1469 return abs (upper - result) >= abs (lower - result) ? upper : lower;
1470}
1471
5fa71a1b 1472static float
794cd17b
JR
1473fsrra_s (float in)
1474{
1475 double result = 1. / sqrt (in);
1476 int exp;
1477 double frac, upper, lower, error, eps;
1478
1479 /* refine result */
1480 result = result - (result * result * in - 1) * 0.5 * result;
1481 /* Search the value with the maximum error that is still within the
1482 architectural spec. */
1483 frac = frexp (result, &exp);
1484 frac = ldexp (frac, 24);
87acb4a7 1485 error = 4.0; /* 1 << 24-1-21 */
794cd17b
JR
1486 /* use eps to compensate for possible 1 ulp error in our 'exact' result. */
1487 eps = ldexp (1., -29);
1488 upper = floor (frac + error - eps);
1489 if (upper > 16777216.)
1490 upper = floor ((frac + error - eps) * 0.5) * 2.;
1491 lower = ceil ((frac - error + eps) * 2) * .5;
1492 if (lower > 8388608.)
1493 lower = ceil (frac - error + eps);
1494 upper = ldexp (upper, exp - 24);
1495 lower = ldexp (lower, exp - 24);
1496 return upper - result >= result - lower ? upper : lower;
1497}
1498
ae0a84af
CV
1499
1500/* GET_LOOP_BOUNDS {EXTENDED}
1501 These two functions compute the actual starting and ending point
1502 of the repeat loop, based on the RS and RE registers (repeat start,
1503 repeat stop). The extended version is called for LDRC, and the
1504 regular version is called for SETRC. The difference is that for
1505 LDRC, the loop start and end instructions are literally the ones
1506 pointed to by RS and RE -- for SETRC, they're not (see docs). */
1507
1508static struct loop_bounds
5fa71a1b
MF
1509get_loop_bounds_ext (int rs, int re, unsigned char *memory,
1510 unsigned char *mem_end, int maskw, int endianw)
ae0a84af
CV
1511{
1512 struct loop_bounds loop;
1513
1514 /* FIXME: should I verify RS < RE? */
1515 loop.start = PT2H (RS); /* FIXME not using the params? */
1516 loop.end = PT2H (RE & ~1); /* Ignore bit 0 of RE. */
1517 SKIP_INSN (loop.end);
1518 if (loop.end >= mem_end)
1519 loop.end = PT2H (0);
1520 return loop;
1521}
1522
63978407 1523static struct loop_bounds
5fa71a1b
MF
1524get_loop_bounds (int rs, int re, unsigned char *memory, unsigned char *mem_end,
1525 int maskw, int endianw)
63978407
JR
1526{
1527 struct loop_bounds loop;
1528
1529 if (SR_RC)
1530 {
1531 if (RS >= RE)
1532 {
1533 loop.start = PT2H (RE - 4);
1534 SKIP_INSN (loop.start);
1535 loop.end = loop.start;
1536 if (RS - RE == 0)
1537 SKIP_INSN (loop.end);
1538 if (RS - RE <= 2)
1539 SKIP_INSN (loop.end);
1540 SKIP_INSN (loop.end);
1541 }
1542 else
1543 {
1544 loop.start = PT2H (RS);
1545 loop.end = PT2H (RE - 4);
1546 SKIP_INSN (loop.end);
1547 SKIP_INSN (loop.end);
1548 SKIP_INSN (loop.end);
1549 SKIP_INSN (loop.end);
1550 }
1551 if (loop.end >= mem_end)
1552 loop.end = PT2H (0);
1553 }
1554 else
1555 loop.end = PT2H (0);
1556
1557 return loop;
1558}
1559
87acb4a7 1560static void ppi_insn ();
63978407
JR
1561
1562#include "ppi.c"
1563
6a8492b5
JR
1564/* Provide calloc / free versions that use an anonymous mmap. This can
1565 significantly cut the start-up time when a large simulator memory is
1566 required, because pages are only zeroed on demand. */
1567#ifdef MAP_ANONYMOUS
5fa71a1b 1568static void *
6a8492b5
JR
1569mcalloc (size_t nmemb, size_t size)
1570{
1571 void *page;
1572
1573 if (nmemb != 1)
1574 size *= nmemb;
1575 return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
1576 -1, 0);
1577}
1578
1579#define mfree(start,length) munmap ((start), (length))
1580#else
1581#define mcalloc calloc
1582#define mfree(start,length) free(start)
1583#endif
1584
c906108c
SS
1585/* Set the memory size to the power of two provided. */
1586
62454d3d 1587static void
5fa71a1b 1588sim_size (int power)
c906108c 1589{
c906108c
SS
1590 sim_memory_size = power;
1591
1592 if (saved_state.asregs.memory)
1593 {
6a8492b5 1594 mfree (saved_state.asregs.memory, saved_state.asregs.msize);
c906108c
SS
1595 }
1596
6a8492b5
JR
1597 saved_state.asregs.msize = 1 << power;
1598
c906108c 1599 saved_state.asregs.memory =
6a8492b5 1600 (unsigned char *) mcalloc (1, saved_state.asregs.msize);
c906108c
SS
1601
1602 if (!saved_state.asregs.memory)
1603 {
1604 fprintf (stderr,
1605 "Not enough VM for simulation of %d bytes of RAM\n",
1606 saved_state.asregs.msize);
1607
1608 saved_state.asregs.msize = 1;
6a8492b5 1609 saved_state.asregs.memory = (unsigned char *) mcalloc (1, 1);
c906108c
SS
1610 }
1611}
1612
63978407 1613static void
5fa71a1b 1614init_dsp (struct bfd *abfd)
63978407
JR
1615{
1616 int was_dsp = target_dsp;
1617 unsigned long mach = bfd_get_mach (abfd);
1618
86bc60eb
MS
1619 if (mach == bfd_mach_sh_dsp ||
1620 mach == bfd_mach_sh4al_dsp ||
1621 mach == bfd_mach_sh3_dsp)
63978407
JR
1622 {
1623 int ram_area_size, xram_start, yram_start;
1624 int new_select;
1625
1626 target_dsp = 1;
1627 if (mach == bfd_mach_sh_dsp)
1628 {
1629 /* SH7410 (orig. sh-sdp):
1630 4KB each for X & Y memory;
1631 On-chip X RAM 0x0800f000-0x0800ffff
1632 On-chip Y RAM 0x0801f000-0x0801ffff */
1633 xram_start = 0x0800f000;
1634 ram_area_size = 0x1000;
1635 }
86bc60eb 1636 if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp)
63978407
JR
1637 {
1638 /* SH7612:
1639 8KB each for X & Y memory;
1640 On-chip X RAM 0x1000e000-0x1000ffff
1641 On-chip Y RAM 0x1001e000-0x1001ffff */
1642 xram_start = 0x1000e000;
1643 ram_area_size = 0x2000;
1644 }
1645 yram_start = xram_start + 0x10000;
1646 new_select = ~(ram_area_size - 1);
1647 if (saved_state.asregs.xyram_select != new_select)
1648 {
1649 saved_state.asregs.xyram_select = new_select;
1650 free (saved_state.asregs.xmem);
1651 free (saved_state.asregs.ymem);
ae0a84af
CV
1652 saved_state.asregs.xmem =
1653 (unsigned char *) calloc (1, ram_area_size);
1654 saved_state.asregs.ymem =
1655 (unsigned char *) calloc (1, ram_area_size);
63978407
JR
1656
1657 /* Disable use of X / Y mmeory if not allocated. */
1658 if (! saved_state.asregs.xmem || ! saved_state.asregs.ymem)
1659 {
1660 saved_state.asregs.xyram_select = 0;
1661 if (saved_state.asregs.xmem)
1662 free (saved_state.asregs.xmem);
1663 if (saved_state.asregs.ymem)
1664 free (saved_state.asregs.ymem);
1665 }
1666 }
1667 saved_state.asregs.xram_start = xram_start;
1668 saved_state.asregs.yram_start = yram_start;
1669 saved_state.asregs.xmem_offset = saved_state.asregs.xmem - xram_start;
1670 saved_state.asregs.ymem_offset = saved_state.asregs.ymem - yram_start;
1671 }
1672 else
1673 {
1674 target_dsp = 0;
1675 if (saved_state.asregs.xyram_select)
1676 {
1677 saved_state.asregs.xyram_select = 0;
1678 free (saved_state.asregs.xmem);
1679 free (saved_state.asregs.ymem);
1680 }
1681 }
1682
1683 if (! saved_state.asregs.xyram_select)
1684 {
1685 saved_state.asregs.xram_start = 1;
1686 saved_state.asregs.yram_start = 1;
1687 }
1688
ae0a84af
CV
1689 if (saved_state.asregs.regstack == NULL)
1690 saved_state.asregs.regstack =
1691 calloc (512, sizeof *saved_state.asregs.regstack);
1692
63978407
JR
1693 if (target_dsp != was_dsp)
1694 {
1695 int i, tmp;
1696
3e511797 1697 for (i = (sizeof sh_dsp_table / sizeof sh_dsp_table[0]) - 1; i >= 0; i--)
63978407
JR
1698 {
1699 tmp = sh_jump_table[0xf000 + i];
1700 sh_jump_table[0xf000 + i] = sh_dsp_table[i];
1701 sh_dsp_table[i] = tmp;
1702 }
1703 }
1704}
1705
c906108c 1706static void
5fa71a1b 1707init_pointers (void)
c906108c 1708{
c906108c
SS
1709 if (saved_state.asregs.msize != 1 << sim_memory_size)
1710 {
1711 sim_size (sim_memory_size);
1712 }
1713
1714 if (saved_state.asregs.profile && !profile_file)
1715 {
1716 profile_file = fopen ("gmon.out", "wb");
1717 /* Seek to where to put the call arc data */
1718 nsamples = (1 << sim_profile_size);
1719
1720 fseek (profile_file, nsamples * 2 + 12, 0);
1721
1722 if (!profile_file)
1723 {
1724 fprintf (stderr, "Can't open gmon.out\n");
1725 }
1726 else
1727 {
1728 saved_state.asregs.profile_hist =
1729 (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64));
1730 }
1731 }
1732}
1733
1734static void
5fa71a1b 1735dump_profile (void)
c906108c
SS
1736{
1737 unsigned int minpc;
1738 unsigned int maxpc;
1739 unsigned short *p;
1740 int i;
1741
1742 p = saved_state.asregs.profile_hist;
1743 minpc = 0;
1744 maxpc = (1 << sim_profile_size);
1745
1746 fseek (profile_file, 0L, 0);
1747 swapout (minpc << PROFILE_SHIFT);
1748 swapout (maxpc << PROFILE_SHIFT);
1749 swapout (nsamples * 2 + 12);
1750 for (i = 0; i < nsamples; i++)
1751 swapout16 (saved_state.asregs.profile_hist[i]);
1752
1753}
1754
1755static void
5fa71a1b 1756gotcall (int from, int to)
c906108c
SS
1757{
1758 swapout (from);
1759 swapout (to);
1760 swapout (1);
1761}
1762
1763#define MMASKB ((saved_state.asregs.msize -1) & ~0)
1764
c906108c 1765void
5fa71a1b 1766sim_resume (SIM_DESC sd, int step, int siggnal)
c906108c 1767{
63978407
JR
1768 register unsigned char *insn_ptr;
1769 unsigned char *mem_end;
1770 struct loop_bounds loop;
c906108c
SS
1771 register int cycles = 0;
1772 register int stalls = 0;
1773 register int memstalls = 0;
1774 register int insts = 0;
1775 register int prevlock;
ae0a84af
CV
1776#if 1
1777 int thislock;
1778#else
c906108c 1779 register int thislock;
ae0a84af 1780#endif
c906108c
SS
1781 register unsigned int doprofile;
1782 register int pollcount = 0;
63978407
JR
1783 /* endianw is used for every insn fetch, hence it makes sense to cache it.
1784 endianb is used less often. */
1785 register int endianw = global_endianw;
c906108c
SS
1786
1787 int tick_start = get_now ();
c906108c 1788 void (*prev_fpe) ();
c906108c 1789
3e511797 1790 register unsigned short *jump_table = sh_jump_table;
c906108c
SS
1791
1792 register int *R = &(saved_state.asregs.regs[0]);
1793 /*register int T;*/
63978407 1794#ifndef PR
c906108c 1795 register int PR;
63978407 1796#endif
c906108c 1797
63978407
JR
1798 register int maskb = ~((saved_state.asregs.msize - 1) & ~0);
1799 register int maskw = ~((saved_state.asregs.msize - 1) & ~1);
1800 register int maskl = ~((saved_state.asregs.msize - 1) & ~3);
c906108c
SS
1801 register unsigned char *memory;
1802 register unsigned int sbit = ((unsigned int) 1 << 31);
1803
c906108c
SS
1804 prev_fpe = signal (SIGFPE, SIG_IGN);
1805
1806 init_pointers ();
63978407 1807 saved_state.asregs.exception = 0;
c906108c
SS
1808
1809 memory = saved_state.asregs.memory;
63978407 1810 mem_end = memory + saved_state.asregs.msize;
c906108c 1811
86bc60eb
MS
1812 if (RE & 1)
1813 loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);
1814 else
1815 loop = get_loop_bounds (RS, RE, memory, mem_end, maskw, endianw);
1816
63978407
JR
1817 insn_ptr = PT2H (saved_state.asregs.pc);
1818 CHECK_INSN_PTR (insn_ptr);
c906108c 1819
63978407
JR
1820#ifndef PR
1821 PR = saved_state.asregs.sregs.named.pr;
1822#endif
c906108c
SS
1823 /*T = GET_SR () & SR_MASK_T;*/
1824 prevlock = saved_state.asregs.prevlock;
1825 thislock = saved_state.asregs.thislock;
1826 doprofile = saved_state.asregs.profile;
1827
1828 /* If profiling not enabled, disable it by asking for
1829 profiles infrequently. */
1830 if (doprofile == 0)
1831 doprofile = ~0;
1832
63978407
JR
1833 loop:
1834 if (step && insn_ptr < saved_state.asregs.insn_end)
1835 {
1836 if (saved_state.asregs.exception)
1837 /* This can happen if we've already been single-stepping and
1838 encountered a loop end. */
1839 saved_state.asregs.insn_end = insn_ptr;
1840 else
1841 {
1842 saved_state.asregs.exception = SIGTRAP;
1843 saved_state.asregs.insn_end = insn_ptr + 2;
1844 }
1845 }
1846
1847 while (insn_ptr < saved_state.asregs.insn_end)
c906108c 1848 {
63978407 1849 register unsigned int iword = RIAT (insn_ptr);
c906108c 1850 register unsigned int ult;
63978407
JR
1851 register unsigned char *nip = insn_ptr + 2;
1852
c906108c
SS
1853#ifndef ACE_FAST
1854 insts++;
1855#endif
1856 top:
1857
1858#include "code.c"
1859
1860
ae0a84af 1861 in_delay_slot = 0;
63978407 1862 insn_ptr = nip;
c906108c
SS
1863
1864 if (--pollcount < 0)
1865 {
6cc98856
MF
1866 host_callback *callback = STATE_CALLBACK (sd);
1867
7a292a7a 1868 pollcount = POLL_QUIT_INTERVAL;
c906108c
SS
1869 if ((*callback->poll_quit) != NULL
1870 && (*callback->poll_quit) (callback))
1871 {
1872 sim_stop (sd);
1873 }
1874 }
1875
1876#ifndef ACE_FAST
1877 prevlock = thislock;
1878 thislock = 30;
1879 cycles++;
1880
1881 if (cycles >= doprofile)
1882 {
1883
1884 saved_state.asregs.cycles += doprofile;
1885 cycles -= doprofile;
1886 if (saved_state.asregs.profile_hist)
1887 {
63978407 1888 int n = PH2T (insn_ptr) >> PROFILE_SHIFT;
c906108c
SS
1889 if (n < nsamples)
1890 {
1891 int i = saved_state.asregs.profile_hist[n];
1892 if (i < 65000)
1893 saved_state.asregs.profile_hist[n] = i + 1;
1894 }
1895
1896 }
1897 }
1898#endif
1899 }
63978407
JR
1900 if (saved_state.asregs.insn_end == loop.end)
1901 {
1902 saved_state.asregs.cregs.named.sr += SR_RC_INCREMENT;
1903 if (SR_RC)
1904 insn_ptr = loop.start;
1905 else
1906 {
1907 saved_state.asregs.insn_end = mem_end;
1908 loop.end = PT2H (0);
1909 }
1910 goto loop;
1911 }
c906108c
SS
1912
1913 if (saved_state.asregs.exception == SIGILL
1914 || saved_state.asregs.exception == SIGBUS)
1915 {
63978407 1916 insn_ptr -= 2;
c906108c 1917 }
63978407
JR
1918 /* Check for SIGBUS due to insn fetch. */
1919 else if (! saved_state.asregs.exception)
dc9feb5c 1920 saved_state.asregs.exception = SIGBUS;
c906108c
SS
1921
1922 saved_state.asregs.ticks += get_now () - tick_start;
1923 saved_state.asregs.cycles += cycles;
1924 saved_state.asregs.stalls += stalls;
1925 saved_state.asregs.memstalls += memstalls;
1926 saved_state.asregs.insts += insts;
63978407
JR
1927 saved_state.asregs.pc = PH2T (insn_ptr);
1928#ifndef PR
1929 saved_state.asregs.sregs.named.pr = PR;
1930#endif
c906108c
SS
1931
1932 saved_state.asregs.prevlock = prevlock;
1933 saved_state.asregs.thislock = thislock;
1934
1935 if (profile_file)
1936 {
1937 dump_profile ();
1938 }
1939
1940 signal (SIGFPE, prev_fpe);
c906108c
SS
1941}
1942
1943int
5fa71a1b 1944sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
c906108c
SS
1945{
1946 int i;
1947
1948 init_pointers ();
1949
1950 for (i = 0; i < size; i++)
1951 {
63978407 1952 saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb] = buffer[i];
c906108c
SS
1953 }
1954 return size;
1955}
1956
1957int
5fa71a1b 1958sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
c906108c
SS
1959{
1960 int i;
1961
1962 init_pointers ();
1963
1964 for (i = 0; i < size; i++)
1965 {
63978407 1966 buffer[i] = saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb];
c906108c
SS
1967 }
1968 return size;
1969}
1970
ae0a84af
CV
1971static int gdb_bank_number;
1972enum {
1973 REGBANK_MACH = 15,
1974 REGBANK_IVN = 16,
1975 REGBANK_PR = 17,
1976 REGBANK_GBR = 18,
1977 REGBANK_MACL = 19
1978};
1979
e1211e55
MF
1980static int
1981sh_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
c906108c 1982{
63978407
JR
1983 unsigned val;
1984
c906108c 1985 init_pointers ();
87acb4a7 1986 val = swap (* (int *) memory);
63978407
JR
1987 switch (rn)
1988 {
2f14585c
JR
1989 case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
1990 case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
1991 case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
1992 case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
1993 case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
1994 case SIM_SH_R15_REGNUM:
63978407
JR
1995 saved_state.asregs.regs[rn] = val;
1996 break;
2f14585c 1997 case SIM_SH_PC_REGNUM:
63978407
JR
1998 saved_state.asregs.pc = val;
1999 break;
2f14585c 2000 case SIM_SH_PR_REGNUM:
63978407
JR
2001 PR = val;
2002 break;
2f14585c 2003 case SIM_SH_GBR_REGNUM:
63978407
JR
2004 GBR = val;
2005 break;
2f14585c 2006 case SIM_SH_VBR_REGNUM:
63978407
JR
2007 VBR = val;
2008 break;
2f14585c 2009 case SIM_SH_MACH_REGNUM:
63978407
JR
2010 MACH = val;
2011 break;
2f14585c 2012 case SIM_SH_MACL_REGNUM:
63978407
JR
2013 MACL = val;
2014 break;
2f14585c 2015 case SIM_SH_SR_REGNUM:
63978407
JR
2016 SET_SR (val);
2017 break;
2f14585c 2018 case SIM_SH_FPUL_REGNUM:
63978407
JR
2019 FPUL = val;
2020 break;
2f14585c 2021 case SIM_SH_FPSCR_REGNUM:
63978407
JR
2022 SET_FPSCR (val);
2023 break;
2f14585c
JR
2024 case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
2025 case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
2026 case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
2027 case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
2028 case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
2029 case SIM_SH_FR15_REGNUM:
2030 SET_FI (rn - SIM_SH_FR0_REGNUM, val);
2031 break;
2032 case SIM_SH_DSR_REGNUM:
2033 DSR = val;
2034 break;
2035 case SIM_SH_A0G_REGNUM:
2036 A0G = val;
2037 break;
2038 case SIM_SH_A0_REGNUM:
2039 A0 = val;
2040 break;
2041 case SIM_SH_A1G_REGNUM:
2042 A1G = val;
2043 break;
2044 case SIM_SH_A1_REGNUM:
2045 A1 = val;
2046 break;
2047 case SIM_SH_M0_REGNUM:
2048 M0 = val;
2049 break;
2050 case SIM_SH_M1_REGNUM:
2051 M1 = val;
2052 break;
2053 case SIM_SH_X0_REGNUM:
2054 X0 = val;
2055 break;
2056 case SIM_SH_X1_REGNUM:
2057 X1 = val;
2058 break;
2059 case SIM_SH_Y0_REGNUM:
2060 Y0 = val;
2061 break;
2062 case SIM_SH_Y1_REGNUM:
2063 Y1 = val;
2064 break;
2065 case SIM_SH_MOD_REGNUM:
2066 SET_MOD (val);
2067 break;
2068 case SIM_SH_RS_REGNUM:
2069 RS = val;
2070 break;
2071 case SIM_SH_RE_REGNUM:
2072 RE = val;
2073 break;
2074 case SIM_SH_SSR_REGNUM:
63978407
JR
2075 SSR = val;
2076 break;
2f14585c 2077 case SIM_SH_SPC_REGNUM:
63978407
JR
2078 SPC = val;
2079 break;
2080 /* The rn_bank idiosyncracies are not due to hardware differences, but to
2081 a weird aliasing naming scheme for sh3 / sh3e / sh4. */
2f14585c
JR
2082 case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
2083 case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
2084 case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
2085 case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
ae0a84af
CV
2086 if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
2087 {
2088 rn -= SIM_SH_R0_BANK0_REGNUM;
2089 saved_state.asregs.regstack[gdb_bank_number].regs[rn] = val;
2090 }
2091 else
63978407 2092 if (SR_MD && SR_RB)
2f14585c 2093 Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) = val;
63978407 2094 else
2f14585c 2095 saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM] = val;
63978407 2096 break;
2f14585c
JR
2097 case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
2098 case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
2099 case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
2100 case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
ae0a84af
CV
2101 if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
2102 {
2103 rn -= SIM_SH_R0_BANK1_REGNUM;
2104 saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8] = val;
2105 }
2106 else
2f14585c
JR
2107 if (SR_MD && SR_RB)
2108 saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM] = val;
63978407 2109 else
2f14585c
JR
2110 Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM) = val;
2111 break;
2112 case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
2113 case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
2114 case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
2115 case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
2116 SET_Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM, val);
63978407 2117 break;
ae0a84af
CV
2118 case SIM_SH_TBR_REGNUM:
2119 TBR = val;
2120 break;
2121 case SIM_SH_IBNR_REGNUM:
2122 IBNR = val;
2123 break;
2124 case SIM_SH_IBCR_REGNUM:
2125 IBCR = val;
2126 break;
2127 case SIM_SH_BANK_REGNUM:
2128 /* This is a pseudo-register maintained just for gdb.
2129 It tells us what register bank gdb would like to read/write. */
2130 gdb_bank_number = val;
2131 break;
2132 case SIM_SH_BANK_MACL_REGNUM:
2133 saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL] = val;
2134 break;
2135 case SIM_SH_BANK_GBR_REGNUM:
2136 saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR] = val;
2137 break;
2138 case SIM_SH_BANK_PR_REGNUM:
2139 saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR] = val;
2140 break;
2141 case SIM_SH_BANK_IVN_REGNUM:
2142 saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN] = val;
2143 break;
2144 case SIM_SH_BANK_MACH_REGNUM:
2145 saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH] = val;
2146 break;
63978407
JR
2147 default:
2148 return 0;
2149 }
f95586a4 2150 return length;
c906108c
SS
2151}
2152
e1211e55
MF
2153static int
2154sh_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
c906108c 2155{
63978407
JR
2156 int val;
2157
c906108c 2158 init_pointers ();
63978407
JR
2159 switch (rn)
2160 {
2f14585c
JR
2161 case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
2162 case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
2163 case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
2164 case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
2165 case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
2166 case SIM_SH_R15_REGNUM:
63978407
JR
2167 val = saved_state.asregs.regs[rn];
2168 break;
2f14585c 2169 case SIM_SH_PC_REGNUM:
63978407
JR
2170 val = saved_state.asregs.pc;
2171 break;
2f14585c 2172 case SIM_SH_PR_REGNUM:
63978407
JR
2173 val = PR;
2174 break;
2f14585c 2175 case SIM_SH_GBR_REGNUM:
63978407
JR
2176 val = GBR;
2177 break;
2f14585c 2178 case SIM_SH_VBR_REGNUM:
63978407
JR
2179 val = VBR;
2180 break;
2f14585c 2181 case SIM_SH_MACH_REGNUM:
63978407
JR
2182 val = MACH;
2183 break;
2f14585c 2184 case SIM_SH_MACL_REGNUM:
63978407
JR
2185 val = MACL;
2186 break;
2f14585c 2187 case SIM_SH_SR_REGNUM:
63978407
JR
2188 val = GET_SR ();
2189 break;
2f14585c 2190 case SIM_SH_FPUL_REGNUM:
63978407
JR
2191 val = FPUL;
2192 break;
2f14585c 2193 case SIM_SH_FPSCR_REGNUM:
63978407
JR
2194 val = GET_FPSCR ();
2195 break;
2f14585c
JR
2196 case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
2197 case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
2198 case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
2199 case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
2200 case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
2201 case SIM_SH_FR15_REGNUM:
2202 val = FI (rn - SIM_SH_FR0_REGNUM);
63978407 2203 break;
2f14585c
JR
2204 case SIM_SH_DSR_REGNUM:
2205 val = DSR;
63978407 2206 break;
2f14585c
JR
2207 case SIM_SH_A0G_REGNUM:
2208 val = SEXT (A0G);
63978407 2209 break;
2f14585c
JR
2210 case SIM_SH_A0_REGNUM:
2211 val = A0;
63978407 2212 break;
2f14585c
JR
2213 case SIM_SH_A1G_REGNUM:
2214 val = SEXT (A1G);
63978407 2215 break;
2f14585c
JR
2216 case SIM_SH_A1_REGNUM:
2217 val = A1;
63978407 2218 break;
2f14585c
JR
2219 case SIM_SH_M0_REGNUM:
2220 val = M0;
63978407 2221 break;
2f14585c
JR
2222 case SIM_SH_M1_REGNUM:
2223 val = M1;
63978407 2224 break;
2f14585c
JR
2225 case SIM_SH_X0_REGNUM:
2226 val = X0;
63978407 2227 break;
2f14585c
JR
2228 case SIM_SH_X1_REGNUM:
2229 val = X1;
63978407 2230 break;
2f14585c
JR
2231 case SIM_SH_Y0_REGNUM:
2232 val = Y0;
63978407 2233 break;
2f14585c
JR
2234 case SIM_SH_Y1_REGNUM:
2235 val = Y1;
63978407 2236 break;
2f14585c
JR
2237 case SIM_SH_MOD_REGNUM:
2238 val = MOD;
2239 break;
2240 case SIM_SH_RS_REGNUM:
2241 val = RS;
2242 break;
2243 case SIM_SH_RE_REGNUM:
2244 val = RE;
2245 break;
2246 case SIM_SH_SSR_REGNUM:
63978407
JR
2247 val = SSR;
2248 break;
2f14585c 2249 case SIM_SH_SPC_REGNUM:
63978407
JR
2250 val = SPC;
2251 break;
2252 /* The rn_bank idiosyncracies are not due to hardware differences, but to
2253 a weird aliasing naming scheme for sh3 / sh3e / sh4. */
2f14585c
JR
2254 case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
2255 case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
2256 case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
2257 case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
ae0a84af
CV
2258 if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
2259 {
2260 rn -= SIM_SH_R0_BANK0_REGNUM;
2261 val = saved_state.asregs.regstack[gdb_bank_number].regs[rn];
2262 }
2263 else
2f14585c
JR
2264 val = (SR_MD && SR_RB
2265 ? Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM)
2266 : saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM]);
2267 break;
2268 case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
2269 case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
2270 case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
2271 case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
ae0a84af
CV
2272 if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
2273 {
2274 rn -= SIM_SH_R0_BANK1_REGNUM;
2275 val = saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8];
2276 }
2277 else
2f14585c
JR
2278 val = (! SR_MD || ! SR_RB
2279 ? Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM)
2280 : saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM]);
2281 break;
2282 case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
2283 case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
2284 case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
2285 case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
2286 val = Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM);
63978407 2287 break;
ae0a84af
CV
2288 case SIM_SH_TBR_REGNUM:
2289 val = TBR;
2290 break;
2291 case SIM_SH_IBNR_REGNUM:
2292 val = IBNR;
2293 break;
2294 case SIM_SH_IBCR_REGNUM:
2295 val = IBCR;
2296 break;
2297 case SIM_SH_BANK_REGNUM:
2298 /* This is a pseudo-register maintained just for gdb.
2299 It tells us what register bank gdb would like to read/write. */
2300 val = gdb_bank_number;
2301 break;
2302 case SIM_SH_BANK_MACL_REGNUM:
2303 val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL];
2304 break;
2305 case SIM_SH_BANK_GBR_REGNUM:
2306 val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR];
2307 break;
2308 case SIM_SH_BANK_PR_REGNUM:
2309 val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR];
2310 break;
2311 case SIM_SH_BANK_IVN_REGNUM:
2312 val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN];
2313 break;
2314 case SIM_SH_BANK_MACH_REGNUM:
2315 val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH];
2316 break;
63978407
JR
2317 default:
2318 return 0;
2319 }
2320 * (int *) memory = swap (val);
f95586a4 2321 return length;
c906108c
SS
2322}
2323
c906108c 2324void
5fa71a1b 2325sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
c906108c
SS
2326{
2327 /* The SH simulator uses SIGQUIT to indicate that the program has
2328 exited, so we must check for it here and translate it to exit. */
2329 if (saved_state.asregs.exception == SIGQUIT)
2330 {
2331 *reason = sim_exited;
2332 *sigrc = saved_state.asregs.regs[5];
2333 }
2334 else
2335 {
2336 *reason = sim_stopped;
2337 *sigrc = saved_state.asregs.exception;
2338 }
2339}
2340
2341void
5fa71a1b 2342sim_info (SIM_DESC sd, int verbose)
c906108c 2343{
87acb4a7
MS
2344 double timetaken =
2345 (double) saved_state.asregs.ticks / (double) now_persec ();
c906108c
SS
2346 double virttime = saved_state.asregs.cycles / 36.0e6;
2347
6cc98856
MF
2348 sim_io_printf (sd, "\n\n# instructions executed %10d\n",
2349 saved_state.asregs.insts);
2350 sim_io_printf (sd, "# cycles %10d\n",
2351 saved_state.asregs.cycles);
2352 sim_io_printf (sd, "# pipeline stalls %10d\n",
2353 saved_state.asregs.stalls);
2354 sim_io_printf (sd, "# misaligned load/store %10d\n",
2355 saved_state.asregs.memstalls);
2356 sim_io_printf (sd, "# real time taken %10.4f\n", timetaken);
2357 sim_io_printf (sd, "# virtual time taken %10.4f\n", virttime);
2358 sim_io_printf (sd, "# profiling size %10d\n", sim_profile_size);
2359 sim_io_printf (sd, "# profiling frequency %10d\n",
2360 saved_state.asregs.profile);
2361 sim_io_printf (sd, "# profile maxpc %10x\n",
2362 (1 << sim_profile_size) << PROFILE_SHIFT);
c906108c
SS
2363
2364 if (timetaken != 0)
2365 {
6cc98856
MF
2366 sim_io_printf (sd, "# cycles/second %10d\n",
2367 (int) (saved_state.asregs.cycles / timetaken));
2368 sim_io_printf (sd, "# simulation ratio %10.4f\n",
2369 virttime / timetaken);
c906108c
SS
2370 }
2371}
2372
27b97b40
MF
2373static sim_cia
2374sh_pc_get (sim_cpu *cpu)
2375{
2376 return saved_state.asregs.pc;
2377}
2378
2379static void
2380sh_pc_set (sim_cpu *cpu, sim_cia pc)
2381{
2382 saved_state.asregs.pc = pc;
2383}
2384
62454d3d
MF
2385static void
2386free_state (SIM_DESC sd)
c906108c 2387{
62454d3d
MF
2388 if (STATE_MODULES (sd) != NULL)
2389 sim_module_uninstall (sd);
2390 sim_cpu_free_all (sd);
2391 sim_state_free (sd);
c906108c
SS
2392}
2393
2394SIM_DESC
5fa71a1b 2395sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
c906108c
SS
2396{
2397 char **p;
63978407
JR
2398 int i;
2399 union
2400 {
2401 int i;
2402 short s[2];
2403 char c[4];
2404 }
2405 mem_word;
c906108c 2406
62454d3d
MF
2407 SIM_DESC sd = sim_state_alloc (kind, cb);
2408 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
2409
62454d3d
MF
2410 /* The cpu data is kept in a separately allocated chunk of memory. */
2411 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
2412 {
2413 free_state (sd);
2414 return 0;
2415 }
2416
2417 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
2418 {
2419 free_state (sd);
2420 return 0;
2421 }
2422
2423 /* getopt will print the error message so we just have to exit if this fails.
2424 FIXME: Hmmm... in the case of gdb we need getopt to call
2425 print_filtered. */
2426 if (sim_parse_args (sd, argv) != SIM_RC_OK)
2427 {
2428 free_state (sd);
2429 return 0;
2430 }
2431
2432 /* Check for/establish the a reference program image. */
2433 if (sim_analyze_program (sd,
2434 (STATE_PROG_ARGV (sd) != NULL
2435 ? *STATE_PROG_ARGV (sd)
2436 : NULL), abfd) != SIM_RC_OK)
2437 {
2438 free_state (sd);
2439 return 0;
2440 }
2441
2442 /* Configure/verify the target byte order and other runtime
2443 configuration options. */
2444 if (sim_config (sd) != SIM_RC_OK)
2445 {
2446 sim_module_uninstall (sd);
2447 return 0;
2448 }
2449
2450 if (sim_post_argv_init (sd) != SIM_RC_OK)
2451 {
2452 /* Uninstall the modules to avoid memory leaks,
2453 file descriptor leaks, etc. */
2454 sim_module_uninstall (sd);
2455 return 0;
2456 }
2457
27b97b40
MF
2458 /* CPU specific initialization. */
2459 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
2460 {
2461 SIM_CPU *cpu = STATE_CPU (sd, i);
2462
e1211e55
MF
2463 CPU_REG_FETCH (cpu) = sh_reg_fetch;
2464 CPU_REG_STORE (cpu) = sh_reg_store;
27b97b40
MF
2465 CPU_PC_FETCH (cpu) = sh_pc_get;
2466 CPU_PC_STORE (cpu) = sh_pc_set;
2467 }
2468
c906108c
SS
2469 for (p = argv + 1; *p != NULL; ++p)
2470 {
62454d3d 2471 if (isdigit (**p))
6cc98856 2472 parse_and_set_memory_size (sd, *p);
c906108c
SS
2473 }
2474
63978407
JR
2475 if (abfd)
2476 init_dsp (abfd);
2477
2478 for (i = 4; (i -= 2) >= 0; )
2479 mem_word.s[i >> 1] = i;
2480 global_endianw = mem_word.i >> (target_little_endian ? 0 : 16) & 0xffff;
2481
2482 for (i = 4; --i >= 0; )
2483 mem_word.c[i] = i;
2484 endianb = mem_word.i >> (target_little_endian ? 0 : 24) & 0xff;
2485
62454d3d 2486 return sd;
c906108c
SS
2487}
2488
2489static void
6cc98856 2490parse_and_set_memory_size (SIM_DESC sd, const char *str)
c906108c
SS
2491{
2492 int n;
2493
2494 n = strtol (str, NULL, 10);
2495 if (n > 0 && n <= 24)
2496 sim_memory_size = n;
2497 else
6cc98856 2498 sim_io_printf (sd, "Bad memory size %d; must be 1 to 24, inclusive\n", n);
c906108c
SS
2499}
2500
c906108c 2501SIM_RC
5fa71a1b 2502sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
c906108c 2503{
de0492b6 2504 /* Clear the registers. */
c906108c 2505 memset (&saved_state, 0,
87acb4a7 2506 (char*) &saved_state.asregs.end_of_registers - (char*) &saved_state);
de0492b6
AO
2507
2508 /* Set the PC. */
c906108c
SS
2509 if (prog_bfd != NULL)
2510 saved_state.asregs.pc = bfd_get_start_address (prog_bfd);
de0492b6 2511
ae0a84af
CV
2512 /* Set the bfd machine type. */
2513 if (prog_bfd != NULL)
2514 saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
2515
62454d3d
MF
2516 if (prog_bfd != NULL)
2517 init_dsp (prog_bfd);
2518
c906108c
SS
2519 return SIM_RC_OK;
2520}
2521
2522void
5fa71a1b 2523sim_do_command (SIM_DESC sd, const char *cmd)
c906108c 2524{
60d847df 2525 const char *sms_cmd = "set-memory-size";
c906108c
SS
2526 int cmdsize;
2527
2528 if (cmd == NULL || *cmd == '\0')
2529 {
2530 cmd = "help";
2531 }
2532
2533 cmdsize = strlen (sms_cmd);
87acb4a7
MS
2534 if (strncmp (cmd, sms_cmd, cmdsize) == 0
2535 && strchr (" \t", cmd[cmdsize]) != NULL)
c906108c 2536 {
6cc98856 2537 parse_and_set_memory_size (sd, cmd + cmdsize + 1);
c906108c
SS
2538 }
2539 else if (strcmp (cmd, "help") == 0)
2540 {
6cc98856
MF
2541 sim_io_printf (sd, "List of SH simulator commands:\n\n");
2542 sim_io_printf (sd, "set-memory-size <n> -- Set the number of address bits to use\n");
2543 sim_io_printf (sd, "\n");
c906108c
SS
2544 }
2545 else
2546 {
6cc98856 2547 sim_io_printf (sd, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
c906108c
SS
2548 }
2549}