diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
commit | c906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch) | |
tree | a0015aa5cedc19ccbab307251353a41722a3ae13 /sim/z8k/support.c | |
parent | cd946cff9ede3f30935803403f06f6ed30cad136 (diff) | |
download | gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2 |
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'sim/z8k/support.c')
-rw-r--r-- | sim/z8k/support.c | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/sim/z8k/support.c b/sim/z8k/support.c new file mode 100644 index 0000000..7392364 --- /dev/null +++ b/sim/z8k/support.c @@ -0,0 +1,784 @@ +/* support routines for interpreted instructions + Copyright (C) 1992, 1993 Free Software Foundation, Inc. + +This file is part of Z8KSIM + +Z8KSIM is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +Z8KSIM is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Z8KZIM; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" + +#include <ansidecl.h> +#include <signal.h> +#include <errno.h> + +#include "tm.h" +#include "sim.h" +#include "mem.h" +#include <stdio.h> +#ifdef HAVE_TIME_H +#include <time.h> +#endif +#ifdef HAVE_SYS_TIMES_H +#include <sys/times.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include "callback.h" +#include "remote-sim.h" +#include "syscall.h" + +static int get_now PARAMS ((void)); +static int now_persec PARAMS ((void)); +static int put_long PARAMS ((sim_state_type * context, int ptr, int value)); +static int put_short PARAMS ((sim_state_type * context, int ptr, int value)); + +int sim_z8001_mode; + +static int +get_now () +{ +#ifdef HAVE_SYS_TIMES_H + struct tms b; + + times (&b); + return b.tms_utime + b.tms_stime; +#else + return time (0); +#endif +} + +static int +now_persec () +{ + return 50; +} + + +/* #define LOG /* define this to print instruction use counts */ + +#ifdef __GNUC__ +#define INLINE __inline__ +#include "inlines.h" +#else +#include "inlines.h" +#endif + +/* This holds the entire cpu context */ +static sim_state_type the_state; + +int +fail (context, dummy) + sim_state_type *context; + int dummy; +{ + context->exception = SIM_BAD_INST; + return 1; +} + +void +sfop_bad1 (context) + sim_state_type *context; +{ + context->exception + = SIM_BAD_INST; +} + +void +bfop_bad1 (context) + sim_state_type *context; +{ + context->exception + = SIM_BAD_INST; +} + +void +fop_bad (context) + sim_state_type *context; +{ + context->exception = + SIM_BAD_INST; +} + +/* Table of bit counts for all byte values */ + +char the_parity[256] = +{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, + 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, + 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, + 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, + 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, + 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, + 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, + 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, + 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, + 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, + 7, 7, 8}; + + +int read (); +int write (); +int open (); +int close (); +int open (); +int close (); + +int link (); +int fstat (); + +static int +put_short (context, ptr, value) + sim_state_type *context; + int ptr; + int value; +{ + put_word_mem_da (context, ptr, value); + return ptr + 2; +} + +static int +put_long (context, ptr, value) + sim_state_type *context; + int + ptr; + int value; +{ + put_long_mem_da (context, ptr, value); + return ptr + 4; +} + +#define aptr(x) ((sitoptr(x)) + (char *)(context->memory)) + +static int args[3]; +static int arg_index; /* Translate a z8k system call into a host system call */ +void +support_call (context, sc) + sim_state_type *context; + int sc; +{ + extern int errno; + int ret; + int retnext = 0; + int fd; + + int olderrno = errno; + errno = 0; + switch (sc) + { + case SYS_ARG: + args[arg_index++] = context->regs[0].word << 16 | context->regs[1].word; + break; + case SYS_exit: + context->exception = SIM_DONE; + ret = args[0]; + arg_index = 0; + break; + case SYS_close: + ret = close ((int) (args[0])); + arg_index = 0; + break; + case SYS_creat: + ret = creat (aptr (args[0]), args[1]); + arg_index = 0; + break; + case SYS_isatty: + ret = isatty (args[0]); + arg_index = 0; + break; + case SYS_open: + ret = open (aptr (args[0]), args[1], args[2]); + arg_index = 0; + break; + case SYS_lseek: + ret = lseek (args[0], (off_t) args[1], args[2]); + arg_index = 0; + break; + case SYS_read: + ret = read (args[0], aptr (args[1]), args[2]); + arg_index = 0; + break; + case SYS_write: + ret = write (args[0],aptr (args[1]), args[2]); + arg_index = 0; + break; + case SYS_time: + { + int dst = args[0]; + + ret = time (0); + if (dst) + { + put_long_mem_da (context, + sitoptr (dst), ret); + } + retnext = ret; + ret = retnext >> 16; + arg_index = 0; + } + break; + case SYS_fstat: + { + int buf; + struct stat host_stat; + fd = args[0]; + buf = sitoptr (args[1]); + ret = fstat (fd, &host_stat); + buf = put_short (context, buf, host_stat.st_dev); + buf = put_short (context, buf, host_stat.st_ino); + /* FIXME: Isn't mode_t 4 bytes? */ + buf = put_short (context, buf, host_stat.st_mode); + buf = put_short (context, buf, host_stat.st_nlink); + buf = put_short (context, buf, host_stat.st_uid); + buf = put_short (context, buf, host_stat.st_uid); + buf = put_short (context, buf, host_stat.st_rdev); + buf = put_long (context, buf, host_stat.st_size); + buf = put_long (context, buf, host_stat.st_atime); + arg_index = 0; + } break; + default: + case SYS_link: + context->exception = SIM_BAD_SYSCALL; + arg_index = 0; + break; + } + context->regs[2].word = ret; + context->regs[3].word = retnext; + context->regs[5].word = errno; + + + /* support for the stdcall calling convention */ + context->regs[6].word = retnext; + context->regs[7].word = ret; + + errno = olderrno; +} + +#undef get_word_mem_da + +int +get_word_mem_da (context, addr) + sim_state_type *context; + int addr; +{ + return (get_byte_mem_da (context, addr) << 8) | (get_byte_mem_da (context, addr + 1)); + +} + +#undef get_word_reg +int +get_word_reg (context, reg) sim_state_type +* context; + int reg; +{ + return context->regs[reg].word; +} + +#ifdef LOG +int log[64 * 1024]; + +#endif + +void +tm_store_register (regno, value) + int regno; + int value; +{ + switch + (regno) + { + case REG_PC: + the_state.sometimes_pc = value; + break; + + default: + put_word_reg (&the_state, regno, value); + } +} + +void +swap_long (buf, val) + char *buf; + int val; +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val >> 0; +} + +void +swap_word (buf, val) + char *buf; + int val; +{ + buf[0] = val >> 8; + buf[1] = val >> 0; +} + +void +tm_fetch_register (regno, buf) + int regno; + char *buf; +{ + switch + (regno) + { + case REG_CYCLES: + swap_long (buf, the_state.cycles); + break; + case REG_INSTS: + swap_long (buf, the_state.insts); + break; + case + REG_TIME: + swap_long (buf, the_state.ticks); + break; + case REG_PC: + swap_long (buf, the_state.sometimes_pc); + break; + case REG_SP: + { + if (sim_z8001_mode) + { + swap_long (buf, get_long_reg (&the_state, 14)); + } + else + { + swap_long (buf, get_word_reg (&the_state, 15)); + } + } + break; + case + REG_FP: + { + if (sim_z8001_mode) + { + swap_long (buf, get_long_reg + (&the_state, 10)); + } + else + { + swap_long (buf, + get_word_reg (&the_state, 10)); + } + } + break; + default: + { + swap_word (buf, + get_word_reg (&the_state, regno)); + } + } +} + +void +tm_resume (step) + int step; +{ + int now = get_now (); + struct op_info + *p; + int word; + int pc; + extern int (*(sfop_table[])) (); + extern int (*(bfop_table[])) (); + int (*((*table))) (); + sim_state_type *context = &the_state; + + if (step) + { + context->exception = SIM_SINGLE_STEP; + } + else + { + context->exception = 0; + } + + pc = context->sometimes_pc; + if (sim_z8001_mode) + { + table = bfop_table; + pc = MAP_PHYSICAL_TO_LOGICAL (pc); + } + else + { + table = sfop_table; + } + + + do + { + word = get_word_mem_da (context, pc); + p = op_info_table + word; + +#ifdef LOG + log[word]++; +#endif + pc = table[p->exec] (context, pc, word); + context->insts++; + + } + while (!context->exception); + + + + context->sometimes_pc = MAP_LOGICAL_TO_PHYSICAL (pc); + context->ticks += get_now () - now; +} + +int +tm_signal () +{ + return the_state.exception; +} + +void +tm_info_print (x) + sim_state_type *x; +{ + double timetaken = (double) x->ticks / (double) now_persec (); + double virttime = x->cycles / 4.0e6; + + printf ("instructions executed : %9d\n", x->insts); + printf ("cycles counted : %9d \n", x->cycles); + printf ("cycles / inst : %9.1f \n", (double) x->cycles / (double) x->insts); + printf ("virtual time taked (at 4 Mhz) : %9.1f \n", virttime); + printf ("real time taken : %9.1f \n", timetaken); + + if (timetaken) + { + printf ("virtual instructions per second : %9.1f\n", x->insts / timetaken); + printf ("emulation speed : %9.1f%%\n", virttime / timetaken * 100.0); + } +#ifdef LOG + { + extern int quick[]; + + for (i = 0; quick[i]; i++) + { + log[quick[i]] += 100000; + } + } + + for (i = 0; i < 64 * 1024; i++) + { + if (log[i]) + { + printf (" /*%7d*/ 0x%x,\n", log[i], i); + } + } +#endif + +} + +int +sim_trace (sd) + SIM_DESC sd; +{ + int i; + char buffer[10]; + int r; + + printf ("\n"); + for (r = 0; r < 16; r++) + { + int m; + + printf ("r%2d", r); + printf ("=%04x ", get_word_reg (&the_state, + r)); + for (m = -4; m < 8; m++) + { + if (m == 0) + printf (">"); + printf ("%04x ", + get_word_mem_da (&the_state, (0xfffe & get_word_reg (&the_state, r)) + m * 2)); + } + printf ("\n"); + } + + printf ("\n"); + printf ("%9d %9d %08x ", the_state.cycles, + the_state.insts, the_state.sometimes_pc); + + for (i = 0; i < 6; i++) + { + buffer[i] = get_byte_mem_da (&the_state, + the_state.sometimes_pc + i); + } + + print_insn_z8001 (the_state.sometimes_pc, buffer, stdout); + printf + ("\n"); + tm_resume (1); + if (the_state.exception != SIM_SINGLE_STEP) + return 1; + return 0; +} + +void +tm_state (x) + sim_state_type *x; +{ + *x = the_state; +} + +void +tm_exception (x) + int x; +{ + the_state.exception = x; +} + +int +tm_read_byte (x) + int x; +{ + x &= 0x3f00ffff; + return sim_read_byte (&the_state, x); +} + +void +tm_write_byte (x, y) + int x, y; +{ + x &= 0x3f00ffff; + sim_write_byte (&the_state, x, y); +} + +#define SIGN(x) ((x) & MASK) +normal_flags_32(context,d,sa,sb,sub) +sim_state_type *context; +unsigned int d; +unsigned int sa; +unsigned int sb; +unsigned int sub; +{ +#undef MASK +#define MASK (1<<31) + context->broken_flags = 0; + if (sub) + PSW_CARRY = sa < sb; + else + PSW_CARRY = d < sa; + if (sub) + PSW_OVERFLOW = (SIGN(sa) != SIGN(sb)) && (SIGN(d) == SIGN(sb)); + else + PSW_OVERFLOW = (SIGN(sa) == SIGN(sb)) && (SIGN(d) != SIGN(sb)); + + PSW_SIGN = ((int)d) <0; + PSW_ZERO = d == 0; +} + +normal_flags_16(context,d,sal,sbl,sub) +sim_state_type *context; +unsigned int d; +unsigned int sal; +unsigned int sbl; +unsigned short int sub; +{ + unsigned short sa = sal; + unsigned short sb = sbl; +#undef MASK +#define MASK (1<<15) + context->broken_flags = 0; + if (sub) + PSW_CARRY = sal < sbl; + else + PSW_CARRY = (d & 0x10000) != 0; + + if (sub) + PSW_OVERFLOW = (SIGN(sa) != SIGN(sb)) && (SIGN(d) == SIGN(sb)); + else + PSW_OVERFLOW = (SIGN(sa) == SIGN(sb)) && (SIGN(d) != SIGN(sb)); + + PSW_SIGN = ((short int)d) <0; + PSW_ZERO = ((short)d) == 0; +} + +normal_flags_8(context,d,sa,sb,sub) +sim_state_type *context; +unsigned char d; +unsigned char sa; +unsigned char sb; +unsigned char sub; +{ +#undef MASK +#define MASK (1<<7) + context->broken_flags = 0; + if (sub) + PSW_CARRY = sa < sb; + else + PSW_CARRY = d < sa; + if (sub) + PSW_OVERFLOW = (SIGN(sa) != SIGN(sb)) && (SIGN(d) == SIGN(sb)); + else + PSW_OVERFLOW = (SIGN(sa) == SIGN(sb)) && (SIGN(d) != SIGN(sb)); + PSW_SIGN = ((char)d) <0; + PSW_ZERO = d == 0; +} + + +static int +is_cond_true (context, c) + sim_state_type *context; + int c; +{ + switch (c) + { + case T: + return 1; + case F: + return 0; /* F */ + case LE: + return (PSW_ZERO | (PSW_SIGN ^ PSW_OVERFLOW)) & 1; /*LE */ + case GT: + return (~(PSW_ZERO | (PSW_SIGN ^ PSW_OVERFLOW))) & 1; /*GT */ + case 0x5: + return (PSW_SIGN & 1); /* sign */ + case 0xd: + return (~(PSW_SIGN)) & 1; /* not sign */ + case 0x3: + return ((PSW_CARRY | PSW_ZERO) & 1); /* ule*/ + case UGT: + return ((~(PSW_CARRY | PSW_ZERO)) & 1); /* ugt */ + case 0x4: + return (PSW_OVERFLOW & 1);/* overflow */ + case 0xc: + return (~(PSW_OVERFLOW)) & 1; /* not overflow */ + case LT: + return (PSW_SIGN ^ PSW_OVERFLOW) & 1; /* LT */ + case GE: + return (~(PSW_SIGN ^ PSW_OVERFLOW)) & 1; /* GE */ + case EQ: + return (PSW_ZERO) & 1; /* zero */ + case NE: + return ((~PSW_ZERO) & 1); /* not zero */ + case 0x7: + return (PSW_CARRY) & 1; /* carry */ + case 0xf: + return (~PSW_CARRY) & 1; /* not carry */ + default: + abort (); + } +} + +int +COND (context, c) + sim_state_type *context; + int c; +{ + if (c == 8) + return 1; + + /* We can calculate what the flags would have been by + looking at the src and dst and size of the operation */ + + if (context->broken_flags) + { + int slow = 0; + int size; + int dst; + int srca; + int srcb; + int mask; + int ans; + + /* see if we can short-cut the nasty flag calcs */ + + switch (size = context->size) + { + default: + abort(); + return 0; + case 8: + srca = (char) (context->srca); + srcb = (char) (context->srcb); + dst = (char) (context->dst); + mask = 0xff; + break; + case 16: + srca = (short) (context->srca); + srcb = (short) (context->srcb); + dst = (short) (context->dst); + mask = 0xffff; + break; + case 32: + srca = (long) (context->srca); + srcb = (long) (context->srcb); + dst = (long) (context->dst); + mask = 0xffffffff; + break; + } + + switch (c) + { + case T: + return 1; + case F: + return 0; + case EQ: + return !dst; + case NE: + return dst; + case GT: + ans = ((dst)) > 0; + if (slow) + { + if (is_cond_true (context, c) != ans) + abort (); + } + return ans; + case LE: + ans = ((dst)) <= 0; + if (slow) + { + if (is_cond_true (context, c) != ans) + abort (); + } + return ans; + case GE: + ans = ((dst)) >= 0; + if (slow) + { + if (is_cond_true (context, c) != ans) + abort (); + } + return ans; + case LT: + ans = ((dst)) < 0; + if (slow) + { + if (is_cond_true (context, c) != ans) + abort (); + } + return ans; + default: + break; + } + + /* Can't fake it, we'll have to work out the flags the + hard way */ + + makeflags (context, mask); + } + + /* don't know how to fake a test, inspect the flags + the hard way */ + + return is_cond_true (context, c); +} |