123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155 |
- /* SH5 simulator support code
- Copyright (C) 2000-2015 Free Software Foundation, Inc.
- Contributed by Red Hat, Inc.
- This file is part of the GNU simulators.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #define WANT_CPU
- #define WANT_CPU_SH64
- #include "sim-main.h"
- #include "sim-fpu.h"
- #include "cgen-mem.h"
- #include "cgen-ops.h"
- #include "gdb/callback.h"
- #include "defs-compact.h"
- #include "bfd.h"
- /* From include/gdb/. */
- #include "gdb/sim-sh.h"
- #define SYS_exit 1
- #define SYS_read 3
- #define SYS_write 4
- #define SYS_open 5
- #define SYS_close 6
- #define SYS_lseek 19
- #define SYS_time 23
- #define SYS_argc 172
- #define SYS_argnlen 173
- #define SYS_argn 174
- IDESC * sh64_idesc_media;
- IDESC * sh64_idesc_compact;
- BI
- sh64_endian (SIM_CPU *current_cpu)
- {
- return (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN);
- }
- SF
- sh64_fldi0 (SIM_CPU *current_cpu)
- {
- SF result;
- sim_fpu_to32 (&result, &sim_fpu_zero);
- return result;
- }
- SF
- sh64_fldi1 (SIM_CPU *current_cpu)
- {
- SF result;
- sim_fpu_to32 (&result, &sim_fpu_one);
- return result;
- }
- DF
- sh64_fabsd(SIM_CPU *current_cpu, DF drgh)
- {
- DF result;
- sim_fpu f, fres;
- sim_fpu_64to (&f, drgh);
- sim_fpu_abs (&fres, &f);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fabss(SIM_CPU *current_cpu, SF frgh)
- {
- SF result;
- sim_fpu f, fres;
- sim_fpu_32to (&f, frgh);
- sim_fpu_abs (&fres, &f);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_faddd(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- DF result;
- sim_fpu f1, f2, fres;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- sim_fpu_add (&fres, &f1, &f2);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fadds(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- SF result;
- sim_fpu f1, f2, fres;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- sim_fpu_add (&fres, &f1, &f2);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- BI
- sh64_fcmpeqd(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- sim_fpu f1, f2;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- return sim_fpu_is_eq (&f1, &f2);
- }
- BI
- sh64_fcmpeqs(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- sim_fpu f1, f2;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- return sim_fpu_is_eq (&f1, &f2);
- }
- BI
- sh64_fcmpged(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- sim_fpu f1, f2;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- return sim_fpu_is_ge (&f1, &f2);
- }
- BI
- sh64_fcmpges(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- sim_fpu f1, f2;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- return sim_fpu_is_ge (&f1, &f2);
- }
- BI
- sh64_fcmpgtd(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- sim_fpu f1, f2;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- return sim_fpu_is_gt (&f1, &f2);
- }
- BI
- sh64_fcmpgts(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- sim_fpu f1, f2;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- return sim_fpu_is_gt (&f1, &f2);
- }
- BI
- sh64_fcmpund(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- sim_fpu f1, f2;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2));
- }
- BI
- sh64_fcmpuns(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- sim_fpu f1, f2;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2));
- }
- SF
- sh64_fcnvds(SIM_CPU *current_cpu, DF drgh)
- {
- union {
- unsigned long long ll;
- double d;
- } f1;
- union {
- unsigned long l;
- float f;
- } f2;
- f1.ll = drgh;
- f2.f = (float) f1.d;
-
- return (SF) f2.l;
- }
- DF
- sh64_fcnvsd(SIM_CPU *current_cpu, SF frgh)
- {
- DF result;
- sim_fpu f;
- sim_fpu_32to (&f, frgh);
- sim_fpu_to64 (&result, &f);
- return result;
- }
- DF
- sh64_fdivd(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- DF result;
- sim_fpu f1, f2, fres;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- sim_fpu_div (&fres, &f1, &f2);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fdivs(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- SF result;
- sim_fpu f1, f2, fres;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- sim_fpu_div (&fres, &f1, &f2);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_floatld(SIM_CPU *current_cpu, SF frgh)
- {
- DF result;
- sim_fpu f;
- sim_fpu_i32to (&f, frgh, sim_fpu_round_default);
- sim_fpu_to64 (&result, &f);
- return result;
- }
- SF
- sh64_floatls(SIM_CPU *current_cpu, SF frgh)
- {
- SF result;
- sim_fpu f;
- sim_fpu_i32to (&f, frgh, sim_fpu_round_default);
- sim_fpu_to32 (&result, &f);
- return result;
- }
- DF
- sh64_floatqd(SIM_CPU *current_cpu, DF drgh)
- {
- DF result;
- sim_fpu f;
- sim_fpu_i64to (&f, drgh, sim_fpu_round_default);
- sim_fpu_to64 (&result, &f);
- return result;
- }
- SF
- sh64_floatqs(SIM_CPU *current_cpu, DF drgh)
- {
- SF result;
- sim_fpu f;
- sim_fpu_i64to (&f, drgh, sim_fpu_round_default);
- sim_fpu_to32 (&result, &f);
- return result;
- }
- SF
- sh64_fmacs(SIM_CPU *current_cpu, SF fr0, SF frm, SF frn)
- {
- SF result;
- sim_fpu m1, m2, a1, fres;
- sim_fpu_32to (&m1, fr0);
- sim_fpu_32to (&m2, frm);
- sim_fpu_32to (&a1, frn);
- sim_fpu_mul (&fres, &m1, &m2);
- sim_fpu_add (&fres, &fres, &a1);
-
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_fmuld(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- DF result;
- sim_fpu f1, f2, fres;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- sim_fpu_mul (&fres, &f1, &f2);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fmuls(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- SF result;
- sim_fpu f1, f2, fres;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- sim_fpu_mul (&fres, &f1, &f2);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_fnegd(SIM_CPU *current_cpu, DF drgh)
- {
- DF result;
- sim_fpu f1, f2;
- sim_fpu_64to (&f1, drgh);
- sim_fpu_neg (&f2, &f1);
- sim_fpu_to64 (&result, &f2);
- return result;
- }
- SF
- sh64_fnegs(SIM_CPU *current_cpu, SF frgh)
- {
- SF result;
- sim_fpu f, fres;
- sim_fpu_32to (&f, frgh);
- sim_fpu_neg (&fres, &f);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_fsqrtd(SIM_CPU *current_cpu, DF drgh)
- {
- DF result;
- sim_fpu f, fres;
- sim_fpu_64to (&f, drgh);
- sim_fpu_sqrt (&fres, &f);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fsqrts(SIM_CPU *current_cpu, SF frgh)
- {
- SF result;
- sim_fpu f, fres;
- sim_fpu_32to (&f, frgh);
- sim_fpu_sqrt (&fres, &f);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- DF
- sh64_fsubd(SIM_CPU *current_cpu, DF drg, DF drh)
- {
- DF result;
- sim_fpu f1, f2, fres;
- sim_fpu_64to (&f1, drg);
- sim_fpu_64to (&f2, drh);
- sim_fpu_sub (&fres, &f1, &f2);
- sim_fpu_to64 (&result, &fres);
- return result;
- }
- SF
- sh64_fsubs(SIM_CPU *current_cpu, SF frg, SF frh)
- {
- SF result;
- sim_fpu f1, f2, fres;
- sim_fpu_32to (&f1, frg);
- sim_fpu_32to (&f2, frh);
- sim_fpu_sub (&fres, &f1, &f2);
- sim_fpu_to32 (&result, &fres);
- return result;
- }
- SF
- sh64_ftrcdl(SIM_CPU *current_cpu, DF drgh)
- {
- SI result;
- sim_fpu f;
- sim_fpu_64to (&f, drgh);
- sim_fpu_to32i (&result, &f, sim_fpu_round_zero);
- return (SF) result;
- }
- SF
- sh64_ftrcsl(SIM_CPU *current_cpu, SF frgh)
- {
- SI result;
- sim_fpu f;
- sim_fpu_32to (&f, frgh);
- sim_fpu_to32i (&result, &f, sim_fpu_round_zero);
- return (SF) result;
- }
- DF
- sh64_ftrcdq(SIM_CPU *current_cpu, DF drgh)
- {
- DI result;
- sim_fpu f;
- sim_fpu_64to (&f, drgh);
- sim_fpu_to64i (&result, &f, sim_fpu_round_zero);
- return (DF) result;
- }
- DF
- sh64_ftrcsq(SIM_CPU *current_cpu, SF frgh)
- {
- DI result;
- sim_fpu f;
- sim_fpu_32to (&f, frgh);
- sim_fpu_to64i (&result, &f, sim_fpu_round_zero);
- return (DF) result;
- }
- VOID
- sh64_ftrvs(SIM_CPU *cpu, unsigned g, unsigned h, unsigned f)
- {
- int i, j;
- for (i = 0; i < 4; i++)
- {
- SF result;
- sim_fpu sum;
- sim_fpu_32to (&sum, 0);
- for (j = 0; j < 4; j++)
- {
- sim_fpu f1, f2, temp;
- sim_fpu_32to (&f1, sh64_h_fr_get (cpu, (g + i) + (j * 4)));
- sim_fpu_32to (&f2, sh64_h_fr_get (cpu, h + j));
- sim_fpu_mul (&temp, &f1, &f2);
- sim_fpu_add (&sum, &sum, &temp);
- }
- sim_fpu_to32 (&result, &sum);
- sh64_h_fr_set (cpu, f + i, result);
- }
- }
- VOID
- sh64_fipr (SIM_CPU *cpu, unsigned m, unsigned n)
- {
- SF result = sh64_fmuls (cpu, sh64_h_fvc_get (cpu, m), sh64_h_fvc_get (cpu, n));
- result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 1), sh64_h_frc_get (cpu, n + 1)));
- result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 2), sh64_h_frc_get (cpu, n + 2)));
- result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 3), sh64_h_frc_get (cpu, n + 3)));
- sh64_h_frc_set (cpu, n + 3, result);
- }
- SF
- sh64_fiprs (SIM_CPU *cpu, unsigned g, unsigned h)
- {
- SF temp = sh64_fmuls (cpu, sh64_h_fr_get (cpu, g), sh64_h_fr_get (cpu, h));
- temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 1), sh64_h_fr_get (cpu, h + 1)));
- temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 2), sh64_h_fr_get (cpu, h + 2)));
- temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 3), sh64_h_fr_get (cpu, h + 3)));
- return temp;
- }
- VOID
- sh64_fldp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f)
- {
- sh64_h_fr_set (cpu, f, GETMEMSF (cpu, pc, rm + rn));
- sh64_h_fr_set (cpu, f + 1, GETMEMSF (cpu, pc, rm + rn + 4));
- }
- VOID
- sh64_fstp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f)
- {
- SETMEMSF (cpu, pc, rm + rn, sh64_h_fr_get (cpu, f));
- SETMEMSF (cpu, pc, rm + rn + 4, sh64_h_fr_get (cpu, f + 1));
- }
- VOID
- sh64_ftrv (SIM_CPU *cpu, UINT ignored)
- {
- /* TODO: Unimplemented. */
- }
- VOID
- sh64_pref (SIM_CPU *cpu, SI addr)
- {
- /* TODO: Unimplemented. */
- }
- /* Count the number of arguments. */
- static int
- count_argc (cpu)
- SIM_CPU *cpu;
- {
- int i = 0;
- if (! STATE_PROG_ARGV (CPU_STATE (cpu)))
- return -1;
-
- while (STATE_PROG_ARGV (CPU_STATE (cpu)) [i] != NULL)
- ++i;
- return i;
- }
- /* Read a null terminated string from memory, return in a buffer */
- static char *
- fetch_str (current_cpu, pc, addr)
- SIM_CPU *current_cpu;
- PCADDR pc;
- DI addr;
- {
- char *buf;
- int nr = 0;
- while (sim_core_read_1 (current_cpu,
- pc, read_map, addr + nr) != 0)
- nr++;
- buf = NZALLOC (char, nr + 1);
- sim_read (CPU_STATE (current_cpu), addr, buf, nr);
- return buf;
- }
- static void
- trap_handler (SIM_CPU *current_cpu, int shmedia_abi_p, UQI trapnum, PCADDR pc)
- {
- char ch;
- switch (trapnum)
- {
- case 1:
- ch = GET_H_GRC (0);
- sim_io_write_stdout (CPU_STATE (current_cpu), &ch, 1);
- fflush (stdout);
- break;
- case 2:
- sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
- break;
- case 34:
- {
- int i;
- int ret_reg = (shmedia_abi_p) ? 2 : 0;
- char *buf;
- DI PARM1 = GET_H_GR ((shmedia_abi_p) ? 3 : 5);
- DI PARM2 = GET_H_GR ((shmedia_abi_p) ? 4 : 6);
- DI PARM3 = GET_H_GR ((shmedia_abi_p) ? 5 : 7);
-
- switch (GET_H_GR ((shmedia_abi_p) ? 2 : 4))
- {
- case SYS_write:
- buf = zalloc (PARM3);
- sim_read (CPU_STATE (current_cpu), PARM2, buf, PARM3);
- SET_H_GR (ret_reg,
- sim_io_write (CPU_STATE (current_cpu),
- PARM1, buf, PARM3));
- free (buf);
- break;
- case SYS_lseek:
- SET_H_GR (ret_reg,
- sim_io_lseek (CPU_STATE (current_cpu),
- PARM1, PARM2, PARM3));
- break;
-
- case SYS_exit:
- sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
- NULL, pc, sim_exited, PARM1);
- break;
- case SYS_read:
- buf = zalloc (PARM3);
- SET_H_GR (ret_reg,
- sim_io_read (CPU_STATE (current_cpu),
- PARM1, buf, PARM3));
- sim_write (CPU_STATE (current_cpu), PARM2, buf, PARM3);
- free (buf);
- break;
-
- case SYS_open:
- buf = fetch_str (current_cpu, pc, PARM1);
- SET_H_GR (ret_reg,
- sim_io_open (CPU_STATE (current_cpu),
- buf, PARM2));
- free (buf);
- break;
- case SYS_close:
- SET_H_GR (ret_reg,
- sim_io_close (CPU_STATE (current_cpu), PARM1));
- break;
- case SYS_time:
- SET_H_GR (ret_reg, time (0));
- break;
- case SYS_argc:
- SET_H_GR (ret_reg, count_argc (current_cpu));
- break;
- case SYS_argnlen:
- if (PARM1 < count_argc (current_cpu))
- SET_H_GR (ret_reg,
- strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]));
- else
- SET_H_GR (ret_reg, -1);
- break;
- case SYS_argn:
- if (PARM1 < count_argc (current_cpu))
- {
- /* Include the NULL byte. */
- i = strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]) + 1;
- sim_write (CPU_STATE (current_cpu),
- PARM2,
- STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1],
- i);
- /* Just for good measure. */
- SET_H_GR (ret_reg, i);
- break;
- }
- else
- SET_H_GR (ret_reg, -1);
- break;
- default:
- SET_H_GR (ret_reg, -1);
- }
- }
- break;
- case 253:
- puts ("pass");
- exit (0);
- case 254:
- puts ("fail");
- exit (1);
- case 0xc3:
- /* fall through. */
- case 255:
- sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
- break;
- }
- }
- void
- sh64_trapa (SIM_CPU *current_cpu, DI rm, PCADDR pc)
- {
- trap_handler (current_cpu, 1, (UQI) rm & 0xff, pc);
- }
- void
- sh64_compact_trapa (SIM_CPU *current_cpu, UQI trapnum, PCADDR pc)
- {
- int mach_sh5_p;
- /* If this is an SH5 executable, this is SHcompact code running in
- the SHmedia ABI. */
- mach_sh5_p =
- (bfd_get_mach (STATE_PROG_BFD (CPU_STATE (current_cpu))) == bfd_mach_sh5);
- trap_handler (current_cpu, mach_sh5_p, trapnum, pc);
- }
- DI
- sh64_nsb (SIM_CPU *current_cpu, DI rm)
- {
- int result = 0, count;
- UDI source = (UDI) rm;
- if ((source >> 63))
- source = ~source;
- source <<= 1;
- for (count = 32; count; count >>= 1)
- {
- UDI newval = source << count;
- if ((newval >> count) == source)
- {
- result |= count;
- source = newval;
- }
- }
-
- return result;
- }
- void
- sh64_break (SIM_CPU *current_cpu, PCADDR pc)
- {
- SIM_DESC sd = CPU_STATE (current_cpu);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
- }
- SI
- sh64_movua (SIM_CPU *current_cpu, PCADDR pc, SI rn)
- {
- SI v;
- int i;
- /* Move the data one byte at a time to avoid alignment problems.
- Be aware of endianness. */
- v = 0;
- for (i = 0; i < 4; ++i)
- v = (v << 8) | (GETMEMQI (current_cpu, pc, rn + i) & 0xff);
- v = T2H_4 (v);
- return v;
- }
- void
- set_isa (SIM_CPU *current_cpu, int mode)
- {
- /* Do nothing. */
- }
- /* The semantic code invokes this for invalid (unrecognized) instructions. */
- SEM_PC
- sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
- {
- SIM_DESC sd = CPU_STATE (current_cpu);
- sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
- return vpc;
- }
- /* Process an address exception. */
- void
- sh64_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
- unsigned int map, int nr_bytes, address_word addr,
- transfer_type transfer, sim_core_signals sig)
- {
- sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
- transfer, sig);
- }
- /* Initialize cycle counting for an insn.
- FIRST_P is non-zero if this is the first insn in a set of parallel
- insns. */
- void
- sh64_compact_model_insn_before (SIM_CPU *cpu, int first_p)
- {
- /* Do nothing. */
- }
- void
- sh64_media_model_insn_before (SIM_CPU *cpu, int first_p)
- {
- /* Do nothing. */
- }
- /* Record the cycles computed for an insn.
- LAST_P is non-zero if this is the last insn in a set of parallel insns,
- and we update the total cycle count.
- CYCLES is the cycle count of the insn. */
- void
- sh64_compact_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
- {
- /* Do nothing. */
- }
- void
- sh64_media_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
- {
- /* Do nothing. */
- }
- int
- sh64_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
- {
- /* Fetch general purpose registers. */
- if (nr >= SIM_SH64_R0_REGNUM
- && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS)
- && len == 8)
- {
- *((unsigned64*) buf) =
- H2T_8 (sh64_h_gr_get (cpu, nr - SIM_SH64_R0_REGNUM));
- return len;
- }
- /* Fetch PC. */
- if (nr == SIM_SH64_PC_REGNUM && len == 8)
- {
- *((unsigned64*) buf) = H2T_8 (sh64_h_pc_get (cpu) | sh64_h_ism_get (cpu));
- return len;
- }
- /* Fetch status register (SR). */
- if (nr == SIM_SH64_SR_REGNUM && len == 8)
- {
- *((unsigned64*) buf) = H2T_8 (sh64_h_sr_get (cpu));
- return len;
- }
-
- /* Fetch saved status register (SSR) and PC (SPC). */
- if ((nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM)
- && len == 8)
- {
- *((unsigned64*) buf) = 0;
- return len;
- }
- /* Fetch target registers. */
- if (nr >= SIM_SH64_TR0_REGNUM
- && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS)
- && len == 8)
- {
- *((unsigned64*) buf) =
- H2T_8 (sh64_h_tr_get (cpu, nr - SIM_SH64_TR0_REGNUM));
- return len;
- }
- /* Fetch floating point registers. */
- if (nr >= SIM_SH64_FR0_REGNUM
- && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS)
- && len == 4)
- {
- *((unsigned32*) buf) =
- H2T_4 (sh64_h_fr_get (cpu, nr - SIM_SH64_FR0_REGNUM));
- return len;
- }
- /* We should never get here. */
- return 0;
- }
- int
- sh64_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
- {
- /* Store general purpose registers. */
- if (nr >= SIM_SH64_R0_REGNUM
- && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS)
- && len == 8)
- {
- sh64_h_gr_set (cpu, nr - SIM_SH64_R0_REGNUM, T2H_8 (*((unsigned64*)buf)));
- return len;
- }
- /* Store PC. */
- if (nr == SIM_SH64_PC_REGNUM && len == 8)
- {
- unsigned64 new_pc = T2H_8 (*((unsigned64*)buf));
- sh64_h_pc_set (cpu, new_pc);
- return len;
- }
- /* Store status register (SR). */
- if (nr == SIM_SH64_SR_REGNUM && len == 8)
- {
- sh64_h_sr_set (cpu, T2H_8 (*((unsigned64*)buf)));
- return len;
- }
- /* Store saved status register (SSR) and PC (SPC). */
- if (nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM)
- {
- /* Do nothing. */
- return len;
- }
- /* Store target registers. */
- if (nr >= SIM_SH64_TR0_REGNUM
- && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS)
- && len == 8)
- {
- sh64_h_tr_set (cpu, nr - SIM_SH64_TR0_REGNUM, T2H_8 (*((unsigned64*)buf)));
- return len;
- }
- /* Store floating point registers. */
- if (nr >= SIM_SH64_FR0_REGNUM
- && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS)
- && len == 4)
- {
- sh64_h_fr_set (cpu, nr - SIM_SH64_FR0_REGNUM, T2H_4 (*((unsigned32*)buf)));
- return len;
- }
- /* We should never get here. */
- return 0;
- }
- void
- sh64_engine_run_full(SIM_CPU *cpu)
- {
- if (sh64_h_ism_get (cpu) == ISM_MEDIA)
- {
- if (!sh64_idesc_media)
- {
- sh64_media_init_idesc_table (cpu);
- sh64_idesc_media = CPU_IDESC (cpu);
- }
- else
- CPU_IDESC (cpu) = sh64_idesc_media;
- sh64_media_engine_run_full (cpu);
- }
- else
- {
- if (!sh64_idesc_compact)
- {
- sh64_compact_init_idesc_table (cpu);
- sh64_idesc_compact = CPU_IDESC (cpu);
- }
- else
- CPU_IDESC (cpu) = sh64_idesc_compact;
- sh64_compact_engine_run_full (cpu);
- }
- }
- void
- sh64_engine_run_fast (SIM_CPU *cpu)
- {
- if (sh64_h_ism_get (cpu) == ISM_MEDIA)
- {
- if (!sh64_idesc_media)
- {
- sh64_media_init_idesc_table (cpu);
- sh64_idesc_media = CPU_IDESC (cpu);
- }
- else
- CPU_IDESC (cpu) = sh64_idesc_media;
- sh64_media_engine_run_fast (cpu);
- }
- else
- {
- if (!sh64_idesc_compact)
- {
- sh64_compact_init_idesc_table (cpu);
- sh64_idesc_compact = CPU_IDESC (cpu);
- }
- else
- CPU_IDESC (cpu) = sh64_idesc_compact;
- sh64_compact_engine_run_fast (cpu);
- }
- }
- static void
- sh64_prepare_run (SIM_CPU *cpu)
- {
- /* Nothing. */
- }
- static const CGEN_INSN *
- sh64_get_idata (SIM_CPU *cpu, int inum)
- {
- return CPU_IDESC (cpu) [inum].idata;
- }
- static void
- sh64_init_cpu (SIM_CPU *cpu)
- {
- CPU_REG_FETCH (cpu) = sh64_fetch_register;
- CPU_REG_STORE (cpu) = sh64_store_register;
- CPU_PC_FETCH (cpu) = sh64_h_pc_get;
- CPU_PC_STORE (cpu) = sh64_h_pc_set;
- CPU_GET_IDATA (cpu) = sh64_get_idata;
- /* Only used by profiling. 0 disables it. */
- CPU_MAX_INSNS (cpu) = 0;
- CPU_INSN_NAME (cpu) = cgen_insn_name;
- CPU_FULL_ENGINE_FN (cpu) = sh64_engine_run_full;
- #if WITH_FAST
- CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_fast;
- #else
- CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_full;
- #endif
- }
- static void
- shmedia_init_cpu (SIM_CPU *cpu)
- {
- sh64_init_cpu (cpu);
- }
- static void
- shcompact_init_cpu (SIM_CPU *cpu)
- {
- sh64_init_cpu (cpu);
- }
- static void
- sh64_model_init()
- {
- /* Do nothing. */
- }
- static const MODEL sh_models [] =
- {
- { "sh2", & sh2_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh2e", & sh2e_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh2a", & sh2a_fpu_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh2a_nofpu", & sh2a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh3", & sh3_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh3e", & sh3_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh4", & sh4_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh4_nofpu", & sh4_nofpu_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh4a", & sh4a_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh4a_nofpu", & sh4a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh4al", & sh4al_mach, MODEL_SH5, NULL, sh64_model_init },
- { "sh5", & sh5_mach, MODEL_SH5, NULL, sh64_model_init },
- { 0 }
- };
- static const MACH_IMP_PROPERTIES sh5_imp_properties =
- {
- sizeof (SIM_CPU),
- #if WITH_SCACHE
- sizeof (SCACHE)
- #else
- 0
- #endif
- };
- const MACH sh2_mach =
- {
- "sh2", "sh2", MACH_SH5,
- 16, 16, &sh_models[0], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh2e_mach =
- {
- "sh2e", "sh2e", MACH_SH5,
- 16, 16, &sh_models[1], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh2a_fpu_mach =
- {
- "sh2a", "sh2a", MACH_SH5,
- 16, 16, &sh_models[2], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh2a_nofpu_mach =
- {
- "sh2a_nofpu", "sh2a_nofpu", MACH_SH5,
- 16, 16, &sh_models[3], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh3_mach =
- {
- "sh3", "sh3", MACH_SH5,
- 16, 16, &sh_models[4], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh3e_mach =
- {
- "sh3e", "sh3e", MACH_SH5,
- 16, 16, &sh_models[5], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh4_mach =
- {
- "sh4", "sh4", MACH_SH5,
- 16, 16, &sh_models[6], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh4_nofpu_mach =
- {
- "sh4_nofpu", "sh4_nofpu", MACH_SH5,
- 16, 16, &sh_models[7], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh4a_mach =
- {
- "sh4a", "sh4a", MACH_SH5,
- 16, 16, &sh_models[8], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh4a_nofpu_mach =
- {
- "sh4a_nofpu", "sh4a_nofpu", MACH_SH5,
- 16, 16, &sh_models[9], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh4al_mach =
- {
- "sh4al", "sh4al", MACH_SH5,
- 16, 16, &sh_models[10], &sh5_imp_properties,
- shcompact_init_cpu,
- sh64_prepare_run
- };
- const MACH sh5_mach =
- {
- "sh5", "sh5", MACH_SH5,
- 32, 32, &sh_models[11], &sh5_imp_properties,
- shmedia_init_cpu,
- sh64_prepare_run
- };
|