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