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