1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485 |
- /* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture.
- Written by Steve Chamberlain of Cygnus Support.
- sac@cygnus.com
- This file is part of SH sim
- THIS SOFTWARE IS NOT COPYRIGHTED
- Cygnus offers the following for use in the public domain. Cygnus
- makes no warranty with regard to the software or it's performance
- and the user accepts the software "AS IS" with all faults.
- CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
- THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
- /* This must come before any other includes. */
- #include "defs.h"
- #include <ctype.h>
- #include <stdio.h>
- #include <errno.h>
- #include <signal.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_MMAP
- #include <sys/mman.h>
- # ifndef MAP_FAILED
- # define MAP_FAILED -1
- # endif
- # if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
- # define MAP_ANONYMOUS MAP_ANON
- # endif
- #endif
- #include <string.h>
- #include <stdlib.h>
- #ifdef HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #include <time.h>
- #include <sys/time.h>
- #ifdef HAVE_UTIME_H
- #include <utime.h>
- #endif
- #ifndef _WIN32
- #include <sys/wait.h>
- #endif
- #include "bfd.h"
- #include "sim/callback.h"
- #include "sim/sim.h"
- #include "gdb/sim-sh.h"
- #include "sim-main.h"
- #include "sim-base.h"
- #include "sim-options.h"
- #include "target-newlib-syscall.h"
- #include <math.h>
- #ifdef _WIN32
- #include <float.h> /* Needed for _isnan() */
- #ifndef isnan
- #define isnan _isnan
- #endif
- #endif
- #ifndef SIGBUS
- #define SIGBUS SIGSEGV
- #endif
- #ifndef SIGQUIT
- #define SIGQUIT SIGTERM
- #endif
- #ifndef SIGTRAP
- #define SIGTRAP 5
- #endif
- /* TODO: Stop using these names. */
- #undef SEXT
- #undef SEXT32
- extern unsigned short sh_jump_table[], sh_dsp_table[0x1000], ppi_table[];
- #define O_RECOMPILE 85
- #define DEFINE_TABLE
- #define DISASSEMBLER_TABLE
- /* Define the rate at which the simulator should poll the host
- for a quit. */
- #define POLL_QUIT_INTERVAL 0x60000
- /* TODO: Move into sim_cpu. */
- saved_state_type saved_state;
- struct loop_bounds { unsigned char *start, *end; };
- /* These variables are at file scope so that functions other than
- sim_resume can use the fetch/store macros */
- #define target_little_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
- static int global_endianw, endianb;
- static int target_dsp;
- #define host_little_endian (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
- static int maskw = 0;
- static int maskl = 0;
- /* Short hand definitions of the registers */
- #define SBIT(x) ((x)&sbit)
- #define R0 saved_state.asregs.regs[0]
- #define Rn saved_state.asregs.regs[n]
- #define Rm saved_state.asregs.regs[m]
- #define UR0 (unsigned int) (saved_state.asregs.regs[0])
- #define UR (unsigned int) R
- #define UR (unsigned int) R
- #define SR0 saved_state.asregs.regs[0]
- #define CREG(n) (saved_state.asregs.cregs[(n)])
- #define GBR saved_state.asregs.gbr
- #define VBR saved_state.asregs.vbr
- #define DBR saved_state.asregs.dbr
- #define TBR saved_state.asregs.tbr
- #define IBCR saved_state.asregs.ibcr
- #define IBNR saved_state.asregs.ibnr
- #define BANKN (saved_state.asregs.ibnr & 0x1ff)
- #define ME ((saved_state.asregs.ibnr >> 14) & 0x3)
- #define SSR saved_state.asregs.ssr
- #define SPC saved_state.asregs.spc
- #define SGR saved_state.asregs.sgr
- #define SREG(n) (saved_state.asregs.sregs[(n)])
- #define MACH saved_state.asregs.mach
- #define MACL saved_state.asregs.macl
- #define PR saved_state.asregs.pr
- #define FPUL saved_state.asregs.fpul
- #define PC insn_ptr
- /* Alternate bank of registers r0-r7 */
- /* Note: code controling SR handles flips between BANK0 and BANK1 */
- #define Rn_BANK(n) (saved_state.asregs.bank[(n)])
- #define SET_Rn_BANK(n, EXP) do { saved_state.asregs.bank[(n)] = (EXP); } while (0)
- /* Manipulate SR */
- #define SR_MASK_BO (1 << 14)
- #define SR_MASK_CS (1 << 13)
- #define SR_MASK_DMY (1 << 11)
- #define SR_MASK_DMX (1 << 10)
- #define SR_MASK_M (1 << 9)
- #define SR_MASK_Q (1 << 8)
- #define SR_MASK_I (0xf << 4)
- #define SR_MASK_S (1 << 1)
- #define SR_MASK_T (1 << 0)
- #define SR_MASK_BL (1 << 28)
- #define SR_MASK_RB (1 << 29)
- #define SR_MASK_MD (1 << 30)
- #define SR_MASK_RC 0x0fff0000
- #define SR_RC_INCREMENT -0x00010000
- #define BO ((saved_state.asregs.sr & SR_MASK_BO) != 0)
- #define CS ((saved_state.asregs.sr & SR_MASK_CS) != 0)
- #define M ((saved_state.asregs.sr & SR_MASK_M) != 0)
- #define Q ((saved_state.asregs.sr & SR_MASK_Q) != 0)
- #define S ((saved_state.asregs.sr & SR_MASK_S) != 0)
- #define T ((saved_state.asregs.sr & SR_MASK_T) != 0)
- #define LDST ((saved_state.asregs.ldst) != 0)
- #define SR_BL ((saved_state.asregs.sr & SR_MASK_BL) != 0)
- #define SR_RB ((saved_state.asregs.sr & SR_MASK_RB) != 0)
- #define SR_MD ((saved_state.asregs.sr & SR_MASK_MD) != 0)
- #define SR_DMY ((saved_state.asregs.sr & SR_MASK_DMY) != 0)
- #define SR_DMX ((saved_state.asregs.sr & SR_MASK_DMX) != 0)
- #define SR_RC ((saved_state.asregs.sr & SR_MASK_RC))
- /* Note: don't use this for privileged bits */
- #define SET_SR_BIT(EXP, BIT) \
- do { \
- if ((EXP) & 1) \
- saved_state.asregs.sr |= (BIT); \
- else \
- saved_state.asregs.sr &= ~(BIT); \
- } while (0)
- #define SET_SR_BO(EXP) SET_SR_BIT ((EXP), SR_MASK_BO)
- #define SET_SR_CS(EXP) SET_SR_BIT ((EXP), SR_MASK_CS)
- #define SET_BANKN(EXP) \
- do { \
- IBNR = (IBNR & 0xfe00) | ((EXP) & 0x1f); \
- } while (0)
- #define SET_ME(EXP) \
- do { \
- IBNR = (IBNR & 0x3fff) | (((EXP) & 0x3) << 14); \
- } while (0)
- #define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M)
- #define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q)
- #define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S)
- #define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T)
- #define SET_LDST(EXP) (saved_state.asregs.ldst = ((EXP) != 0))
- /* stc currently relies on being able to read SR without modifications. */
- #define GET_SR() (saved_state.asregs.sr - 0)
- #define SET_SR(x) set_sr (x)
- #define SET_RC(x) \
- (saved_state.asregs.sr \
- = (saved_state.asregs.sr & 0xf000ffff) | ((x) & 0xfff) << 16)
- /* Manipulate FPSCR */
- #define FPSCR_MASK_FR (1 << 21)
- #define FPSCR_MASK_SZ (1 << 20)
- #define FPSCR_MASK_PR (1 << 19)
- #define FPSCR_FR ((GET_FPSCR () & FPSCR_MASK_FR) != 0)
- #define FPSCR_SZ ((GET_FPSCR () & FPSCR_MASK_SZ) != 0)
- #define FPSCR_PR ((GET_FPSCR () & FPSCR_MASK_PR) != 0)
- static void
- set_fpscr1 (int x)
- {
- int old = saved_state.asregs.fpscr;
- saved_state.asregs.fpscr = (x);
- /* swap the floating point register banks */
- if ((saved_state.asregs.fpscr ^ old) & FPSCR_MASK_FR
- /* Ignore bit change if simulating sh-dsp. */
- && ! target_dsp)
- {
- union fregs_u tmpf = saved_state.asregs.fregs[0];
- saved_state.asregs.fregs[0] = saved_state.asregs.fregs[1];
- saved_state.asregs.fregs[1] = tmpf;
- }
- }
- /* sts relies on being able to read fpscr directly. */
- #define GET_FPSCR() (saved_state.asregs.fpscr)
- #define SET_FPSCR(x) \
- do { \
- set_fpscr1 (x); \
- } while (0)
- #define DSR (saved_state.asregs.fpscr)
- #define RAISE_EXCEPTION(x) \
- (saved_state.asregs.exception = x, saved_state.asregs.insn_end = 0)
- #define RAISE_EXCEPTION_IF_IN_DELAY_SLOT() \
- if (in_delay_slot) RAISE_EXCEPTION (SIGILL)
- /* This function exists mainly for the purpose of setting a breakpoint to
- catch simulated bus errors when running the simulator under GDB. */
- static void
- raise_exception (int x)
- {
- RAISE_EXCEPTION (x);
- }
- static void
- raise_buserror (void)
- {
- raise_exception (SIGBUS);
- }
- #define PROCESS_SPECIAL_ADDRESS(addr, endian, ptr, bits_written, \
- forbidden_addr_bits, data, retval) \
- do { \
- if (addr & forbidden_addr_bits) \
- { \
- raise_buserror (); \
- return retval; \
- } \
- else if ((addr & saved_state.asregs.xyram_select) \
- == saved_state.asregs.xram_start) \
- ptr = (void *) &saved_state.asregs.xmem_offset[addr ^ endian]; \
- else if ((addr & saved_state.asregs.xyram_select) \
- == saved_state.asregs.yram_start) \
- ptr = (void *) &saved_state.asregs.ymem_offset[addr ^ endian]; \
- else if ((unsigned) addr >> 24 == 0xf0 \
- && bits_written == 32 && (data & 1) == 0) \
- /* This invalidates (if not associative) or might invalidate \
- (if associative) an instruction cache line. This is used for \
- trampolines. Since we don't simulate the cache, this is a no-op \
- as far as the simulator is concerned. */ \
- return retval; \
- else \
- { \
- if (bits_written == 8 && addr > 0x5000000) \
- IOMEM (addr, 1, data); \
- /* We can't do anything useful with the other stuff, so fail. */ \
- raise_buserror (); \
- return retval; \
- } \
- } while (0)
- /* FIXME: sim_resume should be renamed to sim_engine_run. sim_resume
- being implemented by ../common/sim_resume.c and the below should
- make a call to sim_engine_halt */
- #define BUSERROR(addr, mask) ((addr) & (mask))
- #define WRITE_BUSERROR(addr, mask, data, addr_func) \
- do \
- { \
- if (addr & mask) \
- { \
- addr_func (addr, data); \
- return; \
- } \
- } \
- while (0)
- #define READ_BUSERROR(addr, mask, addr_func) \
- do \
- { \
- if (addr & mask) \
- return addr_func (addr); \
- } \
- while (0)
- /* Define this to enable register lifetime checking.
- The compiler generates "add #0,rn" insns to mark registers as invalid,
- the simulator uses this info to call fail if it finds a ref to an invalid
- register before a def
- #define PARANOID
- */
- #ifdef PARANOID
- int valid[16];
- #define CREF(x) if (!valid[x]) fail ();
- #define CDEF(x) valid[x] = 1;
- #define UNDEF(x) valid[x] = 0;
- #else
- #define CREF(x)
- #define CDEF(x)
- #define UNDEF(x)
- #endif
- static void parse_and_set_memory_size (SIM_DESC sd, const char *str);
- static int IOMEM (int addr, int write, int value);
- static struct loop_bounds get_loop_bounds (int, int, unsigned char *,
- unsigned char *, int, int);
- static void process_wlat_addr (int, int);
- static void process_wwat_addr (int, int);
- static void process_wbat_addr (int, int);
- static int process_rlat_addr (int);
- static int process_rwat_addr (int);
- static int process_rbat_addr (int);
- /* Floating point registers */
- #define DR(n) (get_dr (n))
- static double
- get_dr (int n)
- {
- n = (n & ~1);
- if (host_little_endian)
- {
- union
- {
- int i[2];
- double d;
- } dr;
- dr.i[1] = saved_state.asregs.fregs[0].i[n + 0];
- dr.i[0] = saved_state.asregs.fregs[0].i[n + 1];
- return dr.d;
- }
- else
- return (saved_state.asregs.fregs[0].d[n >> 1]);
- }
- #define SET_DR(n, EXP) set_dr ((n), (EXP))
- static void
- set_dr (int n, double exp)
- {
- n = (n & ~1);
- if (host_little_endian)
- {
- union
- {
- int i[2];
- double d;
- } dr;
- dr.d = exp;
- saved_state.asregs.fregs[0].i[n + 0] = dr.i[1];
- saved_state.asregs.fregs[0].i[n + 1] = dr.i[0];
- }
- else
- saved_state.asregs.fregs[0].d[n >> 1] = exp;
- }
- #define SET_FI(n,EXP) (saved_state.asregs.fregs[0].i[(n)] = (EXP))
- #define FI(n) (saved_state.asregs.fregs[0].i[(n)])
- #define FR(n) (saved_state.asregs.fregs[0].f[(n)])
- #define SET_FR(n,EXP) (saved_state.asregs.fregs[0].f[(n)] = (EXP))
- #define XD_TO_XF(n) ((((n) & 1) << 5) | ((n) & 0x1e))
- #define XF(n) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f])
- #define SET_XF(n,EXP) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f] = (EXP))
- #define RS saved_state.asregs.rs
- #define RE saved_state.asregs.re
- #define MOD (saved_state.asregs.mod)
- #define SET_MOD(i) \
- (MOD = (i), \
- MOD_ME = (unsigned) MOD >> 16 | (SR_DMY ? ~0xffff : (SR_DMX ? 0 : 0x10000)), \
- MOD_DELTA = (MOD & 0xffff) - ((unsigned) MOD >> 16))
- #define DSP_R(n) saved_state.asregs.sregs[(n)]
- #define DSP_GRD(n) DSP_R ((n) + 8)
- #define GET_DSP_GRD(n) ((n | 2) == 7 ? SEXT (DSP_GRD (n)) : SIGN32 (DSP_R (n)))
- #define A1 DSP_R (5)
- #define A0 DSP_R (7)
- #define X0 DSP_R (8)
- #define X1 DSP_R (9)
- #define Y0 DSP_R (10)
- #define Y1 DSP_R (11)
- #define M0 DSP_R (12)
- #define A1G DSP_R (13)
- #define M1 DSP_R (14)
- #define A0G DSP_R (15)
- /* DSP_R (16) / DSP_GRD (16) are used as a fake destination for pcmp. */
- #define MOD_ME DSP_GRD (17)
- #define MOD_DELTA DSP_GRD (18)
- #define FP_OP(n, OP, m) \
- { \
- if (FPSCR_PR) \
- { \
- if (((n) & 1) || ((m) & 1)) \
- RAISE_EXCEPTION (SIGILL); \
- else \
- SET_DR (n, (DR (n) OP DR (m))); \
- } \
- else \
- SET_FR (n, (FR (n) OP FR (m))); \
- } while (0)
- #define FP_UNARY(n, OP) \
- { \
- if (FPSCR_PR) \
- { \
- if ((n) & 1) \
- RAISE_EXCEPTION (SIGILL); \
- else \
- SET_DR (n, (OP (DR (n)))); \
- } \
- else \
- SET_FR (n, (OP (FR (n)))); \
- } while (0)
- #define FP_CMP(n, OP, m) \
- { \
- if (FPSCR_PR) \
- { \
- if (((n) & 1) || ((m) & 1)) \
- RAISE_EXCEPTION (SIGILL); \
- else \
- SET_SR_T (DR (n) OP DR (m)); \
- } \
- else \
- SET_SR_T (FR (n) OP FR (m)); \
- } while (0)
- static void
- set_sr (int new_sr)
- {
- /* do we need to swap banks */
- int old_gpr = SR_MD && SR_RB;
- int new_gpr = (new_sr & SR_MASK_MD) && (new_sr & SR_MASK_RB);
- if (old_gpr != new_gpr)
- {
- int i, tmp;
- for (i = 0; i < 8; i++)
- {
- tmp = saved_state.asregs.bank[i];
- saved_state.asregs.bank[i] = saved_state.asregs.regs[i];
- saved_state.asregs.regs[i] = tmp;
- }
- }
- saved_state.asregs.sr = new_sr;
- SET_MOD (MOD);
- }
- static INLINE void
- wlat_fast (unsigned char *memory, int x, int value, int maskl)
- {
- int v = value;
- unsigned int *p = (unsigned int *) (memory + x);
- WRITE_BUSERROR (x, maskl, v, process_wlat_addr);
- *p = v;
- }
- static INLINE void
- wwat_fast (unsigned char *memory, int x, int value, int maskw, int endianw)
- {
- int v = value;
- unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
- WRITE_BUSERROR (x, maskw, v, process_wwat_addr);
- *p = v;
- }
- static INLINE void
- wbat_fast (unsigned char *memory, int x, int value, int maskb)
- {
- unsigned char *p = memory + (x ^ endianb);
- WRITE_BUSERROR (x, maskb, value, process_wbat_addr);
- p[0] = value;
- }
- /* Read functions */
- static INLINE int
- rlat_fast (unsigned char *memory, int x, int maskl)
- {
- unsigned int *p = (unsigned int *) (memory + x);
- READ_BUSERROR (x, maskl, process_rlat_addr);
- return *p;
- }
- static INLINE int
- rwat_fast (unsigned char *memory, int x, int maskw, int endianw)
- {
- unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
- READ_BUSERROR (x, maskw, process_rwat_addr);
- return *p;
- }
- static INLINE int
- riat_fast (unsigned char *insn_ptr, int endianw)
- {
- unsigned short *p = (unsigned short *) ((uintptr_t) insn_ptr ^ endianw);
- return *p;
- }
- static INLINE int
- rbat_fast (unsigned char *memory, int x, int maskb)
- {
- unsigned char *p = memory + (x ^ endianb);
- READ_BUSERROR (x, maskb, process_rbat_addr);
- return *p;
- }
- #define RWAT(x) (rwat_fast (memory, x, maskw, endianw))
- #define RLAT(x) (rlat_fast (memory, x, maskl))
- #define RBAT(x) (rbat_fast (memory, x, maskb))
- #define RIAT(p) (riat_fast ((p), endianw))
- #define WWAT(x,v) (wwat_fast (memory, x, v, maskw, endianw))
- #define WLAT(x,v) (wlat_fast (memory, x, v, maskl))
- #define WBAT(x,v) (wbat_fast (memory, x, v, maskb))
- #define RUWAT(x) (RWAT (x) & 0xffff)
- #define RSWAT(x) ((short) (RWAT (x)))
- #define RSLAT(x) ((long) (RLAT (x)))
- #define RSBAT(x) (SEXT (RBAT (x)))
- #define RDAT(x, n) (do_rdat (memory, (x), (n), (maskl)))
- static int
- do_rdat (unsigned char *memory, int x, int n, int maskl)
- {
- int f0;
- int f1;
- int i = (n & 1);
- int j = (n & ~1);
- f0 = rlat_fast (memory, x + 0, maskl);
- f1 = rlat_fast (memory, x + 4, maskl);
- saved_state.asregs.fregs[i].i[(j + 0)] = f0;
- saved_state.asregs.fregs[i].i[(j + 1)] = f1;
- return 0;
- }
- #define WDAT(x, n) (do_wdat (memory, (x), (n), (maskl)))
- static int
- do_wdat (unsigned char *memory, int x, int n, int maskl)
- {
- int f0;
- int f1;
- int i = (n & 1);
- int j = (n & ~1);
- f0 = saved_state.asregs.fregs[i].i[(j + 0)];
- f1 = saved_state.asregs.fregs[i].i[(j + 1)];
- wlat_fast (memory, (x + 0), f0, maskl);
- wlat_fast (memory, (x + 4), f1, maskl);
- return 0;
- }
- static void
- process_wlat_addr (int addr, int value)
- {
- unsigned int *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 32, 3, value, );
- *ptr = value;
- }
- static void
- process_wwat_addr (int addr, int value)
- {
- unsigned short *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 16, 1, value, );
- *ptr = value;
- }
- static void
- process_wbat_addr (int addr, int value)
- {
- unsigned char *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 8, 0, value, );
- *ptr = value;
- }
- static int
- process_rlat_addr (int addr)
- {
- unsigned char *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -32, 3, -1, 0);
- return *ptr;
- }
- static int
- process_rwat_addr (int addr)
- {
- unsigned char *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -16, 1, -1, 0);
- return *ptr;
- }
- static int
- process_rbat_addr (int addr)
- {
- unsigned char *ptr;
- PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -8, 0, -1, 0);
- return *ptr;
- }
- #define SEXT(x) (((x & 0xff) ^ (~0x7f))+0x80)
- #define SEXT12(x) (((x & 0xfff) ^ 0x800) - 0x800)
- #define SEXTW(y) ((int) ((short) y))
- #if 0
- #define SEXT32(x) ((int) ((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1)
- #else
- #define SEXT32(x) ((int) (x))
- #endif
- #define SIGN32(x) (SEXT32 (x) >> 31)
- /* convert pointer from target to host value. */
- #define PT2H(x) ((x) + memory)
- /* convert pointer from host to target value. */
- #define PH2T(x) ((x) - memory)
- #define SKIP_INSN(p) ((p) += ((RIAT (p) & 0xfc00) == 0xf800 ? 4 : 2))
- #define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip);
- static int in_delay_slot = 0;
- #define Delay_Slot(TEMPPC) iword = RIAT (TEMPPC); in_delay_slot = 1; goto top;
- #define CHECK_INSN_PTR(p) \
- do { \
- if (saved_state.asregs.exception || PH2T (p) & maskw) \
- saved_state.asregs.insn_end = 0; \
- else if (p < loop.end) \
- saved_state.asregs.insn_end = loop.end; \
- else \
- saved_state.asregs.insn_end = mem_end; \
- } while (0)
- #ifdef ACE_FAST
- #define MA(n)
- #define L(x)
- #define TL(x)
- #define TB(x)
- #else
- #define MA(n) \
- do { memstalls += ((((uintptr_t) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
- #define L(x) thislock = x;
- #define TL(x) if ((x) == prevlock) stalls++;
- #define TB(x,y) if ((x) == prevlock || (y) == prevlock) stalls++;
- #endif
- #if defined(__GO32__)
- int sim_memory_size = 19;
- #else
- int sim_memory_size = 30;
- #endif
- static int sim_profile_size = 17;
- static int nsamples;
- #undef TB
- #define TB(x,y)
- #define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */
- #define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */
- #define SCR1 (0x05FFFECA) /* Channel 1 serial control register */
- #define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */
- #define SSR1 (0x05FFFECC) /* Channel 1 serial status register */
- #define RDR1 (0x05FFFECD) /* Channel 1 receive data register */
- #define SCI_RDRF 0x40 /* Recieve data register full */
- #define SCI_TDRE 0x80 /* Transmit data register empty */
- static int
- IOMEM (int addr, int write, int value)
- {
- if (write)
- {
- switch (addr)
- {
- case TDR1:
- if (value != '\r')
- {
- putchar (value);
- fflush (stdout);
- }
- break;
- }
- }
- else
- {
- switch (addr)
- {
- case RDR1:
- return getchar ();
- }
- }
- return 0;
- }
- static int
- get_now (void)
- {
- return time (NULL);
- }
- static int
- now_persec (void)
- {
- return 1;
- }
- static FILE *profile_file;
- static INLINE unsigned
- swap (unsigned n)
- {
- if (endianb)
- n = (n << 24 | (n & 0xff00) << 8
- | (n & 0xff0000) >> 8 | (n & 0xff000000) >> 24);
- return n;
- }
- static INLINE unsigned short
- swap16 (unsigned short n)
- {
- if (endianb)
- n = n << 8 | (n & 0xff00) >> 8;
- return n;
- }
- static void
- swapout (int n)
- {
- if (profile_file)
- {
- union { char b[4]; int n; } u;
- u.n = swap (n);
- fwrite (u.b, 4, 1, profile_file);
- }
- }
- static void
- swapout16 (int n)
- {
- union { char b[4]; int n; } u;
- u.n = swap16 (n);
- fwrite (u.b, 2, 1, profile_file);
- }
- /* Turn a pointer in a register into a pointer into real memory. */
- static char *
- ptr (int x)
- {
- return (char *) (x + saved_state.asregs.memory);
- }
- /* STR points to a zero-terminated string in target byte order. Return
- the number of bytes that need to be converted to host byte order in order
- to use this string as a zero-terminated string on the host.
- (Not counting the rounding up needed to operate on entire words.) */
- static int
- strswaplen (int str)
- {
- unsigned char *memory = saved_state.asregs.memory;
- int start, end;
- int endian = endianb;
- if (! endian)
- return 0;
- end = str;
- for (end = str; memory[end ^ endian]; end++) ;
- return end - str + 1;
- }
- static void
- strnswap (int str, int len)
- {
- int *start, *end;
- if (! endianb || ! len)
- return;
- start = (int *) ptr (str & ~3);
- end = (int *) ptr (str + len);
- do
- {
- int old = *start;
- *start = (old << 24 | (old & 0xff00) << 8
- | (old & 0xff0000) >> 8 | (old & 0xff000000) >> 24);
- start++;
- }
- while (start < end);
- }
- /* Simulate a monitor trap, put the result into r0 and errno into r1
- return offset by which to adjust pc. */
- static int
- trap (SIM_DESC sd, int i, int *regs, unsigned char *insn_ptr,
- unsigned char *memory, int maskl, int maskw, int endianw)
- {
- host_callback *callback = STATE_CALLBACK (sd);
- char **prog_argv = STATE_PROG_ARGV (sd);
- switch (i)
- {
- case 1:
- printf ("%c", regs[0]);
- break;
- case 2:
- raise_exception (SIGQUIT);
- break;
- case 3: /* FIXME: for backwards compat, should be removed */
- case 33:
- {
- unsigned int countp = * (unsigned int *) (insn_ptr + 4);
- WLAT (countp, RLAT (countp) + 1);
- return 6;
- }
- case 34:
- {
- int perrno = errno;
- errno = 0;
- switch (regs[4])
- {
- #if !defined(__GO32__) && !defined(_WIN32)
- case TARGET_NEWLIB_SH_SYS_fork:
- regs[0] = fork ();
- break;
- /* This would work only if endianness matched between host and target.
- Besides, it's quite dangerous. */
- #if 0
- case TARGET_NEWLIB_SH_SYS_execve:
- regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]),
- (char **) ptr (regs[7]));
- break;
- case TARGET_NEWLIB_SH_SYS_execv:
- regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), 0);
- break;
- #endif
- case TARGET_NEWLIB_SH_SYS_pipe:
- {
- regs[0] = (BUSERROR (regs[5], maskl)
- ? -EINVAL
- : pipe ((int *) ptr (regs[5])));
- }
- break;
- case TARGET_NEWLIB_SH_SYS_wait:
- regs[0] = wait ((int *) ptr (regs[5]));
- break;
- #endif /* !defined(__GO32__) && !defined(_WIN32) */
- case TARGET_NEWLIB_SH_SYS_read:
- strnswap (regs[6], regs[7]);
- regs[0]
- = callback->read (callback, regs[5], ptr (regs[6]), regs[7]);
- strnswap (regs[6], regs[7]);
- break;
- case TARGET_NEWLIB_SH_SYS_write:
- strnswap (regs[6], regs[7]);
- if (regs[5] == 1)
- regs[0] = (int) callback->write_stdout (callback,
- ptr (regs[6]), regs[7]);
- else
- regs[0] = (int) callback->write (callback, regs[5],
- ptr (regs[6]), regs[7]);
- strnswap (regs[6], regs[7]);
- break;
- case TARGET_NEWLIB_SH_SYS_lseek:
- regs[0] = callback->lseek (callback,regs[5], regs[6], regs[7]);
- break;
- case TARGET_NEWLIB_SH_SYS_close:
- regs[0] = callback->close (callback,regs[5]);
- break;
- case TARGET_NEWLIB_SH_SYS_open:
- {
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- regs[0] = callback->open (callback, ptr (regs[5]), regs[6]);
- strnswap (regs[5], len);
- break;
- }
- case TARGET_NEWLIB_SH_SYS_exit:
- /* EXIT - caller can look in r5 to work out the reason */
- raise_exception (SIGQUIT);
- regs[0] = regs[5];
- break;
- case TARGET_NEWLIB_SH_SYS_stat: /* added at hmsi */
- /* stat system call */
- {
- struct stat host_stat;
- int buf;
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- regs[0] = stat (ptr (regs[5]), &host_stat);
- strnswap (regs[5], len);
- buf = regs[6];
- WWAT (buf, host_stat.st_dev);
- buf += 2;
- WWAT (buf, host_stat.st_ino);
- buf += 2;
- WLAT (buf, host_stat.st_mode);
- buf += 4;
- WWAT (buf, host_stat.st_nlink);
- buf += 2;
- WWAT (buf, host_stat.st_uid);
- buf += 2;
- WWAT (buf, host_stat.st_gid);
- buf += 2;
- WWAT (buf, host_stat.st_rdev);
- buf += 2;
- WLAT (buf, host_stat.st_size);
- buf += 4;
- WLAT (buf, host_stat.st_atime);
- buf += 4;
- WLAT (buf, 0);
- buf += 4;
- WLAT (buf, host_stat.st_mtime);
- buf += 4;
- WLAT (buf, 0);
- buf += 4;
- WLAT (buf, host_stat.st_ctime);
- buf += 4;
- WLAT (buf, 0);
- buf += 4;
- WLAT (buf, 0);
- buf += 4;
- WLAT (buf, 0);
- buf += 4;
- }
- break;
- #ifndef _WIN32
- case TARGET_NEWLIB_SH_SYS_chown:
- {
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- regs[0] = chown (ptr (regs[5]), regs[6], regs[7]);
- strnswap (regs[5], len);
- break;
- }
- #endif /* _WIN32 */
- case TARGET_NEWLIB_SH_SYS_chmod:
- {
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- regs[0] = chmod (ptr (regs[5]), regs[6]);
- strnswap (regs[5], len);
- break;
- }
- case TARGET_NEWLIB_SH_SYS_utime:
- {
- /* Cast the second argument to void *, to avoid type mismatch
- if a prototype is present. */
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- #ifdef HAVE_UTIME_H
- regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6]));
- #else
- errno = ENOSYS;
- regs[0] = -1;
- #endif
- strnswap (regs[5], len);
- break;
- }
- case TARGET_NEWLIB_SH_SYS_argc:
- regs[0] = countargv (prog_argv);
- break;
- case TARGET_NEWLIB_SH_SYS_argnlen:
- if (regs[5] < countargv (prog_argv))
- regs[0] = strlen (prog_argv[regs[5]]);
- else
- regs[0] = -1;
- break;
- case TARGET_NEWLIB_SH_SYS_argn:
- if (regs[5] < countargv (prog_argv))
- {
- /* Include the termination byte. */
- int i = strlen (prog_argv[regs[5]]) + 1;
- regs[0] = sim_write (0, regs[6], (void *) prog_argv[regs[5]], i);
- }
- else
- regs[0] = -1;
- break;
- case TARGET_NEWLIB_SH_SYS_time:
- regs[0] = get_now ();
- break;
- case TARGET_NEWLIB_SH_SYS_ftruncate:
- regs[0] = callback->ftruncate (callback, regs[5], regs[6]);
- break;
- case TARGET_NEWLIB_SH_SYS_truncate:
- {
- int len = strswaplen (regs[5]);
- strnswap (regs[5], len);
- regs[0] = callback->truncate (callback, ptr (regs[5]), regs[6]);
- strnswap (regs[5], len);
- break;
- }
- default:
- regs[0] = -1;
- break;
- }
- regs[1] = callback->get_errno (callback);
- errno = perrno;
- }
- break;
- case 13: /* Set IBNR */
- IBNR = regs[0] & 0xffff;
- break;
- case 14: /* Set IBCR */
- IBCR = regs[0] & 0xffff;
- break;
- case 0xc3:
- case 255:
- raise_exception (SIGTRAP);
- if (i == 0xc3)
- return -2;
- break;
- }
- return 0;
- }
- static void
- div1 (int *R, int iRn2, int iRn1/*, int T*/)
- {
- unsigned long tmp0;
- unsigned char old_q, tmp1;
- old_q = Q;
- SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0));
- R[iRn1] <<= 1;
- R[iRn1] |= (unsigned long) T;
- if (!old_q)
- {
- if (!M)
- {
- tmp0 = R[iRn1];
- R[iRn1] -= R[iRn2];
- tmp1 = (R[iRn1] > tmp0);
- if (!Q)
- SET_SR_Q (tmp1);
- else
- SET_SR_Q ((unsigned char) (tmp1 == 0));
- }
- else
- {
- tmp0 = R[iRn1];
- R[iRn1] += R[iRn2];
- tmp1 = (R[iRn1] < tmp0);
- if (!Q)
- SET_SR_Q ((unsigned char) (tmp1 == 0));
- else
- SET_SR_Q (tmp1);
- }
- }
- else
- {
- if (!M)
- {
- tmp0 = R[iRn1];
- R[iRn1] += R[iRn2];
- tmp1 = (R[iRn1] < tmp0);
- if (!Q)
- SET_SR_Q (tmp1);
- else
- SET_SR_Q ((unsigned char) (tmp1 == 0));
- }
- else
- {
- tmp0 = R[iRn1];
- R[iRn1] -= R[iRn2];
- tmp1 = (R[iRn1] > tmp0);
- if (!Q)
- SET_SR_Q ((unsigned char) (tmp1 == 0));
- else
- SET_SR_Q (tmp1);
- }
- }
- /*T = (Q == M);*/
- SET_SR_T (Q == M);
- /*return T;*/
- }
- static void
- dmul_s (uint32_t rm, uint32_t rn)
- {
- int64_t res = (int64_t)(int32_t)rm * (int64_t)(int32_t)rn;
- MACH = (uint32_t)((uint64_t)res >> 32);
- MACL = (uint32_t)res;
- }
- static void
- dmul_u (uint32_t rm, uint32_t rn)
- {
- uint64_t res = (uint64_t)(uint32_t)rm * (uint64_t)(uint32_t)rn;
- MACH = (uint32_t)(res >> 32);
- MACL = (uint32_t)res;
- }
- static void
- macw (int *regs, unsigned char *memory, int n, int m, int endianw)
- {
- long tempm, tempn;
- long prod, macl, sum;
- tempm=RSWAT (regs[m]); regs[m]+=2;
- tempn=RSWAT (regs[n]); regs[n]+=2;
- macl = MACL;
- prod = (long) (short) tempm * (long) (short) tempn;
- sum = prod + macl;
- if (S)
- {
- if ((~(prod ^ macl) & (sum ^ prod)) < 0)
- {
- /* MACH's lsb is a sticky overflow bit. */
- MACH |= 1;
- /* Store the smallest negative number in MACL if prod is
- negative, and the largest positive number otherwise. */
- sum = 0x7fffffff + (prod < 0);
- }
- }
- else
- {
- long mach;
- /* Add to MACH the sign extended product, and carry from low sum. */
- mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod);
- /* Sign extend at 10:th bit in MACH. */
- MACH = (mach & 0x1ff) | -(mach & 0x200);
- }
- MACL = sum;
- }
- static void
- macl (int *regs, unsigned char *memory, int n, int m)
- {
- long tempm, tempn;
- long macl, mach;
- long long ans;
- long long mac64;
- tempm = RSLAT (regs[m]);
- regs[m] += 4;
- tempn = RSLAT (regs[n]);
- regs[n] += 4;
- mach = MACH;
- macl = MACL;
- mac64 = ((long long) macl & 0xffffffff) |
- ((long long) mach & 0xffffffff) << 32;
- ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */
- mac64 += ans; /* Accumulate 64bit + 64 bit */
- macl = (long) (mac64 & 0xffffffff);
- mach = (long) ((mac64 >> 32) & 0xffffffff);
- if (S) /* Store only 48 bits of the result */
- {
- if (mach < 0) /* Result is negative */
- {
- mach = mach & 0x0000ffff; /* Mask higher 16 bits */
- mach |= 0xffff8000; /* Sign extend higher 16 bits */
- }
- else
- mach = mach & 0x00007fff; /* Postive Result */
- }
- MACL = macl;
- MACH = mach;
- }
- enum {
- B_BCLR = 0,
- B_BSET = 1,
- B_BST = 2,
- B_BLD = 3,
- B_BAND = 4,
- B_BOR = 5,
- B_BXOR = 6,
- B_BLDNOT = 11,
- B_BANDNOT = 12,
- B_BORNOT = 13,
-
- MOVB_RM = 0x0000,
- MOVW_RM = 0x1000,
- MOVL_RM = 0x2000,
- FMOV_RM = 0x3000,
- MOVB_MR = 0x4000,
- MOVW_MR = 0x5000,
- MOVL_MR = 0x6000,
- FMOV_MR = 0x7000,
- MOVU_BMR = 0x8000,
- MOVU_WMR = 0x9000,
- };
- /* Do extended displacement move instructions. */
- static void
- do_long_move_insn (int op, int disp12, int m, int n, int *thatlock)
- {
- int memstalls = 0;
- int thislock = *thatlock;
- int endianw = global_endianw;
- int *R = &(saved_state.asregs.regs[0]);
- unsigned char *memory = saved_state.asregs.memory;
- int maskb = ~((saved_state.asregs.msize - 1) & ~0);
- unsigned char *insn_ptr = PT2H (saved_state.asregs.pc);
- switch (op) {
- case MOVB_RM: /* signed */
- WBAT (disp12 * 1 + R[n], R[m]);
- break;
- case MOVW_RM:
- WWAT (disp12 * 2 + R[n], R[m]);
- break;
- case MOVL_RM:
- WLAT (disp12 * 4 + R[n], R[m]);
- break;
- case FMOV_RM: /* floating point */
- if (FPSCR_SZ)
- {
- MA (1);
- WDAT (R[n] + 8 * disp12, m);
- }
- else
- WLAT (R[n] + 4 * disp12, FI (m));
- break;
- case MOVB_MR:
- R[n] = RSBAT (disp12 * 1 + R[m]);
- L (n);
- break;
- case MOVW_MR:
- R[n] = RSWAT (disp12 * 2 + R[m]);
- L (n);
- break;
- case MOVL_MR:
- R[n] = RLAT (disp12 * 4 + R[m]);
- L (n);
- break;
- case FMOV_MR:
- if (FPSCR_SZ) {
- MA (1);
- RDAT (R[m] + 8 * disp12, n);
- }
- else
- SET_FI (n, RLAT (R[m] + 4 * disp12));
- break;
- case MOVU_BMR: /* unsigned */
- R[n] = RBAT (disp12 * 1 + R[m]);
- L (n);
- break;
- case MOVU_WMR:
- R[n] = RWAT (disp12 * 2 + R[m]);
- L (n);
- break;
- default:
- RAISE_EXCEPTION (SIGINT);
- exit (1);
- }
- saved_state.asregs.memstalls += memstalls;
- *thatlock = thislock;
- }
- /* Do binary logical bit-manipulation insns. */
- static void
- do_blog_insn (int imm, int addr, int binop,
- unsigned char *memory, int maskb)
- {
- int oldval = RBAT (addr);
- switch (binop) {
- case B_BCLR: /* bclr.b */
- WBAT (addr, oldval & ~imm);
- break;
- case B_BSET: /* bset.b */
- WBAT (addr, oldval | imm);
- break;
- case B_BST: /* bst.b */
- if (T)
- WBAT (addr, oldval | imm);
- else
- WBAT (addr, oldval & ~imm);
- break;
- case B_BLD: /* bld.b */
- SET_SR_T ((oldval & imm) != 0);
- break;
- case B_BAND: /* band.b */
- SET_SR_T (T && ((oldval & imm) != 0));
- break;
- case B_BOR: /* bor.b */
- SET_SR_T (T || ((oldval & imm) != 0));
- break;
- case B_BXOR: /* bxor.b */
- SET_SR_T (T ^ ((oldval & imm) != 0));
- break;
- case B_BLDNOT: /* bldnot.b */
- SET_SR_T ((oldval & imm) == 0);
- break;
- case B_BANDNOT: /* bandnot.b */
- SET_SR_T (T && ((oldval & imm) == 0));
- break;
- case B_BORNOT: /* bornot.b */
- SET_SR_T (T || ((oldval & imm) == 0));
- break;
- }
- }
- static float
- fsca_s (int in, double (*f) (double))
- {
- double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
- double result = (*f) (rad);
- double error, upper, lower, frac;
- int exp;
- /* Search the value with the maximum error that is still within the
- architectural spec. */
- error = ldexp (1., -21);
- /* compensate for calculation inaccuracy by reducing error. */
- error = error - ldexp (1., -50);
- upper = result + error;
- frac = frexp (upper, &exp);
- upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
- lower = result - error;
- frac = frexp (lower, &exp);
- lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
- return abs (upper - result) >= abs (lower - result) ? upper : lower;
- }
- static float
- fsrra_s (float in)
- {
- double result = 1. / sqrt (in);
- int exp;
- double frac, upper, lower, error, eps;
- /* refine result */
- result = result - (result * result * in - 1) * 0.5 * result;
- /* Search the value with the maximum error that is still within the
- architectural spec. */
- frac = frexp (result, &exp);
- frac = ldexp (frac, 24);
- error = 4.0; /* 1 << 24-1-21 */
- /* use eps to compensate for possible 1 ulp error in our 'exact' result. */
- eps = ldexp (1., -29);
- upper = floor (frac + error - eps);
- if (upper > 16777216.)
- upper = floor ((frac + error - eps) * 0.5) * 2.;
- lower = ceil ((frac - error + eps) * 2) * .5;
- if (lower > 8388608.)
- lower = ceil (frac - error + eps);
- upper = ldexp (upper, exp - 24);
- lower = ldexp (lower, exp - 24);
- return upper - result >= result - lower ? upper : lower;
- }
- /* GET_LOOP_BOUNDS {EXTENDED}
- These two functions compute the actual starting and ending point
- of the repeat loop, based on the RS and RE registers (repeat start,
- repeat stop). The extended version is called for LDRC, and the
- regular version is called for SETRC. The difference is that for
- LDRC, the loop start and end instructions are literally the ones
- pointed to by RS and RE -- for SETRC, they're not (see docs). */
- static struct loop_bounds
- get_loop_bounds_ext (int rs, int re, unsigned char *memory,
- unsigned char *mem_end, int maskw, int endianw)
- {
- struct loop_bounds loop;
- /* FIXME: should I verify RS < RE? */
- loop.start = PT2H (RS); /* FIXME not using the params? */
- loop.end = PT2H (RE & ~1); /* Ignore bit 0 of RE. */
- SKIP_INSN (loop.end);
- if (loop.end >= mem_end)
- loop.end = PT2H (0);
- return loop;
- }
- static struct loop_bounds
- get_loop_bounds (int rs, int re, unsigned char *memory, unsigned char *mem_end,
- int maskw, int endianw)
- {
- struct loop_bounds loop;
- if (SR_RC)
- {
- if (RS >= RE)
- {
- loop.start = PT2H (RE - 4);
- SKIP_INSN (loop.start);
- loop.end = loop.start;
- if (RS - RE == 0)
- SKIP_INSN (loop.end);
- if (RS - RE <= 2)
- SKIP_INSN (loop.end);
- SKIP_INSN (loop.end);
- }
- else
- {
- loop.start = PT2H (RS);
- loop.end = PT2H (RE - 4);
- SKIP_INSN (loop.end);
- SKIP_INSN (loop.end);
- SKIP_INSN (loop.end);
- SKIP_INSN (loop.end);
- }
- if (loop.end >= mem_end)
- loop.end = PT2H (0);
- }
- else
- loop.end = PT2H (0);
- return loop;
- }
- static void ppi_insn ();
- #include "ppi.c"
- /* Provide calloc / free versions that use an anonymous mmap. This can
- significantly cut the start-up time when a large simulator memory is
- required, because pages are only zeroed on demand. */
- #ifdef MAP_ANONYMOUS
- static void *
- mcalloc (size_t nmemb, size_t size)
- {
- void *page;
- if (nmemb != 1)
- size *= nmemb;
- return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
- }
- #define mfree(start,length) munmap ((start), (length))
- #else
- #define mcalloc calloc
- #define mfree(start,length) free(start)
- #endif
- /* Set the memory size to the power of two provided. */
- static void
- sim_size (int power)
- {
- sim_memory_size = power;
- if (saved_state.asregs.memory)
- {
- mfree (saved_state.asregs.memory, saved_state.asregs.msize);
- }
- saved_state.asregs.msize = 1 << power;
- saved_state.asregs.memory =
- (unsigned char *) mcalloc (1, saved_state.asregs.msize);
- if (!saved_state.asregs.memory)
- {
- fprintf (stderr,
- "Not enough VM for simulation of %d bytes of RAM\n",
- saved_state.asregs.msize);
- saved_state.asregs.msize = 1;
- saved_state.asregs.memory = (unsigned char *) mcalloc (1, 1);
- }
- }
- static void
- init_dsp (struct bfd *abfd)
- {
- int was_dsp = target_dsp;
- unsigned long mach = bfd_get_mach (abfd);
- if (mach == bfd_mach_sh_dsp ||
- mach == bfd_mach_sh4al_dsp ||
- mach == bfd_mach_sh3_dsp)
- {
- int ram_area_size, xram_start, yram_start;
- int new_select;
- target_dsp = 1;
- if (mach == bfd_mach_sh_dsp)
- {
- /* SH7410 (orig. sh-sdp):
- 4KB each for X & Y memory;
- On-chip X RAM 0x0800f000-0x0800ffff
- On-chip Y RAM 0x0801f000-0x0801ffff */
- xram_start = 0x0800f000;
- ram_area_size = 0x1000;
- }
- if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp)
- {
- /* SH7612:
- 8KB each for X & Y memory;
- On-chip X RAM 0x1000e000-0x1000ffff
- On-chip Y RAM 0x1001e000-0x1001ffff */
- xram_start = 0x1000e000;
- ram_area_size = 0x2000;
- }
- yram_start = xram_start + 0x10000;
- new_select = ~(ram_area_size - 1);
- if (saved_state.asregs.xyram_select != new_select)
- {
- saved_state.asregs.xyram_select = new_select;
- free (saved_state.asregs.xmem);
- free (saved_state.asregs.ymem);
- saved_state.asregs.xmem =
- (unsigned char *) calloc (1, ram_area_size);
- saved_state.asregs.ymem =
- (unsigned char *) calloc (1, ram_area_size);
- /* Disable use of X / Y mmeory if not allocated. */
- if (! saved_state.asregs.xmem || ! saved_state.asregs.ymem)
- {
- saved_state.asregs.xyram_select = 0;
- if (saved_state.asregs.xmem)
- free (saved_state.asregs.xmem);
- if (saved_state.asregs.ymem)
- free (saved_state.asregs.ymem);
- }
- }
- saved_state.asregs.xram_start = xram_start;
- saved_state.asregs.yram_start = yram_start;
- saved_state.asregs.xmem_offset = saved_state.asregs.xmem - xram_start;
- saved_state.asregs.ymem_offset = saved_state.asregs.ymem - yram_start;
- }
- else
- {
- target_dsp = 0;
- if (saved_state.asregs.xyram_select)
- {
- saved_state.asregs.xyram_select = 0;
- free (saved_state.asregs.xmem);
- free (saved_state.asregs.ymem);
- }
- }
- if (! saved_state.asregs.xyram_select)
- {
- saved_state.asregs.xram_start = 1;
- saved_state.asregs.yram_start = 1;
- }
- if (saved_state.asregs.regstack == NULL)
- saved_state.asregs.regstack =
- calloc (512, sizeof *saved_state.asregs.regstack);
- if (target_dsp != was_dsp)
- {
- int i, tmp;
- for (i = ARRAY_SIZE (sh_dsp_table) - 1; i >= 0; i--)
- {
- tmp = sh_jump_table[0xf000 + i];
- sh_jump_table[0xf000 + i] = sh_dsp_table[i];
- sh_dsp_table[i] = tmp;
- }
- }
- }
- static void
- init_pointers (void)
- {
- if (saved_state.asregs.msize != 1 << sim_memory_size)
- {
- sim_size (sim_memory_size);
- }
- if (saved_state.asregs.profile && !profile_file)
- {
- profile_file = fopen ("gmon.out", "wb");
- /* Seek to where to put the call arc data */
- nsamples = (1 << sim_profile_size);
- fseek (profile_file, nsamples * 2 + 12, 0);
- if (!profile_file)
- {
- fprintf (stderr, "Can't open gmon.out\n");
- }
- else
- {
- saved_state.asregs.profile_hist =
- (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64));
- }
- }
- }
- static void
- dump_profile (void)
- {
- unsigned int minpc;
- unsigned int maxpc;
- unsigned short *p;
- int i;
- p = saved_state.asregs.profile_hist;
- minpc = 0;
- maxpc = (1 << sim_profile_size);
- fseek (profile_file, 0L, 0);
- swapout (minpc << PROFILE_SHIFT);
- swapout (maxpc << PROFILE_SHIFT);
- swapout (nsamples * 2 + 12);
- for (i = 0; i < nsamples; i++)
- swapout16 (saved_state.asregs.profile_hist[i]);
- }
- static void
- gotcall (int from, int to)
- {
- swapout (from);
- swapout (to);
- swapout (1);
- }
- #define MMASKB ((saved_state.asregs.msize -1) & ~0)
- void
- sim_resume (SIM_DESC sd, int step, int siggnal)
- {
- register unsigned char *insn_ptr;
- unsigned char *mem_end;
- struct loop_bounds loop;
- register int cycles = 0;
- register int stalls = 0;
- register int memstalls = 0;
- register int insts = 0;
- register int prevlock;
- #if 1
- int thislock;
- #else
- register int thislock;
- #endif
- register unsigned int doprofile;
- register int pollcount = 0;
- /* endianw is used for every insn fetch, hence it makes sense to cache it.
- endianb is used less often. */
- register int endianw = global_endianw;
- int tick_start = get_now ();
- void (*prev_fpe) ();
- register unsigned short *jump_table = sh_jump_table;
- register int *R = &(saved_state.asregs.regs[0]);
- /*register int T;*/
- #ifndef PR
- register int PR;
- #endif
- register int maskb = ~((saved_state.asregs.msize - 1) & ~0);
- register int maskw = ~((saved_state.asregs.msize - 1) & ~1);
- register int maskl = ~((saved_state.asregs.msize - 1) & ~3);
- register unsigned char *memory;
- register unsigned int sbit = ((unsigned int) 1 << 31);
- prev_fpe = signal (SIGFPE, SIG_IGN);
- init_pointers ();
- saved_state.asregs.exception = 0;
- memory = saved_state.asregs.memory;
- mem_end = memory + saved_state.asregs.msize;
- if (RE & 1)
- loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);
- else
- loop = get_loop_bounds (RS, RE, memory, mem_end, maskw, endianw);
- insn_ptr = PT2H (saved_state.asregs.pc);
- CHECK_INSN_PTR (insn_ptr);
- #ifndef PR
- PR = saved_state.asregs.pr;
- #endif
- /*T = GET_SR () & SR_MASK_T;*/
- prevlock = saved_state.asregs.prevlock;
- thislock = saved_state.asregs.thislock;
- doprofile = saved_state.asregs.profile;
- /* If profiling not enabled, disable it by asking for
- profiles infrequently. */
- if (doprofile == 0)
- doprofile = ~0;
- loop:
- if (step && insn_ptr < saved_state.asregs.insn_end)
- {
- if (saved_state.asregs.exception)
- /* This can happen if we've already been single-stepping and
- encountered a loop end. */
- saved_state.asregs.insn_end = insn_ptr;
- else
- {
- saved_state.asregs.exception = SIGTRAP;
- saved_state.asregs.insn_end = insn_ptr + 2;
- }
- }
- while (insn_ptr < saved_state.asregs.insn_end)
- {
- register unsigned int iword = RIAT (insn_ptr);
- register unsigned int ult;
- register unsigned char *nip = insn_ptr + 2;
- #ifndef ACE_FAST
- insts++;
- #endif
- top:
- #include "code.c"
- in_delay_slot = 0;
- insn_ptr = nip;
- if (--pollcount < 0)
- {
- host_callback *callback = STATE_CALLBACK (sd);
- pollcount = POLL_QUIT_INTERVAL;
- if ((*callback->poll_quit) != NULL
- && (*callback->poll_quit) (callback))
- {
- sim_stop (sd);
- }
- }
- #ifndef ACE_FAST
- prevlock = thislock;
- thislock = 30;
- cycles++;
- if (cycles >= doprofile)
- {
- saved_state.asregs.cycles += doprofile;
- cycles -= doprofile;
- if (saved_state.asregs.profile_hist)
- {
- int n = PH2T (insn_ptr) >> PROFILE_SHIFT;
- if (n < nsamples)
- {
- int i = saved_state.asregs.profile_hist[n];
- if (i < 65000)
- saved_state.asregs.profile_hist[n] = i + 1;
- }
- }
- }
- #endif
- }
- if (saved_state.asregs.insn_end == loop.end)
- {
- saved_state.asregs.sr += SR_RC_INCREMENT;
- if (SR_RC)
- insn_ptr = loop.start;
- else
- {
- saved_state.asregs.insn_end = mem_end;
- loop.end = PT2H (0);
- }
- goto loop;
- }
- if (saved_state.asregs.exception == SIGILL
- || saved_state.asregs.exception == SIGBUS)
- {
- insn_ptr -= 2;
- }
- /* Check for SIGBUS due to insn fetch. */
- else if (! saved_state.asregs.exception)
- saved_state.asregs.exception = SIGBUS;
- saved_state.asregs.ticks += get_now () - tick_start;
- saved_state.asregs.cycles += cycles;
- saved_state.asregs.stalls += stalls;
- saved_state.asregs.memstalls += memstalls;
- saved_state.asregs.insts += insts;
- saved_state.asregs.pc = PH2T (insn_ptr);
- #ifndef PR
- saved_state.asregs.pr = PR;
- #endif
- saved_state.asregs.prevlock = prevlock;
- saved_state.asregs.thislock = thislock;
- if (profile_file)
- {
- dump_profile ();
- }
- signal (SIGFPE, prev_fpe);
- }
- int
- sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
- {
- int i;
- init_pointers ();
- for (i = 0; i < size; i++)
- {
- saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb] = buffer[i];
- }
- return size;
- }
- int
- sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
- {
- int i;
- init_pointers ();
- for (i = 0; i < size; i++)
- {
- buffer[i] = saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb];
- }
- return size;
- }
- static int gdb_bank_number;
- enum {
- REGBANK_MACH = 15,
- REGBANK_IVN = 16,
- REGBANK_PR = 17,
- REGBANK_GBR = 18,
- REGBANK_MACL = 19
- };
- static int
- sh_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
- {
- unsigned val;
- init_pointers ();
- val = swap (* (int *) memory);
- switch (rn)
- {
- case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
- case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
- case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
- case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
- case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
- case SIM_SH_R15_REGNUM:
- saved_state.asregs.regs[rn] = val;
- break;
- case SIM_SH_PC_REGNUM:
- saved_state.asregs.pc = val;
- break;
- case SIM_SH_PR_REGNUM:
- PR = val;
- break;
- case SIM_SH_GBR_REGNUM:
- GBR = val;
- break;
- case SIM_SH_VBR_REGNUM:
- VBR = val;
- break;
- case SIM_SH_MACH_REGNUM:
- MACH = val;
- break;
- case SIM_SH_MACL_REGNUM:
- MACL = val;
- break;
- case SIM_SH_SR_REGNUM:
- SET_SR (val);
- break;
- case SIM_SH_FPUL_REGNUM:
- FPUL = val;
- break;
- case SIM_SH_FPSCR_REGNUM:
- SET_FPSCR (val);
- break;
- case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
- case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
- case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
- case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
- case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
- case SIM_SH_FR15_REGNUM:
- SET_FI (rn - SIM_SH_FR0_REGNUM, val);
- break;
- case SIM_SH_DSR_REGNUM:
- DSR = val;
- break;
- case SIM_SH_A0G_REGNUM:
- A0G = val;
- break;
- case SIM_SH_A0_REGNUM:
- A0 = val;
- break;
- case SIM_SH_A1G_REGNUM:
- A1G = val;
- break;
- case SIM_SH_A1_REGNUM:
- A1 = val;
- break;
- case SIM_SH_M0_REGNUM:
- M0 = val;
- break;
- case SIM_SH_M1_REGNUM:
- M1 = val;
- break;
- case SIM_SH_X0_REGNUM:
- X0 = val;
- break;
- case SIM_SH_X1_REGNUM:
- X1 = val;
- break;
- case SIM_SH_Y0_REGNUM:
- Y0 = val;
- break;
- case SIM_SH_Y1_REGNUM:
- Y1 = val;
- break;
- case SIM_SH_MOD_REGNUM:
- SET_MOD (val);
- break;
- case SIM_SH_RS_REGNUM:
- RS = val;
- break;
- case SIM_SH_RE_REGNUM:
- RE = val;
- break;
- case SIM_SH_SSR_REGNUM:
- SSR = val;
- break;
- case SIM_SH_SPC_REGNUM:
- SPC = val;
- break;
- /* The rn_bank idiosyncracies are not due to hardware differences, but to
- a weird aliasing naming scheme for sh3 / sh3e / sh4. */
- case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
- case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
- case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
- case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
- if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
- {
- rn -= SIM_SH_R0_BANK0_REGNUM;
- saved_state.asregs.regstack[gdb_bank_number].regs[rn] = val;
- }
- else
- if (SR_MD && SR_RB)
- Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) = val;
- else
- saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM] = val;
- break;
- case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
- case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
- case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
- case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
- if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
- {
- rn -= SIM_SH_R0_BANK1_REGNUM;
- saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8] = val;
- }
- else
- if (SR_MD && SR_RB)
- saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM] = val;
- else
- Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM) = val;
- break;
- case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
- case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
- case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
- case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
- SET_Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM, val);
- break;
- case SIM_SH_TBR_REGNUM:
- TBR = val;
- break;
- case SIM_SH_IBNR_REGNUM:
- IBNR = val;
- break;
- case SIM_SH_IBCR_REGNUM:
- IBCR = val;
- break;
- case SIM_SH_BANK_REGNUM:
- /* This is a pseudo-register maintained just for gdb.
- It tells us what register bank gdb would like to read/write. */
- gdb_bank_number = val;
- break;
- case SIM_SH_BANK_MACL_REGNUM:
- saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL] = val;
- break;
- case SIM_SH_BANK_GBR_REGNUM:
- saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR] = val;
- break;
- case SIM_SH_BANK_PR_REGNUM:
- saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR] = val;
- break;
- case SIM_SH_BANK_IVN_REGNUM:
- saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN] = val;
- break;
- case SIM_SH_BANK_MACH_REGNUM:
- saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH] = val;
- break;
- default:
- return 0;
- }
- return length;
- }
- static int
- sh_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
- {
- int val;
- init_pointers ();
- switch (rn)
- {
- case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
- case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
- case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
- case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
- case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
- case SIM_SH_R15_REGNUM:
- val = saved_state.asregs.regs[rn];
- break;
- case SIM_SH_PC_REGNUM:
- val = saved_state.asregs.pc;
- break;
- case SIM_SH_PR_REGNUM:
- val = PR;
- break;
- case SIM_SH_GBR_REGNUM:
- val = GBR;
- break;
- case SIM_SH_VBR_REGNUM:
- val = VBR;
- break;
- case SIM_SH_MACH_REGNUM:
- val = MACH;
- break;
- case SIM_SH_MACL_REGNUM:
- val = MACL;
- break;
- case SIM_SH_SR_REGNUM:
- val = GET_SR ();
- break;
- case SIM_SH_FPUL_REGNUM:
- val = FPUL;
- break;
- case SIM_SH_FPSCR_REGNUM:
- val = GET_FPSCR ();
- break;
- case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
- case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
- case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
- case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
- case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
- case SIM_SH_FR15_REGNUM:
- val = FI (rn - SIM_SH_FR0_REGNUM);
- break;
- case SIM_SH_DSR_REGNUM:
- val = DSR;
- break;
- case SIM_SH_A0G_REGNUM:
- val = SEXT (A0G);
- break;
- case SIM_SH_A0_REGNUM:
- val = A0;
- break;
- case SIM_SH_A1G_REGNUM:
- val = SEXT (A1G);
- break;
- case SIM_SH_A1_REGNUM:
- val = A1;
- break;
- case SIM_SH_M0_REGNUM:
- val = M0;
- break;
- case SIM_SH_M1_REGNUM:
- val = M1;
- break;
- case SIM_SH_X0_REGNUM:
- val = X0;
- break;
- case SIM_SH_X1_REGNUM:
- val = X1;
- break;
- case SIM_SH_Y0_REGNUM:
- val = Y0;
- break;
- case SIM_SH_Y1_REGNUM:
- val = Y1;
- break;
- case SIM_SH_MOD_REGNUM:
- val = MOD;
- break;
- case SIM_SH_RS_REGNUM:
- val = RS;
- break;
- case SIM_SH_RE_REGNUM:
- val = RE;
- break;
- case SIM_SH_SSR_REGNUM:
- val = SSR;
- break;
- case SIM_SH_SPC_REGNUM:
- val = SPC;
- break;
- /* The rn_bank idiosyncracies are not due to hardware differences, but to
- a weird aliasing naming scheme for sh3 / sh3e / sh4. */
- case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
- case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
- case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
- case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
- if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
- {
- rn -= SIM_SH_R0_BANK0_REGNUM;
- val = saved_state.asregs.regstack[gdb_bank_number].regs[rn];
- }
- else
- val = (SR_MD && SR_RB
- ? Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM)
- : saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM]);
- break;
- case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
- case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
- case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
- case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
- if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
- {
- rn -= SIM_SH_R0_BANK1_REGNUM;
- val = saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8];
- }
- else
- val = (! SR_MD || ! SR_RB
- ? Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM)
- : saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM]);
- break;
- case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
- case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
- case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
- case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
- val = Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM);
- break;
- case SIM_SH_TBR_REGNUM:
- val = TBR;
- break;
- case SIM_SH_IBNR_REGNUM:
- val = IBNR;
- break;
- case SIM_SH_IBCR_REGNUM:
- val = IBCR;
- break;
- case SIM_SH_BANK_REGNUM:
- /* This is a pseudo-register maintained just for gdb.
- It tells us what register bank gdb would like to read/write. */
- val = gdb_bank_number;
- break;
- case SIM_SH_BANK_MACL_REGNUM:
- val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL];
- break;
- case SIM_SH_BANK_GBR_REGNUM:
- val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR];
- break;
- case SIM_SH_BANK_PR_REGNUM:
- val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR];
- break;
- case SIM_SH_BANK_IVN_REGNUM:
- val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN];
- break;
- case SIM_SH_BANK_MACH_REGNUM:
- val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH];
- break;
- default:
- return 0;
- }
- * (int *) memory = swap (val);
- return length;
- }
- void
- sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
- {
- /* The SH simulator uses SIGQUIT to indicate that the program has
- exited, so we must check for it here and translate it to exit. */
- if (saved_state.asregs.exception == SIGQUIT)
- {
- *reason = sim_exited;
- *sigrc = saved_state.asregs.regs[5];
- }
- else
- {
- *reason = sim_stopped;
- *sigrc = saved_state.asregs.exception;
- }
- }
- void
- sim_info (SIM_DESC sd, int verbose)
- {
- double timetaken =
- (double) saved_state.asregs.ticks / (double) now_persec ();
- double virttime = saved_state.asregs.cycles / 36.0e6;
- sim_io_printf (sd, "\n\n# instructions executed %10d\n",
- saved_state.asregs.insts);
- sim_io_printf (sd, "# cycles %10d\n",
- saved_state.asregs.cycles);
- sim_io_printf (sd, "# pipeline stalls %10d\n",
- saved_state.asregs.stalls);
- sim_io_printf (sd, "# misaligned load/store %10d\n",
- saved_state.asregs.memstalls);
- sim_io_printf (sd, "# real time taken %10.4f\n", timetaken);
- sim_io_printf (sd, "# virtual time taken %10.4f\n", virttime);
- sim_io_printf (sd, "# profiling size %10d\n", sim_profile_size);
- sim_io_printf (sd, "# profiling frequency %10d\n",
- saved_state.asregs.profile);
- sim_io_printf (sd, "# profile maxpc %10x\n",
- (1 << sim_profile_size) << PROFILE_SHIFT);
- if (timetaken != 0)
- {
- sim_io_printf (sd, "# cycles/second %10d\n",
- (int) (saved_state.asregs.cycles / timetaken));
- sim_io_printf (sd, "# simulation ratio %10.4f\n",
- virttime / timetaken);
- }
- }
- static sim_cia
- sh_pc_get (sim_cpu *cpu)
- {
- return saved_state.asregs.pc;
- }
- static void
- sh_pc_set (sim_cpu *cpu, sim_cia pc)
- {
- saved_state.asregs.pc = pc;
- }
- static void
- free_state (SIM_DESC sd)
- {
- if (STATE_MODULES (sd) != NULL)
- sim_module_uninstall (sd);
- sim_cpu_free_all (sd);
- sim_state_free (sd);
- }
- SIM_DESC
- sim_open (SIM_OPEN_KIND kind, host_callback *cb,
- struct bfd *abfd, char * const *argv)
- {
- char * const *p;
- int i;
- union
- {
- int i;
- short s[2];
- char c[4];
- }
- mem_word;
- SIM_DESC sd = sim_state_alloc (kind, cb);
- SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
- /* Set default options before parsing user options. */
- current_alignment = STRICT_ALIGNMENT;
- cb->syscall_map = cb_sh_syscall_map;
- /* The cpu data is kept in a separately allocated chunk of memory. */
- if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* The parser will print an error message for us, so we silently return. */
- if (sim_parse_args (sd, argv) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* Check for/establish the a reference program image. */
- if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* Configure/verify the target byte order and other runtime
- configuration options. */
- if (sim_config (sd) != SIM_RC_OK)
- {
- sim_module_uninstall (sd);
- return 0;
- }
- if (sim_post_argv_init (sd) != SIM_RC_OK)
- {
- /* Uninstall the modules to avoid memory leaks,
- file descriptor leaks, etc. */
- sim_module_uninstall (sd);
- return 0;
- }
- /* CPU specific initialization. */
- for (i = 0; i < MAX_NR_PROCESSORS; ++i)
- {
- SIM_CPU *cpu = STATE_CPU (sd, i);
- CPU_REG_FETCH (cpu) = sh_reg_fetch;
- CPU_REG_STORE (cpu) = sh_reg_store;
- CPU_PC_FETCH (cpu) = sh_pc_get;
- CPU_PC_STORE (cpu) = sh_pc_set;
- }
- for (p = argv + 1; *p != NULL; ++p)
- {
- if (isdigit (**p))
- parse_and_set_memory_size (sd, *p);
- }
- if (abfd)
- init_dsp (abfd);
- for (i = 4; (i -= 2) >= 0; )
- mem_word.s[i >> 1] = i;
- global_endianw = mem_word.i >> (target_little_endian ? 0 : 16) & 0xffff;
- for (i = 4; --i >= 0; )
- mem_word.c[i] = i;
- endianb = mem_word.i >> (target_little_endian ? 0 : 24) & 0xff;
- return sd;
- }
- static void
- parse_and_set_memory_size (SIM_DESC sd, const char *str)
- {
- int n;
- n = strtol (str, NULL, 10);
- if (n > 0 && n <= 31)
- sim_memory_size = n;
- else
- sim_io_printf (sd, "Bad memory size %d; must be 1 to 31, inclusive\n", n);
- }
- SIM_RC
- sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
- char * const *argv, char * const *env)
- {
- /* Clear the registers. */
- memset (&saved_state, 0,
- (char*) &saved_state.asregs.end_of_registers - (char*) &saved_state);
- /* Set the PC. */
- if (prog_bfd != NULL)
- saved_state.asregs.pc = bfd_get_start_address (prog_bfd);
- /* Set the bfd machine type. */
- if (prog_bfd != NULL)
- saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
- if (prog_bfd != NULL)
- init_dsp (prog_bfd);
- return SIM_RC_OK;
- }
- void
- sim_do_command (SIM_DESC sd, const char *cmd)
- {
- const char *sms_cmd = "set-memory-size";
- int cmdsize;
- if (cmd == NULL || *cmd == '\0')
- {
- cmd = "help";
- }
- cmdsize = strlen (sms_cmd);
- if (strncmp (cmd, sms_cmd, cmdsize) == 0
- && strchr (" \t", cmd[cmdsize]) != NULL)
- {
- parse_and_set_memory_size (sd, cmd + cmdsize + 1);
- }
- else if (strcmp (cmd, "help") == 0)
- {
- sim_io_printf (sd, "List of SH simulator commands:\n\n");
- sim_io_printf (sd, "set-memory-size <n> -- Set the number of address bits to use\n");
- sim_io_printf (sd, "\n");
- }
- else
- {
- sim_io_printf (sd, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
- }
- }
|