aboutsummaryrefslogtreecommitdiff
path: root/sim/h8500/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/h8500/compile.c')
-rw-r--r--sim/h8500/compile.c2519
1 files changed, 2519 insertions, 0 deletions
diff --git a/sim/h8500/compile.c b/sim/h8500/compile.c
new file mode 100644
index 0000000..1aad644
--- /dev/null
+++ b/sim/h8500/compile.c
@@ -0,0 +1,2519 @@
+/* Simulator for the Hitachi H8/500 architecture.
+
+ Written by Steve Chamberlain of Cygnus Support.
+ sac@cygnus.com
+
+ This file is part of H8/500 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.
+
+*/
+
+#include "config.h"
+
+#include <signal.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <sys/param.h>
+#include <setjmp.h>
+#include "ansidecl.h"
+#include "bfd.h"
+#include "callback.h"
+#include "remote-sim.h"
+
+#define O_RECOMPILE 85
+#define DEFINE_TABLE
+#define DISASSEMBLER_TABLE
+
+/* FIXME: Needs to live in header file.
+ This header should also include the things in remote-sim.h.
+ One could move this to remote-sim.h but this function isn't needed
+ by gdb. */
+void sim_set_simcache_size PARAMS ((int));
+
+int debug;
+
+host_callback *sim_callback;
+
+static SIM_OPEN_KIND sim_kind;
+static char *myname;
+
+/* This code can be compiled with any old C compiler, in which case
+ four or five switch statements will be executed for each
+ instruction simulated. It can be compiled with GCC, then the
+ simulated instructions thread through the code fragments, and
+ everything goes much faster.
+
+ These definitions make the code work either way
+*/
+#ifdef __GNUC__
+#define DISPATCH(X) goto *(X); do
+#define LABEL(X) X##_L
+#define LABELN(X,N) X##_L##N
+#define LABEL_REF(X) &&X##_L
+#define LABEL_REFN(X,N) &&X##_L##N
+#define ENDDISPATCH while (0);
+#define fastref void *
+
+#define DEFAULT ;
+#define INLINE __inline__
+#else
+#define DEFAULT default :
+#define DISPATCH(X) switch (X)
+#define LABEL(X) case X
+#define LABELN(X,N) case X
+#define LABEL_REF(X) X
+#define LABEL_REFN(X,N) X
+#define ENDDISPATCH
+#define fastref int
+
+
+
+#define INLINE
+#define STORE_REG_B 1
+#define STORE_REG_W 2
+#define STORE_INC_B 3
+#define STORE_INC_W 4
+#define STORE_DEC_B 5
+#define STORE_DEC_W 6
+#define STORE_DISP_B 7
+#define STORE_DISP_W 8
+#define STORE_CRB 9
+#define STORE_CRW 10
+#define STORE_REG_L 11
+#define STORE_NOP 12
+
+#define FETCH_NOP 9
+#define FETCH_REG_B 10
+#define FETCH_REG_W 11
+#define FETCH_INC_B 12
+#define FETCH_INC_W 13
+#define FETCH_DEC_B 14
+#define FETCH_DEC_W 15
+#define FETCH_DISP_B 16
+#define FETCH_DISP_W 17
+#define FETCH_IMM 18
+#define FETCH_CRB 19
+#define FETCH_CRW 20
+#define FETCH_LVAL 21
+#define FETCH_LVAL24 22
+#define FETCH_REG_L 23
+
+#define FLAG_m 20
+#define FLAG_M 21
+#define FLAG_A 22
+#define FLAG_NONE 23
+#define FLAG_NOSTORE 24
+#define FLAG_CLEAR 25
+#define FLAG_a 26
+#define FLAG_BRANCH 27
+#define FLAG_special 28
+
+#define FLAG_shiftword 29
+#define FLAG_shiftbyte 30
+
+#define FLAG_multword 31
+#define FLAG_multbyte 32
+#endif
+
+
+#define h8500_table h8500_compile_table
+#include "../opcodes/h8500-opc.h"
+
+#include "inst.h"
+
+#define LOW_BYTE(x) ((x) & 0xff)
+#define HIGH_BYTE(x) (((x)>>8) & 0xff)
+#define NORMAL_CP ((cpu.regs[R_CP].c - cpu.memory)>>16)
+#define NORMAL_DP ((cpu.regs[R_DP].c - cpu.memory)>>16)
+#define NORMAL_EP ((cpu.regs[R_EP].c - cpu.memory)>>16)
+#define NORMAL_TP ((cpu.regs[R_TP].c - cpu.memory)>>16)
+#define SET_NORMREG(x,y) ((cpu.regs[x].l = (y)))
+#define GET_NORMREG(x) (cpu.regs[x].l)
+#define SET_SEGREG(x,y) { cpu.regs[x].c = ((y) & 0xff0000) + cpu.memory;}
+#define GET_SEGREG(x) ( (cpu.regs[x].c - cpu.memory ) >> 16)
+#define SET_NORMAL_CPPC(x) { pc = (x) & 0xffff; SET_SEGREG(R_CP, (x));}
+#define NORMAL_SR ((N<<3)|(Z<<2)|(V<<1)|(C))
+#define P(X,Y) ((X<<8) | Y)
+
+#define BUILDSR() cpu.regs[R_SR].s[LOW] = (N << 3) | (Z << 2) | (V<<1) | C;
+
+#define GETSR() \
+ C = (cpu.regs[R_SR].s[LOW] >> 0) & 1;\
+ V = (cpu.regs[R_SR].s[LOW] >> 1) & 1;\
+ Z = (cpu.regs[R_SR].s[LOW] >> 2) & 1;\
+ N = (cpu.regs[R_SR].s[LOW] >> 3) & 1;
+
+#ifdef __CHAR_IS_SIGNED__
+#define SEXTCHAR(x) ((char)(x))
+#endif
+
+#ifndef SEXTCHAR
+#define SEXTCHAR(x) ((x & 0x80) ? (x | ~0xff):x)
+#endif
+
+#define SEXTSHORT(x) ((short)(x))
+
+/* Which segment registers go with which pointer registers */
+static unsigned char **segmap[R_LAST];
+static unsigned char *(regptr[R_LAST][3]);
+static unsigned char *(segregptr[R_LAST][3]);
+static cpu_state_type cpu;
+
+static int segforreg[] = {R_DP, R_DP, R_DP, R_DP,
+ R_EP, R_EP, R_TP, R_TP,
+ R_DP, R_DP, R_DP, R_DP,
+ R_EP, R_EP, R_TP, R_TP};
+int LOW;
+int HIGH;
+
+/* routines for getting and storing args */
+#define elval(struct, lit) \
+ (((*(struct.reg.wptr) + lit) & 0xffff) + (*(struct.r2.segreg)))
+
+#define displval(s) elval((s),(s).literal)
+
+#define ireglval(struct) elval(struct, 0)
+#define wordat(x) (((x)[0] << 8) | (x)[1])
+#define longat(x) ((wordat((x))<<16)|(wordat((x)+2)))
+#define byteat(x) ((x)[0])
+
+#define setwordat(x,y) {x[0] =( y)>>8; x[1] = y;}
+#define setbyteat(x,y) {x[0] = y;}
+
+/*#define setalignedwordat(x,y) {((short *)x)[0] =y;}*/
+/*
+statics
+*/
+
+ea_type rd;
+ea_type rs;
+ea_type imm;
+ea_type cr;
+ea_type ea;
+ea_type nop;
+ea_type lval;
+ea_type lval24;
+
+ea_type eavector[2];
+
+int disp;
+
+#define JBYTE 0
+#define JWORD 1
+#define JLONG 2
+
+typedef union
+{
+ struct
+ {
+ fastref srcabyte;
+ fastref srcaword;
+ fastref srcalong;
+
+ fastref srcbbyte;
+ fastref srcbword;
+ fastref srcblong;
+
+ fastref dstbyte;
+ fastref dstword;
+ fastref dstlong;
+ } s;
+ struct
+ {
+ fastref byte;
+ fastref word;
+ fastref lon;
+ } a[3];
+
+ fastref j[9];
+} size_ptr;
+
+union
+{
+ struct ea_struct
+ {
+ size_ptr ea_nop;
+ size_ptr ea_reg;
+ size_ptr ea_inc;
+ size_ptr ea_dec;
+ size_ptr ea_disp;
+
+ size_ptr ea_imm;
+ size_ptr ea_cr;
+ size_ptr ea_lval;
+ size_ptr ea_lval24;
+ } s;
+#define N_EATYPES (sizeof(struct ea_struct) / sizeof(size_ptr))
+ size_ptr a[N_EATYPES];
+} eas;
+
+/* This function takes an ea structure filled in for the 1st source
+ operand and modifies it to be for either the 1st, 2nd or dst operand */
+
+static void
+howto_workout (encoded, semiencoded, n)
+ ea_type *encoded;
+ ea_type *semiencoded;
+ int n;
+{
+ int i;
+ *encoded = *semiencoded;
+
+ for (i = 0; i < N_EATYPES; i++)
+ {
+ if (encoded->type == eas.a[i].s.srcabyte)
+ {
+ encoded->type = eas.a[i].a[n].byte;
+ return;
+ }
+ else if (encoded->type == eas.a[i].s.srcaword)
+ {
+ encoded->type = eas.a[i].a[n].word;
+ return;
+ }
+ else if (encoded->type == eas.a[i].s.srcalong)
+ {
+ encoded->type = eas.a[i].a[n].lon;
+ return;
+ }
+ }
+
+ abort ();
+}
+
+fastref flag_shiftword;
+fastref flag_shiftbyte;
+fastref flag_multword;
+fastref flag_multbyte;
+fastref flag_mp;
+fastref flag_special;
+fastref flag_Mp;
+fastref flag_ap;
+fastref flag_Ap;
+fastref flag_nonep;
+fastref flag_nostorep;
+fastref flag_clearp;
+fastref flag_branch;
+fastref exec_dispatch[100];
+
+static int
+get_now ()
+{
+ return time (0);
+}
+
+static int
+now_persec ()
+{
+ return 1;
+}
+
+static void
+gotcr (ptr, n)
+ ea_type *ptr;
+ int n;
+{
+ int size;
+ n &= 0x7;
+ if (n == 0)
+ {
+ abort ();
+ }
+ else
+ {
+ ptr->type = eas.s.ea_cr.j[JBYTE];
+ ptr->reg.bptr = segregptr[n][JLONG];
+ }
+}
+static void
+gotreg (ptr, n, size)
+ ea_type *ptr;
+ int n;
+ int size;
+{
+ n &= 0x7;
+ ptr->type = eas.s.ea_reg.j[size];
+ ptr->reg.bptr = regptr[n][size];
+}
+
+static void
+gotinc (ptr, n, inc, size)
+ ea_type *ptr;
+ int n;
+ int size;
+{
+ n &= 0x7;
+ if (inc > 0)
+ {
+ ptr->type = eas.s.ea_inc.j[size];
+ }
+ else
+ {
+ ptr->type = eas.s.ea_dec.j[size];
+ }
+ ptr->reg.bptr = regptr[n][JWORD];
+ ptr->r2.segreg = segmap[n];
+}
+
+
+static void
+gotabs (ptr, disp, reg, size)
+ ea_type *ptr;
+ int disp;
+ int reg;
+ int size;
+{
+ ptr->type = eas.s.ea_disp.j[size];
+ ptr->reg.bptr = regptr[reg][JWORD];
+ ptr->r2.segreg = segmap[reg];
+ ptr->literal = disp;
+}
+
+static void
+gotind (ptr, disp, reg, size)
+ ea_type *ptr;
+ int disp;
+ int reg;
+ int size;
+{
+ gotabs (ptr, disp, reg & 0x7, size);
+}
+
+static void
+gotimm (ptr, val)
+ ea_type *ptr;
+ int val;
+{
+ ptr->type = eas.s.ea_imm.j[0];
+ ptr->literal = val;
+}
+
+static void
+indoff (ptr)
+ ea_type *ptr;
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ {
+ if (ptr->type == eas.s.ea_disp.j[i])
+ {
+ ptr->type = eas.s.ea_lval.j[i];
+ return;
+ }
+ }
+}
+
+thinkabout_shifts (d, bytesized)
+ decoded_inst *d;
+ int bytesized;
+{
+ if (bytesized)
+ {
+ /* Got a byte shift, fake up second arg */
+ d->srcb.type = eas.s.ea_imm.s.srcbword;
+ d->srcb.literal = 8;
+ }
+ else
+ {
+ /* got a word shift, fake up second arg */
+ d->srcb.type = eas.s.ea_imm.s.srcbword;
+ d->srcb.literal = 16;
+ }
+}
+
+/* Calculate the number of cycles required to run this
+ instruction
+*/
+static void
+compcycles (dst, opcode)
+ decoded_inst *dst;
+ h8500_opcode_info *opcode;
+{
+ int cycles = 0;
+ /* Guess for the time being - 1 cycle for the first two bytes in the
+ opcode - to fecth the operand, and 3 cycles for all the rest of
+ the bytes, since they mean that there is probably an operand to
+ fetch */
+
+ switch (opcode->length)
+ {
+ case 1:
+ case 2:
+ cycles += opcode->length;
+ break;
+ default:
+ cycles += opcode->length * 3;
+ break;
+ }
+
+ dst->cycles = cycles;
+}
+
+static void
+translate (ptr, from, to)
+ ea_type *ptr;
+ fastref from;
+ fastref to;
+{
+ if (ptr->reg.wptr == &cpu.regs[7].s[LOW]
+ && ptr->type == from)
+ {
+ ptr->type = to;
+ }
+}
+
+static
+void
+fix_incdecs (dst)
+ decoded_inst *dst;
+{
+ if (dst->dst.type == eas.s.ea_inc.s.dstbyte
+ && (dst->srca.type == eas.s.ea_inc.s.srcabyte
+ || dst->srcb.type == eas.s.ea_inc.s.srcbbyte))
+ {
+ dst->dst.type = eas.s.ea_disp.s.dstbyte;
+ }
+
+ if (dst->dst.type == eas.s.ea_inc.s.dstword
+ && (dst->srca.type == eas.s.ea_inc.s.srcaword
+ || dst->srcb.type == eas.s.ea_inc.s.srcbword))
+ {
+ dst->dst.type = eas.s.ea_disp.s.dstword;
+ }
+
+ if (dst->dst.type == eas.s.ea_dec.s.dstbyte
+ || dst->dst.type == eas.s.ea_dec.s.dstword)
+ {
+ if (dst->srca.type == eas.s.ea_dec.s.srcabyte)
+ {
+ dst->srca.type = eas.s.ea_disp.s.srcabyte;
+ }
+ else if (dst->srca.type == eas.s.ea_dec.s.srcaword)
+ {
+ dst->srca.type = eas.s.ea_disp.s.srcaword;
+ }
+ else if (dst->srcb.type == eas.s.ea_dec.s.srcbbyte)
+ {
+ dst->srcb.type = eas.s.ea_disp.s.srcbbyte;
+ }
+ else if (dst->srcb.type == eas.s.ea_dec.s.srcbword)
+ {
+ dst->srcb.type = eas.s.ea_disp.s.srcbword;
+ }
+ }
+
+
+ /* Turn a byte ops from the sp into word ops */
+ translate (&dst->dst, eas.s.ea_dec.s.dstbyte, eas.s.ea_dec.s.dstword);
+ translate (&dst->dst, eas.s.ea_inc.s.dstbyte, eas.s.ea_inc.s.dstword);
+
+ translate (&dst->srca, eas.s.ea_dec.s.srcabyte, eas.s.ea_dec.s.srcaword);
+ translate (&dst->srca, eas.s.ea_inc.s.srcabyte, eas.s.ea_inc.s.srcaword);
+
+ translate (&dst->srcb, eas.s.ea_dec.s.srcbbyte, eas.s.ea_dec.s.srcbword);
+ translate (&dst->srcb, eas.s.ea_inc.s.srcbbyte, eas.s.ea_inc.s.srcbword);
+
+
+}
+
+
+static void
+find (pc, buffer, dst)
+ int pc;
+ unsigned char *buffer;
+ decoded_inst *dst;
+{
+ h8500_opcode_info *opcode;
+ int i;
+ int idx;
+ int hadimm = 0;
+ dst->srca.reg.rptr = 0;
+
+ /* Run down the table to find the one which matches */
+ for (opcode = h8500_table; opcode->name; opcode++)
+ {
+ int byte;
+ int rn;
+ int rd;
+ int rs;
+ int disp;
+ int abs;
+ int imm;
+ int pcrel;
+ int qim;
+ int i;
+ int cr;
+
+
+ dst->opcode = exec_dispatch[opcode->flavor & 0x7f];
+
+ for (byte = 0; byte < opcode->length; byte++)
+ {
+ if ((buffer[byte] & opcode->bytes[byte].mask)
+ != (opcode->bytes[byte].contents))
+ {
+ goto next;
+ }
+ else
+ {
+ /* extract any info parts */
+ switch (opcode->bytes[byte].insert)
+ {
+ case 0:
+ case FP:
+ break;
+ default:
+ abort ();
+ break;
+ case RN:
+ rn = buffer[byte] & 0x7;
+ break;
+ case RS:
+ rs = buffer[byte] & 0x7;
+ break;
+ case CRB:
+ cr = buffer[byte] & 0x7;
+ if (cr == 0)
+ goto next;
+ break;
+ case CRW:
+ cr = buffer[byte] & 0x7;
+ if (cr != 0)
+ goto next;
+ break;
+ case DISP16:
+ disp = (buffer[byte] << 8) | (buffer[byte + 1]);
+ break;
+ case FPIND_D8:
+ case DISP8:
+ disp = ((char) (buffer[byte]));
+ break;
+ case RD:
+ case RDIND:
+ rd = buffer[byte] & 0x7;
+ break;
+ case ABS24:
+ abs =
+ (buffer[byte] << 16)
+ | (buffer[byte + 1] << 8)
+ | (buffer[byte + 2]);
+ break;
+ case ABS16:
+ abs = (buffer[byte] << 8) | (buffer[byte + 1]);
+ break;
+ case ABS8:
+ abs = (buffer[byte]);
+ break;
+ case IMM16:
+ imm = (buffer[byte] << 8) | (buffer[byte + 1]);
+ break;
+ case IMM4:
+ imm = (buffer[byte]) & 0xf;
+ break;
+ case IMM8:
+ case RLIST:
+ imm = SEXTCHAR (buffer[byte]);
+ break;
+ case PCREL16:
+ pcrel = SEXTSHORT ((buffer[byte] << 8) | (buffer[byte + 1]));
+ break;
+ case PCREL8:
+ pcrel = SEXTCHAR ((buffer[byte]));
+ break;
+ case QIM:
+ switch (buffer[byte] & 0x7)
+ {
+ case 0:
+ imm = 1;
+ break;
+ case 1:
+ imm = 2;
+ break;
+ case 4:
+ imm = -1;
+ break;
+ case 5:
+ imm = -2;
+ break;
+ }
+ break;
+
+ }
+ }
+ }
+ if (opcode->flavor & O_BYTE)
+ {
+ idx = 0;
+ switch (opcode->flags)
+ {
+ case 'h':
+ dst->flags = flag_shiftbyte;
+ break;
+ case 'p':
+ dst->flags = flag_multbyte;
+ break;
+ case 'B':
+ dst->flags = flag_branch;
+ break;
+ case 'm':
+ dst->flags = flag_mp;
+ break;
+ case 'a':
+ dst->flags = flag_ap;
+ break;
+ case '-':
+ dst->flags = flag_nonep;
+ break;
+ case 0:
+ dst->flags = flag_nostorep;
+ break;
+ case 'c':
+ dst->flags = flag_clearp;
+ break;
+ case 's':
+ /* special */
+ dst->flags = flag_special;
+ }
+ }
+ else
+ {
+ idx = 1;
+ switch (opcode->flags)
+ {
+ case 'h':
+ dst->flags = flag_shiftword;
+ break;
+ case 'p':
+ dst->flags = flag_multword;
+ break;
+ case 'B':
+ dst->flags = flag_branch;
+ break;
+ case 'm':
+ dst->flags = flag_Mp;
+ break;
+ case 'a':
+ dst->flags = flag_Ap;
+ break;
+ case '-':
+ dst->flags = flag_nonep;
+ break;
+ case 0:
+ dst->flags = flag_nostorep;
+ break;
+ case 'c':
+ dst->flags = flag_clearp;
+ break;
+ case 's':
+ /* special */
+ dst->flags = flag_special;
+ break;
+ }
+ }
+
+ for (i = 0; i < opcode->nargs; i++)
+ {
+ ea_type *p = eavector + i;
+
+ switch (opcode->arg_type[i])
+ {
+ default:
+ abort ();
+
+ case FP:
+ gotreg (p, 6, idx);
+ break;
+ case RNIND:
+ disp = 0;
+ case RNIND_D16:
+ case RNIND_D8:
+ gotind (p, disp, rn, idx);
+ break;
+ break;
+ case RDIND:
+ disp = 0;
+ case RDIND_D16:
+ case RDIND_D8:
+ gotind (p, disp, rd, idx);
+ break;
+ case FPIND_D8:
+ gotind (p, disp, 6, idx);
+ break;
+ case CRB:
+ case CRW:
+ gotcr (p, cr);
+ break;
+ case RN:
+ gotreg (p, rn, idx);
+ break;
+ case RD:
+ gotreg (p, rd, idx);
+ break;
+ case RS:
+ gotreg (p, rs, idx);
+ break;
+ case RNDEC:
+ gotinc (p, rn, -1, idx);
+ break;
+ case RNINC:
+ gotinc (p, rn, 1, idx);
+ break;
+ case SPINC:
+ gotinc (p, 7, 1, idx);
+ break;
+ case SPDEC:
+ gotinc (p, 7, -1, idx);
+ break;
+ case ABS24:
+ case ABS16:
+ gotabs (p, abs, R_HARD_0, idx);
+ break;
+ case ABS8:
+ gotabs (p, abs, R_HARD8_0, idx);
+ break;
+ case IMM16:
+ case RLIST:
+ case QIM:
+ case IMM4:
+ case IMM8:
+ gotimm (p, imm);
+ break;
+ case PCREL16:
+ case PCREL8:
+ gotimm (p,
+ ((pcrel + pc + opcode->length) & 0xffff) | (pc & 0xff0000),
+ R_HARD_0, JLONG);
+
+ }
+ }
+
+ /* Finished and done - turn from two operand stuff into three */
+
+ dst->srca.type = eas.s.ea_nop.s.srcabyte;
+ dst->srcb.type = eas.s.ea_nop.s.srcbbyte;
+ dst->dst.type = eas.s.ea_nop.s.dstbyte;
+
+ if (opcode->nargs)
+ {
+ switch (opcode->nargs)
+ {
+ case 1:
+ howto_workout (&dst->srca, &eavector[0], 0);
+ if (opcode->dst != '!')
+ howto_workout (&dst->dst, &eavector[0], 2);
+ break;
+ case 2:
+ if (opcode->src2 == '!')
+ {
+ howto_workout (&dst->srca, &eavector[0], 0);
+ howto_workout (&dst->dst, &eavector[1], 2);
+ }
+ else
+ {
+ howto_workout (&dst->srca, &eavector[0], 0);
+ howto_workout (&dst->srcb, &eavector[1], 1);
+ if (opcode->dst != '!')
+ {
+ howto_workout (&dst->dst, &eavector[1], 2);
+ }
+ }
+ break;
+ }
+
+
+
+ /* Some extra stuff with pre inc and post dec,
+ make sure that if the same ea is there twice, only one of the
+ ops is auto inc/dec */
+
+ fix_incdecs (dst);
+
+
+ /* Some special cases */
+ if (dst->opcode == exec_dispatch[O_PJSR]
+ || dst->opcode == exec_dispatch[O_PJMP])
+ {
+ /* Both the @abs:24 and @rn turn into a disp word,
+ chose the right a mode since @abs:24 is 4 bytes
+ long */
+
+ if (opcode->length == 4)
+ {
+ dst->srca.type = eas.s.ea_lval24.s.srcabyte;
+ }
+ else
+ {
+ dst->srca.type = eas.s.ea_reg.s.srcalong;
+ }
+
+ dst->srca.r2.rptr = &cpu.regs[R_HARD_0];
+
+ /* For [P]JSR, keep return address precomputed */
+ dst->srcb.literal = pc + opcode->length;
+ dst->srcb.type = eas.s.ea_imm.s.srcbword;
+ }
+ else if (dst->opcode == exec_dispatch[O_MULXU])
+ {
+ /* This is a multiply -fix the destination op */
+ if (dst->dst.type == eas.s.ea_reg.s.dstword)
+ {
+ dst->dst.type = eas.s.ea_reg.s.dstlong;
+ }
+ else
+ {
+ dst->dst.type = eas.s.ea_reg.s.dstword;
+ }
+ dst->dst.reg.bptr = regptr[rd][JWORD];
+ }
+ else if (dst->opcode == exec_dispatch[O_DIVXU])
+ {
+ /* This is a wider than normal, fix the source operand */
+ dst->srcb.type
+ = (dst->srcb.type == eas.s.ea_reg.s.srcbword)
+ ? eas.s.ea_reg.s.srcblong
+ : eas.s.ea_reg.s.srcbword;
+
+ dst->dst.type
+ = (dst->dst.type == eas.s.ea_reg.s.dstword)
+ ? eas.s.ea_reg.s.dstlong
+ : eas.s.ea_reg.s.dstword;
+
+ }
+
+ else if (dst->opcode == exec_dispatch[O_LDM])
+ {
+ /* Turn of the stack ref */
+ dst->srca.type = eas.s.ea_nop.s.srcabyte;
+ }
+ else if (dst->opcode == exec_dispatch[O_STM])
+ {
+ /* Turn of the stack ref */
+ dst->srcb.type = eas.s.ea_nop.s.srcbbyte;
+ }
+
+
+ /* extends read one size and write another */
+ else if (dst->opcode == exec_dispatch[O_EXTS]
+ || dst->opcode == exec_dispatch[O_EXTU])
+ {
+ dst->dst.type = eas.s.ea_reg.s.dstword;
+ dst->dst.reg.bptr = regptr[rd][JWORD];
+ dst->flags = flag_Ap;
+ }
+
+
+ if (opcode->flags == 'h')
+ thinkabout_shifts (dst, opcode->flavor & O_BYTE);
+
+
+ /* For a branch, turn off one level of indirection */
+ if (opcode->src1 == 'B')
+ {
+ indoff (&dst->srca, 0);
+ }
+
+ }
+ dst->next_pc = pc + opcode->length;
+
+ compcycles (dst, opcode);
+
+ return;
+
+
+ next:;
+ }
+
+ /* Couldn't understand anything */
+ dst->opcode = exec_dispatch[O_TRAPA];
+ dst->next_pc = pc + 1;
+
+}
+
+compile (pc)
+{
+ int idx;
+
+ /* find the next cache entry to use */
+
+ idx = cpu.cache_top + 1;
+ cpu.compiles++;
+ if (idx >= cpu.csize)
+ {
+ idx = 1;
+ }
+ cpu.cache_top = idx;
+
+ /* Throw away its old meaning */
+ cpu.cache_idx[cpu.cache[idx].oldpc] = 0;
+
+ /* set to new address */
+ cpu.cache[idx].oldpc = pc;
+
+ /* fill in instruction info */
+ find (pc, cpu.memory + pc, cpu.cache + idx);
+
+ /* point to new cache entry */
+ cpu.cache_idx[pc] = idx;
+}
+
+baddefault (x)
+{
+ printf ("bad default %d\n", x);
+}
+
+static int fetch_l (arg)
+ ea_type *arg;
+{
+ int l, r;
+
+ int h = *(arg->reg.wptr);
+ r = (union rtype *) (arg->reg.wptr) - &cpu.regs[0];
+ r++;
+
+ l = cpu.regs[r].s[LOW];
+ return (h << 16) | l;
+
+}
+
+#define FETCH(dst, arg, n) \
+{ \
+ int r; unsigned char*lval; \
+ DISPATCH((arg).type) \
+ { LABELN(FETCH_NOP,n): \
+ dst= 0; \
+ break; \
+ DEFAULT baddefault((arg).type); break; \
+ LABELN(FETCH_LVAL,n): \
+ dst = (*(((arg).reg.wptr)) + (arg.literal)) ; \
+ break; \
+ LABELN(FETCH_LVAL24,n): \
+ dst = (*(((arg).reg.wptr)) + *(((arg).r2.wptr)) + (arg.literal)) &0xffffff; \
+ break; \
+ LABELN(FETCH_CRB,n): \
+ dst = (*((arg).reg.segptr) - cpu.memory)>>16; \
+ break; \
+ LABELN(FETCH_CRW,n): \
+ dst = BUILDSR();\
+ break; \
+ LABELN(FETCH_REG_B,n): \
+ dst = *((arg).reg.bptr); \
+ break; \
+ LABELN(FETCH_REG_W,n): \
+ dst = *((arg).reg.wptr); \
+ break; \
+ LABELN(FETCH_REG_L,n): \
+ dst = fetch_l(&(arg));\
+ break; \
+ LABELN(FETCH_INC_B,n): \
+ lval = elval ((arg), 0); \
+ dst = byteat (lval); \
+ (*((arg).reg.wptr))++; \
+ break; \
+ LABELN(FETCH_INC_W,n): \
+ lval = elval ((arg), 0); \
+ dst = wordat (lval); \
+ (*(((arg).reg.wptr))) += 2; \
+ break; \
+ LABELN(FETCH_DEC_B, n): \
+ (*(arg).reg.wptr)--; \
+ lval = elval ((arg), 0); \
+ r = byteat (lval); \
+ dst = r; \
+ break; \
+ LABELN(FETCH_DEC_W, n): \
+ (*((arg).reg.wptr)) -= 2; \
+ lval = elval ((arg), 0); \
+ r = wordat (lval); \
+ dst = r; \
+ break; \
+ LABELN(FETCH_DISP_B,n): \
+ lval = displval ((arg)); \
+ dst = byteat (lval); \
+ break; \
+ LABELN(FETCH_DISP_W,n): \
+ lval = displval ((arg)); \
+ dst = wordat (lval); \
+ break; \
+ LABELN(FETCH_IMM, n): \
+ dst = (arg).literal; \
+ break; \
+ } \
+ ENDDISPATCH; \
+}
+
+static union
+{
+ short int i;
+ struct
+ {
+ char low;
+ char high;
+ }
+ u;
+}
+
+littleendian;
+
+static
+void
+init_pointers ()
+{
+ static int init;
+
+ if (!init)
+ {
+ int i;
+
+ init = 1;
+ littleendian.i = 1;
+
+ for (i = 0; i < (int) R_LAST; i++)
+ {
+ if (littleendian.u.high)
+ {
+ /* big endian host */
+
+
+ LOW = 1;
+ HIGH = 0;
+
+ regptr[i][0] = ((unsigned char *) (cpu.regs + i)) + 3;
+ regptr[i][1] = ((unsigned char *) (cpu.regs + i)) + 2;
+ }
+ else
+ {
+ LOW = 0;
+ HIGH = 1;
+
+ regptr[i][0] = (unsigned char *) &(cpu.regs[i]);
+ regptr[i][1] = (unsigned char *) (&(cpu.regs[i]));
+ }
+
+ regptr[i][2] = (unsigned char *) &(cpu.regs[i]);
+ }
+
+ memcpy (segregptr + 0, regptr + R_SR, sizeof (segregptr[0]));
+ memcpy (segregptr + 1, regptr + R_TP, sizeof (segregptr[1]));
+ memcpy (segregptr + 3, regptr + R_BR, sizeof (segregptr[3]));
+ memcpy (segregptr + 4, regptr + R_EP, sizeof (segregptr[4]));
+ memcpy (segregptr + 5, regptr + R_DP, sizeof (segregptr[5]));
+ memcpy (segregptr + 6, regptr + R_CP, sizeof (segregptr[6]));
+ memcpy (segregptr + 7, regptr + R_TP, sizeof (segregptr[7]));
+
+ /* Pointers to into the cpu state for the seg registers */
+
+ segmap[R0] = &cpu.regs[R_DP].c;
+ segmap[R1] = &cpu.regs[R_DP].c;
+ segmap[R2] = &cpu.regs[R_DP].c;
+ segmap[R3] = &cpu.regs[R_DP].c;
+ segmap[R4] = &cpu.regs[R_EP].c;
+ segmap[R5] = &cpu.regs[R_EP].c;
+ segmap[R6] = &cpu.regs[R_TP].c;
+ segmap[R7] = &cpu.regs[R_TP].c;
+ segmap[R_HARD_0] = &cpu.regs[R_DP].c;
+ segmap[R_HARD8_0] = &cpu.regs[R_BP].c;
+
+ cpu.memory = (unsigned char *) calloc (sizeof (char), H8500_MSIZE);
+ cpu.cache_idx = (unsigned short *) calloc (sizeof (short), H8500_MSIZE);
+
+ /* initialize the seg registers */
+
+ cpu.regs[R_DP].c = cpu.memory;
+ cpu.regs[R_TP].c = cpu.memory;
+ cpu.regs[R_CP].c = cpu.memory;
+ cpu.regs[R_BP].c = cpu.memory;
+ cpu.regs[R_EP].c = cpu.memory;
+ cpu.regs[R7].s[LOW] = 0xfffe;
+ cpu.regs[R6].s[LOW] = 0xfffe;
+ if (!cpu.cache)
+ sim_set_simcache_size (CSIZE);
+ }
+}
+
+#define PUSHWORD(x) \
+{ \
+ int sp = cpu.regs[R7].s[LOW]; \
+ unsigned char *p; \
+ \
+ sp -= 2; \
+ p = (sp & 0xffff) + (cpu.regs[R_TP].c); \
+ cpu.regs[R7].s[LOW] = sp; \
+ setwordat (p, x); \
+} \
+
+#define POPWORD(d) \
+{ \
+ int spx= cpu.regs[R7].s[LOW]; \
+ unsigned char *p; \
+ \
+ p = (spx& 0xffff) + (cpu.regs[R_TP].c); \
+ spx+= 2; \
+ cpu.regs[R7].s[LOW] = spx; \
+ d = wordat (p); \
+} \
+
+/* simulate a monitor trap */
+trap ()
+{
+ switch (cpu.regs[R3].s[LOW] & 0xff)
+ {
+ case 33:
+ /* exit */
+ cpu.exception = SIGQUIT;
+ break;
+ case 34:
+ /* abort */
+ cpu.exception = SIGABRT;
+ break;
+ case 6:
+ /* print char in r0 */
+ printf ("%c", cpu.regs[R0].s[LOW]);
+ break;
+ }
+}
+void
+control_c (sig, code, scp, addr)
+ int sig;
+ int code;
+ char *scp;
+ char *addr;
+{
+ cpu.exception = SIGINT;
+}
+
+static jmp_buf jbuf;
+static void
+segv ()
+{
+ cpu.exception = SIGSEGV;
+ longjmp (jbuf, 1);
+}
+
+int
+sim_stop (sd)
+ SIM_DESC sd;
+{
+ cpu.exception = SIGINT;
+ return 1;
+}
+
+void
+sim_resume (sd, step, siggnal)
+ SIM_DESC sd;
+{
+ static int init1;
+ int res;
+ int tmp;
+ int arga;
+ int argb;
+ int bit;
+ int pc;
+ int C, Z, V, N;
+ int cycles = 0;
+ int insts = 0;
+ int tick_start = get_now ();
+ void (*prev) ();
+ void (*prev_seg) ();
+
+ if (!init1)
+ {
+ int i;
+
+ init1 = 1;
+ init_pointers ();
+
+ for (i = 0; i < N_EATYPES; i++)
+ {
+ eas.a[i].s.srcabyte = LABEL_REFN (FETCH_NOP, 0);
+ eas.a[i].s.srcaword = LABEL_REFN (FETCH_NOP, 0);
+ eas.a[i].s.srcalong = LABEL_REFN (FETCH_NOP, 0);
+
+ eas.a[i].s.srcbbyte = LABEL_REFN (FETCH_NOP, 1);
+ eas.a[i].s.srcbword = LABEL_REFN (FETCH_NOP, 1);
+ eas.a[i].s.srcblong = LABEL_REFN (FETCH_NOP, 1);
+
+ eas.a[i].s.dstbyte = LABEL_REF (STORE_NOP);
+ eas.a[i].s.dstword = LABEL_REF (STORE_NOP);
+ eas.a[i].s.dstlong = LABEL_REF (STORE_NOP);
+ }
+
+ eas.s.ea_lval.s.srcabyte = LABEL_REFN (FETCH_LVAL, 0);
+ eas.s.ea_lval.s.srcaword = LABEL_REFN (FETCH_LVAL, 0);
+ eas.s.ea_lval24.s.srcabyte = LABEL_REFN (FETCH_LVAL24, 0);
+ eas.s.ea_lval24.s.srcaword = LABEL_REFN (FETCH_LVAL24, 0);
+
+ eas.s.ea_nop.s.srcabyte = LABEL_REFN (FETCH_NOP, 0);
+ eas.s.ea_nop.s.srcaword = LABEL_REFN (FETCH_NOP, 0);
+ eas.s.ea_nop.s.srcbbyte = LABEL_REFN (FETCH_NOP, 1);
+ eas.s.ea_nop.s.srcbword = LABEL_REFN (FETCH_NOP, 1);
+ eas.s.ea_nop.s.dstbyte = LABEL_REF (STORE_NOP);
+ eas.s.ea_nop.s.dstword = LABEL_REF (STORE_NOP);
+
+ eas.s.ea_cr.s.srcabyte = LABEL_REFN (FETCH_CRB, 0);
+ eas.s.ea_cr.s.srcaword = LABEL_REFN (FETCH_CRW, 0);
+
+ eas.s.ea_cr.s.srcbbyte = LABEL_REFN (FETCH_CRB, 1);
+ eas.s.ea_cr.s.srcbword = LABEL_REFN (FETCH_CRW, 1);
+
+ eas.s.ea_cr.s.dstbyte = LABEL_REF (STORE_CRB);
+ eas.s.ea_cr.s.dstword = LABEL_REF (STORE_CRW);
+
+ eas.s.ea_reg.s.srcabyte = LABEL_REFN (FETCH_REG_B, 0);
+ eas.s.ea_reg.s.srcaword = LABEL_REFN (FETCH_REG_W, 0);
+ eas.s.ea_reg.s.srcalong = LABEL_REFN (FETCH_REG_L, 0);
+
+ eas.s.ea_reg.s.srcbbyte = LABEL_REFN (FETCH_REG_B, 1);
+ eas.s.ea_reg.s.srcbword = LABEL_REFN (FETCH_REG_W, 1);
+ eas.s.ea_reg.s.srcblong = LABEL_REFN (FETCH_REG_L, 1);
+
+ eas.s.ea_reg.s.dstbyte = LABEL_REF (STORE_REG_B);
+ eas.s.ea_reg.s.dstword = LABEL_REF (STORE_REG_W);
+ eas.s.ea_reg.s.dstlong = LABEL_REF (STORE_REG_L);
+
+ eas.s.ea_inc.s.srcabyte = LABEL_REFN (FETCH_INC_B, 0);
+ eas.s.ea_inc.s.srcaword = LABEL_REFN (FETCH_INC_W, 0);
+ eas.s.ea_inc.s.srcbbyte = LABEL_REFN (FETCH_INC_B, 1);
+ eas.s.ea_inc.s.srcbword = LABEL_REFN (FETCH_INC_W, 1);
+ eas.s.ea_inc.s.dstbyte = LABEL_REF (STORE_INC_B);
+ eas.s.ea_inc.s.dstword = LABEL_REF (STORE_INC_W);
+
+ eas.s.ea_dec.s.srcabyte = LABEL_REFN (FETCH_DEC_B, 0);
+ eas.s.ea_dec.s.srcaword = LABEL_REFN (FETCH_DEC_W, 0);
+ eas.s.ea_dec.s.srcbbyte = LABEL_REFN (FETCH_DEC_B, 1);
+ eas.s.ea_dec.s.srcbword = LABEL_REFN (FETCH_DEC_W, 1);
+ eas.s.ea_dec.s.dstbyte = LABEL_REF (STORE_DEC_B);
+ eas.s.ea_dec.s.dstword = LABEL_REF (STORE_DEC_W);
+
+ eas.s.ea_disp.s.srcabyte = LABEL_REFN (FETCH_DISP_B, 0);
+ eas.s.ea_disp.s.srcaword = LABEL_REFN (FETCH_DISP_W, 0);
+ eas.s.ea_disp.s.srcbbyte = LABEL_REFN (FETCH_DISP_B, 1);
+ eas.s.ea_disp.s.srcbword = LABEL_REFN (FETCH_DISP_W, 1);
+ eas.s.ea_disp.s.dstbyte = LABEL_REF (STORE_DISP_B);
+ eas.s.ea_disp.s.dstword = LABEL_REF (STORE_DISP_W);
+
+ eas.s.ea_imm.s.srcabyte = LABEL_REFN (FETCH_IMM, 0);
+ eas.s.ea_imm.s.srcaword = LABEL_REFN (FETCH_IMM, 0);
+ eas.s.ea_imm.s.srcbbyte = LABEL_REFN (FETCH_IMM, 1);
+ eas.s.ea_imm.s.srcbword = LABEL_REFN (FETCH_IMM, 1);
+
+ flag_special = LABEL_REF (FLAG_special);
+ flag_mp = LABEL_REF (FLAG_m);
+ flag_Mp = LABEL_REF (FLAG_M);
+ flag_ap = LABEL_REF (FLAG_a);
+ flag_Ap = LABEL_REF (FLAG_A);
+ flag_nonep = LABEL_REF (FLAG_NONE);
+ flag_nostorep = LABEL_REF (FLAG_NOSTORE);
+ flag_clearp = LABEL_REF (FLAG_CLEAR);
+ flag_shiftbyte = LABEL_REF (FLAG_shiftbyte);
+ flag_shiftword = LABEL_REF (FLAG_shiftword);
+ flag_multbyte = LABEL_REF (FLAG_multbyte);
+ flag_multword = LABEL_REF (FLAG_multword);
+
+
+ exec_dispatch[O_ADDS] = LABEL_REF (O_ADDS);
+ exec_dispatch[O_ADDX] = LABEL_REF (O_ADDX);
+ exec_dispatch[O_ADD] = LABEL_REF (O_ADD);
+ exec_dispatch[O_ANDC] = LABEL_REF (O_ANDC);
+ exec_dispatch[O_AND] = LABEL_REF (O_AND);
+ exec_dispatch[O_BCC] = LABEL_REF (O_BCC);
+ exec_dispatch[O_BCLR] = LABEL_REF (O_BCLR);
+ exec_dispatch[O_BCS] = LABEL_REF (O_BCS);
+ exec_dispatch[O_BEQ] = LABEL_REF (O_BEQ);
+ exec_dispatch[O_BF] = LABEL_REF (O_BF);
+ exec_dispatch[O_BGE] = LABEL_REF (O_BGE);
+ exec_dispatch[O_BGT] = LABEL_REF (O_BGT);
+ exec_dispatch[O_BHI] = LABEL_REF (O_BHI);
+ exec_dispatch[O_BHS] = LABEL_REF (O_BHS);
+ exec_dispatch[O_BLE] = LABEL_REF (O_BLE);
+ exec_dispatch[O_BLO] = LABEL_REF (O_BLO);
+ exec_dispatch[O_BLS] = LABEL_REF (O_BLS);
+ exec_dispatch[O_BLT] = LABEL_REF (O_BLT);
+ exec_dispatch[O_BMI] = LABEL_REF (O_BMI);
+ exec_dispatch[O_BNE] = LABEL_REF (O_BNE);
+ exec_dispatch[O_BNOT] = LABEL_REF (O_BNOT);
+ exec_dispatch[O_BPL] = LABEL_REF (O_BPL);
+ exec_dispatch[O_BPT] = LABEL_REF (O_BPT);
+ exec_dispatch[O_BRA] = LABEL_REF (O_BRA);
+ exec_dispatch[O_BRN] = LABEL_REF (O_BRN);
+ exec_dispatch[O_BSET] = LABEL_REF (O_BSET);
+ exec_dispatch[O_BSR] = LABEL_REF (O_BSR);
+ exec_dispatch[O_BTST] = LABEL_REF (O_BTST);
+ exec_dispatch[O_BT] = LABEL_REF (O_BT);
+ exec_dispatch[O_BVC] = LABEL_REF (O_BVC);
+ exec_dispatch[O_BVS] = LABEL_REF (O_BVS);
+ exec_dispatch[O_CLR] = LABEL_REF (O_CLR);
+ exec_dispatch[O_CMP] = LABEL_REF (O_CMP);
+ exec_dispatch[O_DADD] = LABEL_REF (O_DADD);
+ exec_dispatch[O_DIVXU] = LABEL_REF (O_DIVXU);
+ exec_dispatch[O_DSUB] = LABEL_REF (O_DSUB);
+ exec_dispatch[O_EXTS] = LABEL_REF (O_EXTS);
+ exec_dispatch[O_EXTU] = LABEL_REF (O_EXTU);
+ exec_dispatch[O_JMP] = LABEL_REF (O_JMP);
+ exec_dispatch[O_JSR] = LABEL_REF (O_JSR);
+ exec_dispatch[O_LDC] = LABEL_REF (O_LDC);
+ exec_dispatch[O_LDM] = LABEL_REF (O_LDM);
+ exec_dispatch[O_LINK] = LABEL_REF (O_LINK);
+ exec_dispatch[O_MOVFPE] = LABEL_REF (O_MOVFPE);
+ exec_dispatch[O_MOVTPE] = LABEL_REF (O_MOVTPE);
+ exec_dispatch[O_MOV] = LABEL_REF (O_MOV);
+ exec_dispatch[O_MULXU] = LABEL_REF (O_MULXU);
+ exec_dispatch[O_NEG] = LABEL_REF (O_NEG);
+ exec_dispatch[O_NOP] = LABEL_REF (O_NOP);
+ exec_dispatch[O_NOT] = LABEL_REF (O_NOT);
+ exec_dispatch[O_ORC] = LABEL_REF (O_ORC);
+ exec_dispatch[O_OR] = LABEL_REF (O_OR);
+ exec_dispatch[O_PJMP] = LABEL_REF (O_PJMP);
+ exec_dispatch[O_PJSR] = LABEL_REF (O_PJSR);
+ exec_dispatch[O_PRTD] = LABEL_REF (O_PRTD);
+ exec_dispatch[O_PRTS] = LABEL_REF (O_PRTS);
+ exec_dispatch[O_RECOMPILE] = LABEL_REF (O_RECOMPILE);
+
+ exec_dispatch[O_ROTL] = LABEL_REF (O_ROTL);
+ exec_dispatch[O_ROTR] = LABEL_REF (O_ROTR);
+ exec_dispatch[O_ROTXL] = LABEL_REF (O_ROTXL);
+ exec_dispatch[O_ROTXR] = LABEL_REF (O_ROTXR);
+
+ exec_dispatch[O_RTD] = LABEL_REF (O_RTD);
+ exec_dispatch[O_RTS] = LABEL_REF (O_RTS);
+ exec_dispatch[O_SCB_EQ] = LABEL_REF (O_SCB_EQ);
+ exec_dispatch[O_SCB_F] = LABEL_REF (O_SCB_F);
+ exec_dispatch[O_SCB_NE] = LABEL_REF (O_SCB_NE);
+ exec_dispatch[O_SHAL] = LABEL_REF (O_SHAL);
+ exec_dispatch[O_SHAR] = LABEL_REF (O_SHAR);
+ exec_dispatch[O_SHLL] = LABEL_REF (O_SHLL);
+ exec_dispatch[O_SHLR] = LABEL_REF (O_SHLR);
+
+ exec_dispatch[O_SLEEP] = LABEL_REF (O_SLEEP);
+ exec_dispatch[O_STC] = LABEL_REF (O_STC);
+ exec_dispatch[O_STM] = LABEL_REF (O_STM);
+ exec_dispatch[O_SUBS] = LABEL_REF (O_SUBS);
+ exec_dispatch[O_SUBX] = LABEL_REF (O_SUBX);
+ exec_dispatch[O_SUB] = LABEL_REF (O_SUB);
+ exec_dispatch[O_SWAP] = LABEL_REF (O_SWAP);
+ exec_dispatch[O_TAS] = LABEL_REF (O_TAS);
+ exec_dispatch[O_TRAPA] = LABEL_REF (O_TRAPA);
+ exec_dispatch[O_TRAP_VS] = LABEL_REF (O_TRAP_VS);
+ exec_dispatch[O_TST] = LABEL_REF (O_TST);
+ exec_dispatch[O_UNLK] = LABEL_REF (O_UNLK);
+ exec_dispatch[O_XCH] = LABEL_REF (O_XCH);
+ exec_dispatch[O_XORC] = LABEL_REF (O_XORC);
+ exec_dispatch[O_XOR] = LABEL_REF (O_XOR);
+ nop.type = eas.s.ea_nop.s.srcabyte;
+ cpu.cache[0].opcode = exec_dispatch[O_RECOMPILE];
+ cpu.cache[0].srca.type = eas.s.ea_nop.s.srcabyte;
+ cpu.cache[0].srcb.type = eas.s.ea_nop.s.srcbbyte;
+ }
+
+ prev = signal (SIGINT, control_c);
+ prev_seg = signal (SIGSEGV, segv);
+
+ if (step)
+ {
+ cpu.exception = SIGTRAP;
+ }
+ else
+ {
+ cpu.exception = 0;
+ }
+
+ pc = cpu.regs[R_PC].s[LOW] + (NORMAL_CP << 16);
+
+ GETSR ();
+
+ if (setjmp (jbuf) == 0) {
+ do
+ {
+ int cidx;
+ decoded_inst *code;
+
+ top:
+ cidx = cpu.cache_idx[pc];
+ code = cpu.cache + cidx;
+
+ FETCH (arga, code->srca, 0);
+ FETCH (argb, code->srcb, 1);
+
+
+
+#ifdef DEBUG
+ if (debug)
+ {
+ printf ("%x %d %s\n", pc, code->opcode,
+ code->op ? code->op->name : "**");
+ }
+#endif
+
+ cycles += code->cycles;
+ insts++;
+ DISPATCH (code->opcode)
+ {
+ LABEL (O_RECOMPILE):
+ /* This opcode is a fake for when we get to an instruction which
+ hasn't been compiled */
+ compile (pc);
+ goto top;
+ break;
+ LABEL (O_NEG):
+ arga = -arga;
+ argb = 0;
+ res = arga + argb;
+ break;
+ LABEL (O_SUBX):
+ arga += C;
+ LABEL (O_SUB):
+ LABEL (O_SUBS):
+ arga = -arga;
+ LABEL (O_ADD):
+ LABEL (O_ADDS):
+ res = arga + argb;
+ break;
+
+ LABEL (O_ADDX):
+ res = arga + argb + C;
+ break;
+
+ LABEL (O_AND):
+ LABEL (O_ANDC):
+ res = arga & argb;
+ break;
+ break;
+
+ LABEL (O_BCLR):
+ arga &= 0xf;
+ bit = (argb & (1 << arga));
+ res = argb & ~(1 << arga);
+ goto bitop;
+
+
+ LABEL (O_BRA):
+ LABEL (O_BT):
+ if (1)
+ goto condtrue;
+
+ LABEL (O_BRN):
+ LABEL (O_BF):
+ if (0)
+ goto condtrue;
+ break;
+
+ LABEL (O_BHI):
+ if ((C || Z) == 0)
+ goto condtrue;
+ break;
+
+ LABEL (O_BLS):
+ if ((C || Z))
+ goto condtrue;
+ break;
+
+ LABEL (O_BCS):
+ LABEL (O_BLO):
+ if ((C == 1))
+ goto condtrue;
+ break;
+
+ LABEL (O_BCC):
+ LABEL (O_BHS):
+ if ((C == 0))
+ goto condtrue;
+ break;
+
+ LABEL (O_BEQ):
+ if (Z)
+ goto condtrue;
+ break;
+ LABEL (O_BGT):
+ if (((Z || (N ^ V)) == 0))
+ goto condtrue;
+ break;
+
+
+ LABEL (O_BLE):
+ if (((Z || (N ^ V)) == 1))
+ goto condtrue;
+ break;
+
+ LABEL (O_BGE):
+ if ((N ^ V) == 0)
+ goto condtrue;
+ break;
+ LABEL (O_BLT):
+ if ((N ^ V))
+ goto condtrue;
+ break;
+ LABEL (O_BMI):
+ if ((N))
+ goto condtrue;
+ break;
+ LABEL (O_BNE):
+ if ((Z == 0))
+ goto condtrue;
+ break;
+ LABEL (O_BPL):
+ if (N == 0)
+ goto condtrue;
+ break;
+ break;
+ LABEL (O_BVC):
+ if ((V == 0))
+ goto condtrue;
+ break;
+ LABEL (O_BVS):
+ if ((V == 1))
+ goto condtrue;
+ break;
+
+ LABEL (O_BNOT):
+ bit = argb & (1<<(arga & 0xf));
+ res = argb ^ (1<<(arga & 0xf));
+ goto bitop;
+ break;
+
+ LABEL (O_BSET):
+ arga = 1 << (arga & 0xf);
+ bit = argb & arga;
+ res = argb | arga;
+ goto bitop;
+ break;
+
+ LABEL (O_PJMP):
+ pc = arga;
+ goto next;
+
+ LABEL (O_UNLK):
+ {
+ int t;
+ SET_NORMREG (R7, GET_NORMREG (R6));
+ POPWORD (t);
+ SET_NORMREG (R6, t);
+ pc = code->next_pc;
+ goto next;
+ }
+
+ LABEL (O_RTS):
+ {
+ int cp = pc & 0xff0000;
+ POPWORD (pc);
+ pc |= cp;
+ goto next;
+ }
+ break;
+
+ LABEL (O_PRTS):
+ {
+ int cp;
+ int off;
+ POPWORD (cp);
+ POPWORD (off);
+ cp <<= 16;
+ SET_SEGREG (R_CP, cp);
+ pc = cp + off;
+ }
+ goto next;
+
+ LABEL (O_PJSR):
+ PUSHWORD (argb & 0xffff);
+ PUSHWORD (argb >> 16);
+ pc = (arga & 0xffffff);
+ goto next;
+
+ LABEL (O_BSR):
+ LABEL (O_JSR):
+ PUSHWORD (code->next_pc);
+ pc = arga | (pc & 0xff0000);
+ goto next;
+
+ LABEL (O_BTST):
+ Z = (((argb >> (arga & 0xf)) & 1) == 0);
+ pc = code->next_pc;
+ goto next;
+
+ LABEL (O_CLR):
+ res = 0;
+ break;
+
+ LABEL (O_CMP):
+ arga = -arga;
+ res = arga + argb;
+ break;
+
+ LABEL (O_DADD):
+ res = arga + argb + C;
+ if (res > 99)
+ {
+ res -= 100;
+ C = 1;
+ }
+ else
+ {
+ C = 0;
+ }
+ Z = Z && (res == 0);
+ break;
+
+
+ LABEL (O_DSUB):
+ res = argb - arga - C;
+ if (res < 0)
+ {
+ res += 100;
+ C = 1;
+ }
+ else
+ {
+ C = 0;
+ }
+ Z = Z && (res == 0);
+ break;
+
+ LABEL (O_EXTS):
+ res = SEXTCHAR (arga);
+ break;
+
+ LABEL (O_EXTU):
+ res = (unsigned char) arga;
+ break;
+
+ LABEL (O_JMP):
+ pc = arga | (pc & 0xff0000);
+ goto next;
+ break;
+
+ LABEL (O_LDM):
+
+ for (tmp = 0; tmp < 7; tmp++)
+ {
+ if (argb & (1 << tmp))
+ {
+ POPWORD (cpu.regs[tmp].s[LOW]);
+ }
+ }
+ if (argb & 0x80)
+ POPWORD (tmp); /* dummy ready for sp */
+ goto nextpc;
+ break;
+
+ LABEL (O_LINK):
+ PUSHWORD (cpu.regs[R6].s[LOW]);
+ cpu.regs[R6].s[LOW] = cpu.regs[R7].s[LOW];
+ cpu.regs[R7].s[LOW] += argb;
+ goto nextpc;
+
+ LABEL (O_STC):
+ LABEL (O_LDC):
+ LABEL (O_MOVFPE):
+ LABEL (O_MOVTPE):
+ LABEL (O_MOV):
+ LABEL (O_TST):
+ res = arga;
+ break;
+
+ LABEL (O_TRAPA):
+ if (arga == 15)
+ {
+ trap ();
+ }
+ else
+ {
+ PUSHWORD (pc & 0xffff);
+ if (cpu.maximum)
+ {
+ PUSHWORD (NORMAL_CP);
+ }
+ PUSHWORD (NORMAL_SR);
+ if (cpu.maximum)
+ {
+ arga = arga * 4 + 0x40;
+ SET_NORMAL_CPPC (longat (cpu.memory + arga));
+ }
+ else
+ {
+ arga = arga * 2 + 0x20;
+ SET_NORMAL_CPPC (wordat (cpu.memory + arga));
+ }
+ }
+ break;
+
+ LABEL (O_OR):
+ LABEL (O_ORC):
+ res = arga | argb;
+ break;
+
+ LABEL (O_XOR):
+ LABEL (O_XORC):
+ res = arga ^ argb;
+ break;
+
+ LABEL (O_SCB_F):
+ {
+ scb_f:
+ res = arga - 1;
+ code->srca.reg.wptr[0] = res;
+ if (res != -1)
+ {
+ pc = argb;
+ goto next;
+ }
+ }
+ break;
+
+ LABEL (O_SCB_EQ):
+ if (Z == 1)
+ break;
+ else
+ goto scb_f;
+
+ LABEL (O_SCB_NE):
+ if (Z == 0)
+ break;
+ else
+ goto scb_f;
+
+ LABEL (O_NOP):
+ /* If only they were all as simple as this */
+ break;
+
+ LABEL (O_ROTL):
+ res = arga << 1;
+ C = (res >> argb) & 1;
+ res |= C;
+ break;
+
+
+ LABEL (O_ROTR):
+ C = arga & 1;
+ res = arga >> 1;
+ res |= (C << (argb - 1));
+ break;
+
+ LABEL (O_ROTXL):
+ res = arga << 1;
+ res |= C;
+ C = (res >> argb) & 1;
+ break;
+
+ LABEL (O_ROTXR):
+ res = arga >> 1;
+ res |= (C << (argb - 1));
+ C = arga & 1;
+ break;
+
+ LABEL (O_SHAL):
+ res = arga << 1;
+ if (argb == 16)
+ {
+ C = (res >> (16)) & 1;
+ Z = ((res & 0xffff) == 0);
+ N = ((res & 0x8000) != 0);
+ }
+
+ else
+ {
+ C = (res >> (8)) & 1;
+ Z = ((res & 0xff) == 0);
+ N = ((res & 0x80) != 0);
+
+ }
+ V = C ^ N;
+ goto none;
+
+ LABEL (O_SHAR):
+ C = arga & 1;
+ if (argb == 16)
+ {
+ res = ((short) arga) >> 1;
+ }
+ else
+ {
+ res = (SEXTCHAR (arga)) >> 1;
+ }
+ break;
+
+ LABEL (O_SHLL):
+ res = arga << 1;
+ C = (res >> argb) & 1;
+ break;
+
+ LABEL (O_SHLR):
+ C = arga & 1;
+ res = arga >> 1;
+ break;
+
+ LABEL (O_DIVXU):
+ if (arga == 0)
+ {
+ N = V = C = 0;
+ Z = 1;
+ cpu.exception = SIGILL;
+ }
+ else
+ {
+ int d = argb / arga;
+ int m = argb % arga;
+ if (code->dst.type == eas.s.ea_reg.s.dstlong)
+ {
+ res = (m << 16) | (d & 0xffff);
+ }
+ else
+ {
+ res = (m << 8) | (d & 0xff);
+ }
+
+ }
+ break;
+
+ LABEL (O_MULXU):
+ res = arga * argb;
+ break;
+
+ LABEL (O_NOT):
+ res = ~arga;
+ break;
+
+ LABEL (O_SWAP):
+ res = ((arga >> 8) & 0xff) | ((arga << 8) & 0xff00);
+ break;
+
+
+ LABEL (O_STM):
+ for (tmp = 7; tmp >= 0; tmp--)
+ {
+ if (arga & (1 << tmp))
+ {
+ PUSHWORD (cpu.regs[tmp].s[LOW]);
+ }
+ }
+ goto nextpc;
+
+ LABEL (O_TAS):
+ C = 0;
+ V = 0;
+ Z = arga == 0;
+ N = arga < 0;
+ res = arga | 0x80;
+ goto none;
+
+ LABEL (O_PRTD):
+ LABEL (O_XCH):
+ LABEL (O_RTD):
+ cpu.exception = SIGILL;
+ goto next;
+
+ LABEL (O_TRAP_VS):
+ LABEL (O_SLEEP):
+ LABEL (O_BPT):
+ cpu.exception = SIGTRAP;
+ goto next;
+ break;
+ }
+
+ ENDDISPATCH;
+
+ DISPATCH (code->flags)
+ {
+ bitop:
+ Z = (res & bit) == 0;
+ pc = code->next_pc;
+ break;
+ LABEL (FLAG_multword):
+ Z = (res & 0xffff) == 0;
+ N = (res & 0x8000) != 0;
+ V = 0;
+ C = 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_multbyte):
+ /* 8*8 -> 16 */
+ Z = (res & 0xff) == 0;
+ N = (res & 0x80) != 0;
+ V = 0;
+ C = 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_shiftword):
+ N = (res & 0x8000) != 0;
+ Z = (res & 0xffff) == 0;
+ V = 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_shiftbyte):
+ N = (res & 0x80) != 0;
+ Z = (res & 0xff) == 0;
+ V = 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_special):
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_m):
+ /* Move byte flags */
+ /* after a logical instruction */
+ N = (res & 0x80) != 0;
+ Z = (res & 0xff) == 0;
+ V = (((~arga & ~argb & res) | (arga & argb & ~res)) & 0x80) != 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_M):
+ /* Move word flags */
+ /* after a logical instruction */
+ N = (res & 0x8000) != 0;
+ Z = (res & 0xffff) == 0;
+ V = (((~arga & ~argb & res) | (arga & argb & ~res)) & 0x8000) != 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_a):
+ /* after byte sized arith */
+ C = (res & 0x100) != 0;
+ N = (res & 0x80) != 0;
+ Z = (res & 0xff) == 0;
+ V = (((~arga & ~argb & res) | (arga & argb & ~res)) & 0x80) != 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_A):
+ /* after word sized arith */
+ C = (res & 0x10000) != 0;
+ N = (res & 0x8000) != 0;
+ Z = (res & 0xffff) == 0;
+ V = (((~arga & ~argb & res) | (arga & argb & ~res)) & 0x8000) != 0;
+ pc = code->next_pc;
+ break;
+
+ LABEL (FLAG_NONE):
+ none:;
+ /* no flags but store */
+ pc = code->next_pc;
+ break;
+ LABEL (FLAG_NOSTORE):
+ /* no flags and no store */
+ pc = code->next_pc;
+ break;
+ LABEL (FLAG_CLEAR):
+ /* clear flags */
+ N = 0;
+ Z = 1;
+ V = 0;
+ C = 0;
+ pc = code->next_pc;
+ break;
+ condtrue:
+ pc = arga;
+ goto next;
+ }
+ ENDDISPATCH;
+
+ DISPATCH (code->dst.type)
+ {
+ unsigned char *lval;
+
+ LABEL (STORE_CRB):
+ (*(code->dst.reg.segptr)) = cpu.memory + (res << 16);
+ break;
+
+ LABEL (STORE_NOP):
+ break;
+
+ LABEL (STORE_REG_B):
+ (*(code->dst.reg.bptr)) = res;
+ break;
+
+ LABEL (STORE_REG_W):
+ (*(code->dst.reg.wptr)) = res;
+ break;
+
+ LABEL (STORE_REG_L):
+ {
+ int l, r;
+
+ r = (union rtype *) (code->dst.reg.wptr) - &cpu.regs[0];
+ r++;
+ *(code->dst.reg.wptr) = res >> 16;
+ cpu.regs[r].s[LOW] = res & 0xffff;
+
+ }
+
+ break;
+
+ LABEL (STORE_DISP_W):
+ lval = displval (code->dst);
+ setwordat (lval, res);
+ break;
+
+ LABEL (STORE_DISP_B):
+ lval = displval (code->dst);
+ setbyteat (lval, res);
+ break;
+
+ LABEL (STORE_INC_B):
+ lval = elval (code->dst, 0);
+ setbyteat (lval, res);
+ (*(code->dst.reg.wptr))++;
+ break;
+
+ LABEL (STORE_INC_W):
+ lval = elval (code->dst, 0);
+ setwordat (lval, res);
+ (*(code->dst.reg.wptr)) += 2;
+ break;
+
+ LABEL (STORE_DEC_B):
+ (*(code->dst.reg.wptr))--;
+ lval = elval (code->dst, 0);
+ setbyteat (lval, res);
+ break;
+
+ LABEL (STORE_CRW):
+ /* Make an up to date sr from the flag state */
+ cpu.regs[R_SR].s[LOW] = res;
+ GETSR ();
+ break;
+
+ LABEL (STORE_DEC_W):
+ (*(code->dst.reg.wptr)) -= 2;
+ lval = elval (code->dst, 0);
+ setwordat (lval, res);
+
+ break;
+
+ nextpc:
+ pc = code->next_pc;
+
+ }
+ ENDDISPATCH;
+ next:;
+ }
+ while (!cpu.exception);
+ }
+
+ cpu.ticks += get_now () - tick_start;
+ cpu.cycles += cycles;
+ cpu.insts += insts;
+ cpu.regs[R_PC].s[LOW] = pc;
+ BUILDSR ();
+
+ signal (SIGINT, prev);
+ signal (SIGSEGV, prev_seg);
+}
+
+
+
+
+int
+sim_write (sd, addr, buffer, size)
+ SIM_DESC sd;
+ SIM_ADDR addr;
+ unsigned char *buffer;
+ int size;
+{
+ int i;
+
+ init_pointers ();
+ if (addr < 0 || addr + size > H8500_MSIZE)
+ return 0;
+ for (i = 0; i < size; i++)
+ {
+ cpu.memory[addr + i] = buffer[i];
+ cpu.cache_idx[addr + i] = 0;
+ }
+ return size;
+}
+
+int
+sim_read (sd, addr, buffer, size)
+ SIM_DESC sd;
+ SIM_ADDR addr;
+ unsigned char *buffer;
+ int size;
+{
+ init_pointers ();
+ if (addr < 0 || addr + size > H8500_MSIZE)
+ return 0;
+ memcpy (buffer, cpu.memory + addr, size);
+ return size;
+}
+
+/* Ripped off from tm-h8500.h */
+
+#define R0_REGNUM 0
+#define R1_REGNUM 1
+#define R2_REGNUM 2
+#define R3_REGNUM 3
+#define R4_REGNUM 4
+#define R5_REGNUM 5
+#define R6_REGNUM 6
+#define R7_REGNUM 7
+
+/* As above, but with correct seg register glued on */
+#define PR0_REGNUM 8
+#define PR1_REGNUM 9
+#define PR2_REGNUM 10
+#define PR3_REGNUM 11
+#define PR4_REGNUM 12
+#define PR5_REGNUM 13
+#define PR6_REGNUM 14
+#define PR7_REGNUM 15
+
+#define SP_REGNUM PR7_REGNUM /* Contains address of top of stack */
+#define FP_REGNUM PR6_REGNUM /* Contains address of executing stack frame */
+
+
+#define SEG_C_REGNUM 16 /* Segment registers */
+#define SEG_D_REGNUM 17
+#define SEG_E_REGNUM 18
+#define SEG_T_REGNUM 19
+
+#define CCR_REGNUM 20 /* Contains processor status */
+#define PC_REGNUM 21 /* Contains program counter */
+
+#define CYCLE_REGNUM 22
+#define INST_REGNUM 23
+#define TICK_REGNUM 24
+
+int
+sim_store_register (sd, rn, value, length)
+ SIM_DESC sd;
+ int rn;
+ unsigned char *value;
+ int length;
+{
+ int seg = 0;
+ int reg = -1;
+
+ init_pointers ();
+ switch (rn)
+ {
+ case PC_REGNUM:
+ SET_SEGREG (R_CP, (value[1]<<16));
+ cpu.regs[R_PC].s[LOW] = (value[2] << 8) | value[3];
+ break;
+ case SEG_C_REGNUM:
+ case SEG_D_REGNUM:
+ case SEG_E_REGNUM:
+ case SEG_T_REGNUM:
+ seg = rn - SEG_C_REGNUM + R_CP;
+ reg = -1;
+ break;
+ default:
+ abort ();
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R2_REGNUM:
+ case R3_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ case R6_REGNUM:
+ case R7_REGNUM:
+ seg = 0;
+ reg = rn - R0_REGNUM;
+ break;
+ case CCR_REGNUM:
+ seg = 0;
+ reg = R_SR;
+ break;
+ case CYCLE_REGNUM:
+ cpu.cycles = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
+ return;
+ case INST_REGNUM:
+ cpu.insts = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
+ return;
+ case TICK_REGNUM:
+ cpu.ticks = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
+ return;
+ case PR0_REGNUM:
+ case PR1_REGNUM:
+ case PR2_REGNUM:
+ case PR3_REGNUM:
+ case PR4_REGNUM:
+ case PR5_REGNUM:
+ case PR6_REGNUM:
+ case PR7_REGNUM:
+ SET_SEGREG (segforreg[rn], value[1]);
+ reg = rn - PR0_REGNUM;
+ cpu.regs[reg].s[LOW] = (value[2] << 8) | value[3];
+ return;
+ }
+
+ if (seg)
+ SET_SEGREG (seg, value[0] << 16);
+
+ if (reg > 0)
+ {
+ cpu.regs[reg].s[LOW] = (value[0] << 8) | value[1];
+ }
+ return -1;
+}
+
+int
+sim_fetch_register (sd, rn, buf, length)
+ SIM_DESC sd;
+ int rn;
+ unsigned char *buf;
+ int length;
+{
+ init_pointers ();
+
+ switch (rn)
+ {
+ default:
+ abort ();
+ case SEG_C_REGNUM:
+ case SEG_D_REGNUM:
+ case SEG_E_REGNUM:
+ case SEG_T_REGNUM:
+ buf[0] = GET_SEGREG(rn - SEG_C_REGNUM + R_CP);
+ break;
+ case CCR_REGNUM:
+ buf[0] = cpu.regs[R_SR].s[HIGH];
+ buf[1] = cpu.regs[R_SR].s[LOW];
+ break;
+ case PC_REGNUM:
+ buf[0] = 0;
+ buf[1] = GET_SEGREG(R_CP);
+ buf[2] = HIGH_BYTE (cpu.regs[R_PC].s[LOW]);
+ buf[3] = LOW_BYTE (cpu.regs[R_PC].s[LOW]);
+ break;
+
+ case PR0_REGNUM:
+ case PR1_REGNUM:
+ case PR2_REGNUM:
+ case PR3_REGNUM:
+ case PR4_REGNUM:
+ case PR5_REGNUM:
+ case PR6_REGNUM:
+ case PR7_REGNUM:
+ rn -= PR0_REGNUM;
+ buf[0] = 0;
+ buf[1] = GET_SEGREG(segforreg[rn]);
+ buf[2] = HIGH_BYTE (cpu.regs[rn].s[LOW]);
+ buf[3] = LOW_BYTE (cpu.regs[rn].s[LOW]);
+ break;
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R2_REGNUM:
+ case R3_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ case R6_REGNUM:
+ case R7_REGNUM:
+ buf[0] = HIGH_BYTE (cpu.regs[rn].s[LOW]);
+ buf[1] = LOW_BYTE (cpu.regs[rn].s[LOW]);
+ break;
+ case CYCLE_REGNUM:
+ buf[0] = cpu.cycles >> 24;
+ buf[1] = cpu.cycles >> 16;
+ buf[2] = cpu.cycles >> 8;
+ buf[3] = cpu.cycles >> 0;
+ break;
+
+ case TICK_REGNUM:
+ buf[0] = cpu.ticks >> 24;
+ buf[1] = cpu.ticks >> 16;
+ buf[2] = cpu.ticks >> 8;
+ buf[3] = cpu.ticks >> 0;
+ break;
+
+ case INST_REGNUM:
+ buf[0] = cpu.insts >> 24;
+ buf[1] = cpu.insts >> 16;
+ buf[2] = cpu.insts >> 8;
+ buf[3] = cpu.insts >> 0;
+ break;
+ }
+ return -1;
+}
+
+int
+sim_trace (sd)
+ SIM_DESC sd;
+{
+
+ int i;
+
+ for (i = 0; i < 12; i += 2)
+ {
+ unsigned char *p = cpu.regs[R_TP].c + ((cpu.regs[R6].s[LOW] + i) & 0xffff);
+ unsigned short *j = (unsigned short *) p;
+
+ printf ("%04x ", *j);
+ }
+ printf ("\n");
+ printf ("%02x %02x %02x %02x:%04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ NORMAL_DP,
+ NORMAL_EP,
+ NORMAL_TP,
+ NORMAL_CP,
+ cpu.regs[R_PC].s[LOW],
+ cpu.regs[0].s[LOW],
+ cpu.regs[1].s[LOW],
+ cpu.regs[2].s[LOW],
+ cpu.regs[3].s[LOW],
+ cpu.regs[4].s[LOW],
+ cpu.regs[5].s[LOW],
+ cpu.regs[6].s[LOW],
+ cpu.regs[7].s[LOW]);
+ sim_resume (sd, 1, 0);
+ return 0;
+}
+
+void
+sim_stop_reason (sd, reason, sigrc)
+ SIM_DESC sd;
+ enum sim_stop *reason;
+ int *sigrc;
+{
+ *reason = sim_stopped;
+ *sigrc = cpu.exception;
+}
+
+void
+sim_set_simcache_size (n)
+{
+ if (cpu.cache)
+ free (cpu.cache);
+ if (n < 2)
+ n = 2;
+ cpu.cache = (decoded_inst *) malloc (sizeof (decoded_inst) * n);
+ cpu.csize = n;
+}
+
+void
+sim_size (n)
+ int n;
+{
+ /* Fixed size. */
+}
+
+void
+sim_info (sd, verbose)
+ SIM_DESC sd;
+ int verbose;
+{
+ double timetaken = (double) cpu.ticks / (double) now_persec ();
+ double virttime = cpu.cycles / 10.0e6;
+
+ (*sim_callback->printf_filtered) (sim_callback,
+ "\n\ninstructions executed %10d\n",
+ cpu.insts);
+ (*sim_callback->printf_filtered) (sim_callback,
+ "cycles (v approximate) %10d\n",
+ cpu.cycles);
+ (*sim_callback->printf_filtered) (sim_callback,
+ "real time taken %10.4f\n",
+ timetaken);
+ (*sim_callback->printf_filtered) (sim_callback,
+ "virtual time taked %10.4f\n",
+ virttime);
+ if (timetaken)
+ {
+ (*sim_callback->printf_filtered) (sim_callback,
+ "simulation ratio %10.4f\n",
+ virttime / timetaken);
+ }
+
+ (*sim_callback->printf_filtered) (sim_callback,
+ "compiles %10d\n",
+ cpu.compiles);
+ (*sim_callback->printf_filtered) (sim_callback,
+ "cache size %10d\n",
+ cpu.csize);
+}
+
+SIM_DESC
+sim_open (kind, cb, abfd, argv)
+ SIM_OPEN_KIND kind;
+ host_callback *cb;
+ struct _bfd *abfd;
+ char **argv;
+{
+ sim_kind = kind;
+ myname = argv[0];
+ sim_callback = cb;
+ /* fudge our descriptor */
+ return (SIM_DESC) 1;
+}
+
+void
+sim_close (sd, quitting)
+ SIM_DESC sd;
+ int quitting;
+{
+ /* nothing to do */
+}
+
+SIM_RC
+sim_load (sd, prog, abfd, from_tty)
+ SIM_DESC sd;
+ char *prog;
+ bfd *abfd;
+ int from_tty;
+{
+ extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
+ bfd *prog_bfd;
+
+ prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
+ sim_kind == SIM_OPEN_DEBUG,
+ 0, sim_write);
+ if (prog_bfd == NULL)
+ return SIM_RC_FAIL;
+ if (abfd == NULL)
+ bfd_close (prog_bfd);
+ return SIM_RC_OK;
+}
+
+SIM_RC
+sim_create_inferior (sd, abfd, argv, env)
+ SIM_DESC sd;
+ struct _bfd *abfd;
+ char **argv;
+ char **env;
+{
+ int pc;
+ bfd_vma start_address;
+ if (abfd != NULL)
+ start_address = bfd_get_start_address (abfd);
+ else
+ start_address = 0;
+
+ /* ??? We assume this is a 4 byte quantity. */
+ pc = start_address;
+
+ sim_store_register (sd, PC_REGNUM, (unsigned char *) &pc, 4);
+ return SIM_RC_OK;
+}
+
+void
+sim_do_command (sd, cmd)
+ SIM_DESC sd;
+ char *cmd;
+{
+ (*sim_callback->printf_filtered) (sim_callback,
+ "This simulator does not accept any commands.\n");
+}
+
+void
+sim_set_callbacks (ptr)
+ struct host_callback_struct *ptr;
+{
+ sim_callback = ptr;
+}