| /* 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 "gdb/callback.h" |
| #include "gdb/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; |
| } |