From 1490a2c23ffae8b0df564d4a53a65e8d1ee92919 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sun, 28 Jun 2015 06:51:06 -0500 Subject: add gdb patch for h8300 --- toolchain/gdb/patches/git/h8300-sim-io.patch | 1705 ++++++++++++++++++++++++++ 1 file changed, 1705 insertions(+) create mode 100644 toolchain/gdb/patches/git/h8300-sim-io.patch (limited to 'toolchain/gdb') diff --git a/toolchain/gdb/patches/git/h8300-sim-io.patch b/toolchain/gdb/patches/git/h8300-sim-io.patch new file mode 100644 index 000000000..b53a1516b --- /dev/null +++ b/toolchain/gdb/patches/git/h8300-sim-io.patch @@ -0,0 +1,1705 @@ +diff --git a/sim/h8300/Makefile.in b/sim/h8300/Makefile.in +index da68255..713de00 100644 +--- a/sim/h8300/Makefile.in ++++ b/sim/h8300/Makefile.in +@@ -18,6 +18,7 @@ + ## COMMON_PRE_CONFIG_FRAG + + SIM_OBJS = compile.o \ ++ io.o \ + $(SIM_NEW_COMMON_OBJS) \ + sim-load.o + +@@ -28,3 +29,5 @@ compile.o: compile.c inst.h config.h \ + $(srcdir)/../../include/opcode/h8300.h \ + $(srcdir)/../../include/gdb/remote-sim.h \ + $(srcdir)/../../include/gdb/callback.h ++ ++io.o: io.c sim-main.h +diff --git a/sim/h8300/compile.c b/sim/h8300/compile.c +index d084b5d..b2fe38a 100644 +--- a/sim/h8300/compile.c ++++ b/sim/h8300/compile.c +@@ -41,11 +41,14 @@ + #endif + + int debug; ++int h8300_interrupt_mode; + + host_callback *sim_callback; + + static SIM_OPEN_KIND sim_kind; + static char *myname; ++static int verbose_interrupt = 0; ++static int logging = 0; + + /* FIXME: Needs to live in header file. + This header should also include the things in remote-sim.h. +@@ -578,10 +581,8 @@ lvalue (SIM_DESC sd, int x, int rn, unsigned int *val) + static int + cmdline_location() + { +- if (h8300smode && !h8300_normal_mode) +- return 0xffff00L; +- else if (h8300hmode && !h8300_normal_mode) +- return 0x2ff00L; ++ if ((h8300hmode || h8300smode) && !h8300_normal_mode) ++ return 0xff0000L; + else + return 0xff00L; + } +@@ -1037,12 +1038,15 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst) + + /* 8-bit ABS is displacement from SBR. + 16 and 32-bit ABS are displacement from ZERO. +- (SBR will always be zero except for h8/sx) ++ (SBR will always be 0xffff00 except for h8/sx) + */ + if ((x & SIZE) == L_8) + p->reg = SBR_REGNUM; + else +- p->reg = ZERO_REGNUM;; ++ p->reg = ZERO_REGNUM; ++ /* address extend for @x:16 */ ++ if ((x & SIZE) == L_16U) ++ p->literal += (p->literal >= 0x8000)?0xff0000:0x000000; + } + else if ((x & MODE) == MEMIND || + (x & MODE) == VECIND) +@@ -1253,6 +1257,39 @@ compile (SIM_DESC sd, int pc) + h8_set_cache_idx (sd, pc, idx); + } + ++enum mem_access_type {MEM_RL,MEM_RW,MEM_RB,MEM_WL,MEM_WW,MEM_WB}; ++ ++struct memlog { ++ unsigned long pc; ++ unsigned long addr; ++ unsigned long data; ++ enum mem_access_type type; ++}; ++ ++static struct memlog *memlog_buffer; ++static int memlogtail; ++static int memlogsize; ++ ++static add_memlog(unsigned long pc, unsigned long addr, ++ enum mem_access_type type, unsigned long data) ++{ ++ if (!logging) ++ return; ++ if (memlogsize == memlogtail) { ++ memlog_buffer = (struct memlog *)realloc(memlog_buffer, ++ (memlogsize * sizeof(struct memlog) + 65536)); ++ memlogsize += 65536 / sizeof(struct memlog); ++ } ++ if (memlog_buffer) { ++ memlog_buffer[memlogtail].pc = pc; ++ memlog_buffer[memlogtail].addr = addr; ++ memlog_buffer[memlogtail].type = type; ++ memlog_buffer[memlogtail].data = data; ++ memlogtail++; ++ } ++} ++ ++static int pc; + + static unsigned char *breg[32]; + static unsigned short *wreg[16]; +@@ -1265,33 +1302,46 @@ static unsigned int *lreg[18]; + #define GET_L_REG(X) h8_get_reg (sd, X) + #define SET_L_REG(X, Y) h8_set_reg (sd, X, Y) + +-#define GET_MEMORY_L(X) \ +- ((X) < memory_size \ +- ? ((h8_get_memory (sd, (X)+0) << 24) | (h8_get_memory (sd, (X)+1) << 16) \ +- | (h8_get_memory (sd, (X)+2) << 8) | (h8_get_memory (sd, (X)+3) << 0)) \ +- : ((h8_get_eightbit (sd, ((X)+0) & 0xff) << 24) \ +- | (h8_get_eightbit (sd, ((X)+1) & 0xff) << 16) \ +- | (h8_get_eightbit (sd, ((X)+2) & 0xff) << 8) \ +- | (h8_get_eightbit (sd, ((X)+3) & 0xff) << 0))) ++#define GET_MEMORY_L(X) _get_memory_l(sd, X) + +-#define GET_MEMORY_W(X) \ +- ((X) < memory_size \ +- ? ((h8_get_memory (sd, (X)+0) << 8) \ +- | (h8_get_memory (sd, (X)+1) << 0)) \ +- : ((h8_get_eightbit (sd, ((X)+0) & 0xff) << 8) \ +- | (h8_get_eightbit (sd, ((X)+1) & 0xff) << 0))) ++static inline unsigned long _get_memory_l(SIM_DESC sd, unsigned long addr) ++{ ++ unsigned long result; ++ result = ++ ((h8_get_memory (sd, addr+0) << 24) | (h8_get_memory (sd, addr+1) << 16) ++ | (h8_get_memory (sd, addr+2) << 8) | (h8_get_memory (sd, addr+3) << 0)); ++ add_memlog(pc, addr, MEM_RL, result); ++ return result; ++} + ++#define GET_MEMORY_W(X) _get_memory_w(sd, X) + +-#define GET_MEMORY_B(X) \ +- ((X) < memory_size ? (h8_get_memory (sd, (X))) \ +- : (h8_get_eightbit (sd, (X) & 0xff))) ++static inline unsigned short _get_memory_w(SIM_DESC sd, unsigned long addr) ++{ ++ unsigned short result; ++ result = ++ (h8_get_memory (sd, addr+0) << 8) | (h8_get_memory (sd, addr+1) << 0); ++ add_memlog(pc, addr, MEM_RW, result); ++ return result; ++} ++ ++#define GET_MEMORY_B(X) _get_memory_b(sd, X) + ++static inline unsigned short _get_memory_b(SIM_DESC sd, unsigned long addr) ++{ ++ unsigned short result; ++ result = h8_get_memory (sd, addr+0); ++ add_memlog(pc, addr, MEM_RB, result); ++ return result; ++} ++ + #define SET_MEMORY_L(X, Y) \ + { register unsigned char *_p; register int __y = (Y); \ + _p = ((X) < memory_size ? h8_get_memory_buf (sd) + (X) : \ + h8_get_eightbit_buf (sd) + ((X) & 0xff)); \ + _p[0] = __y >> 24; _p[1] = __y >> 16; \ + _p[2] = __y >> 8; _p[3] = __y >> 0; \ ++ add_memlog(pc, X, MEM_WL, Y); \ + } + + #define SET_MEMORY_W(X, Y) \ +@@ -1299,11 +1349,13 @@ static unsigned int *lreg[18]; + _p = ((X) < memory_size ? h8_get_memory_buf (sd) + (X) : \ + h8_get_eightbit_buf (sd) + ((X) & 0xff)); \ + _p[0] = __y >> 8; _p[1] = __y; \ ++ add_memlog(pc, X, MEM_WW, Y); \ + } + + #define SET_MEMORY_B(X, Y) \ + ((X) < memory_size ? (h8_set_memory (sd, (X), (Y))) \ +- : (h8_set_eightbit (sd, (X) & 0xff, (Y)))) ++ : (h8_set_eightbit (sd, (X) & 0xff, (Y)))); \ ++ add_memlog(pc, X, MEM_WB, Y) + + /* Simulate a memory fetch. + Return 0 for success, -1 for failure. +@@ -1792,15 +1844,13 @@ init_pointers (SIM_DESC sd) + free (h8_get_memory_buf (sd)); + if (h8_get_cache_idx_buf (sd)) + free (h8_get_cache_idx_buf (sd)); +- if (h8_get_eightbit_buf (sd)) +- free (h8_get_eightbit_buf (sd)); + + h8_set_memory_buf (sd, (unsigned char *) + calloc (sizeof (char), memory_size)); + h8_set_cache_idx_buf (sd, (unsigned short *) + calloc (sizeof (short), memory_size)); + sd->memory_size = memory_size; +- h8_set_eightbit_buf (sd, (unsigned char *) calloc (sizeof (char), 256)); ++ h8_set_eightbit_buf (sd, (unsigned char *)h8_get_memory_buf(sd) + 0xffff00); + + h8_set_mask (sd, memory_size - 1); + +@@ -1886,6 +1936,105 @@ case O (name, SB): \ + goto next; \ + } + ++static unsigned long *trace_buffer; ++static unsigned long tracesize; ++static unsigned long tracetail; ++ ++static void add_trace(unsigned long pc) ++{ ++ static unsigned long last_pc = 0xfffffff; ++ ++ if (pc == last_pc || logging == 0) ++ return; ++ last_pc = pc; ++ if (tracesize == tracetail) { ++ trace_buffer = (unsigned long *)realloc(trace_buffer, ++ (tracesize * sizeof(unsigned long) + 65536)); ++ tracesize += 65536 / sizeof(unsigned long); ++ } ++ if (trace_buffer) ++ trace_buffer[tracetail++] = pc; ++} ++ ++static void init_history(void) ++{ ++ if(trace_buffer) { ++ free(trace_buffer); ++ trace_buffer = NULL; ++ } ++ tracesize = tracetail = 0; ++ if(memlog_buffer) { ++ free(memlog_buffer); ++ memlog_buffer = NULL; ++ } ++ memlogsize = memlogtail = 0; ++} ++ ++static int intlevel(SIM_DESC sd) ++{ ++ if(h8300smode && (h8300_interrupt_mode == 2)) { ++ return h8_get_ccr (sd) & 0x80?0x100:h8_get_exr (sd) << 8; ++ } else if (h8300_interrupt_mode == 1) { ++ switch((h8_get_ccr (sd) >> 6) & 3) { ++ case 0: ++ case 1: ++ return -1; ++ case 2: ++ return 1 << 8; ++ case 3: ++ return 0x100 << 8; ++ } ++ } else { ++ return h8_get_ccr (sd) & 0x80?0x100 << 8:-1; ++ } ++} ++ ++int iosimulation(SIM_DESC, int); ++ ++#define exception(vector, pri) \ ++do { \ ++ unsigned int ccr; \ ++ unsigned long vbr = 0; \ ++ int tmp; \ ++ if (verbose_interrupt) \ ++ (*sim_callback->printf_filtered) \ ++ (sim_callback, "sim_resume: interrupt occured %d\n", (vector)); \ ++ BUILDSR (sd); \ ++ ccr = h8_get_ccr (sd); \ ++ tmp = h8_get_reg (sd, SP_REGNUM); \ ++ tmp -= 4; \ ++ if (h8300sxmode) \ ++ vbr = h8_get_vbr(sd); \ ++ if (!h8300hmode || h8300_normal_mode) \ ++ { \ ++ SET_MEMORY_W (tmp, (ccr << 8) | ccr); \ ++ SET_MEMORY_W (tmp, pc); \ ++ pc = GET_MEMORY_W (vbr + (vector) * 2) & 0xffff; \ ++ } \ ++ else \ ++ { \ ++ SET_MEMORY_L (tmp, (ccr << 24) | pc); \ ++ pc=GET_MEMORY_L(vbr + (vector) * 4) & 0xffffff; \ ++ } \ ++ if (h8300smode && (h8300_interrupt_mode == 2)) \ ++ { \ ++ int exr; \ ++ exr = h8_get_exr (sd); \ ++ tmp -= 2; \ ++ SET_MEMORY_W (tmp, exr << 8); \ ++ if ((pri) >= 0) \ ++ { \ ++ exr = pri; \ ++ h8_set_exr (sd, exr); \ ++ intMask = pri; \ ++ } \ ++ } \ ++ h8_set_reg (sd, SP_REGNUM, tmp); \ ++ ccr |= (h8300_interrupt_mode == 1)?0xc0:0x80; \ ++ h8_set_ccr (sd, ccr); \ ++ GETSR(sd); \ ++ } while(0) ++ + void + sim_resume (SIM_DESC sd, int step, int siggnal) + { +@@ -1899,12 +2048,12 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + int rd; + int ea; + int bit; +- int pc; + int c, nz, v, n, u, h, ui, intMaskBit; + int trace, intMask; + int oldmask; + enum sim_stop reason; + int sigrc; ++ int vector; + + init_pointers (sd); + +@@ -1929,7 +2078,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + /* Get Status Register (flags). */ + GETSR (sd); + +- if (h8300smode) /* Get exr. */ ++ if (h8300smode && h8300_interrupt_mode) /* Get exr. */ + { + trace = (h8_get_exr (sd) >> 7) & 1; + intMask = h8_get_exr (sd) & 7; +@@ -1944,6 +2093,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + decoded_inst *code; + + top: ++ add_trace(pc); + cidx = h8_get_cache_idx (sd, pc); + if (cidx == (unsigned short) -1 || + cidx >= sd->sim_cache_size) +@@ -1964,6 +2114,13 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + { + cycles += code->cycles; + insts++; ++ add_trace(pc); ++ if ((vector = iosimulation (sd, cycles)) && ++ (intlevel(sd) < (vector & 0xff00))) ++ { ++ exception(vector & 0xff, (vector & 0xff00) >> 8); ++ goto end; ++ } + } + + switch (code->opcode) +@@ -3569,16 +3726,20 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + /* Pops exr and ccr before pc -- otherwise identical to rts. */ + tmp = h8_get_reg (sd, SP_REGNUM); + +- if (h8300smode) /* pop exr */ ++ if (h8300smode && (h8300_interrupt_mode == 2)) /* pop exr */ + { +- h8_set_exr (sd, GET_MEMORY_L (tmp)); +- tmp += 4; ++ unsigned char exr; ++ exr = GET_MEMORY_W (tmp) >> 8; ++ h8_set_exr (sd, exr); ++ intMask = exr & 7; ++ trace = exr & 0x80; ++ tmp += 2; + } + if (h8300hmode && !h8300_normal_mode) + { +- h8_set_ccr (sd, GET_MEMORY_L (tmp)); +- tmp += 4; + pc = GET_MEMORY_L (tmp); ++ h8_set_ccr (sd, pc >> 24); ++ pc &= 0x00ffffff; + tmp += 4; + } + else +@@ -3643,41 +3804,13 @@ sim_resume (SIM_DESC sd, int step, int siggnal) + } + goto end; + +- case O (O_TRAPA, SB): /* trapa */ ++ case O (O_TRAPA, SB): { /* trapa */ + if (fetch (sd, &code->src, &res)) + goto end; /* res is vector number. */ +- +- tmp = h8_get_reg (sd, SP_REGNUM); +- if(h8300_normal_mode) +- { +- tmp -= 2; +- SET_MEMORY_W (tmp, code->next_pc); +- tmp -= 2; +- SET_MEMORY_W (tmp, h8_get_ccr (sd)); +- } +- else +- { +- tmp -= 4; +- SET_MEMORY_L (tmp, code->next_pc); +- tmp -= 4; +- SET_MEMORY_L (tmp, h8_get_ccr (sd)); +- } +- intMaskBit = 1; +- BUILDSR (sd); +- +- if (h8300smode) +- { +- tmp -= 4; +- SET_MEMORY_L (tmp, h8_get_exr (sd)); +- } +- +- h8_set_reg (sd, SP_REGNUM, tmp); +- +- if(h8300_normal_mode) +- pc = GET_MEMORY_L (0x10 + res * 2); /* Vector addresses are 0x10,0x12,0x14 and 0x16 */ +- else +- pc = GET_MEMORY_L (0x20 + res * 4); ++ res += 8; ++ exception(res, -1); + goto end; ++ } + + case O (O_BPT, SN): + sim_engine_set_run_state (sd, sim_stopped, SIGTRAP); +@@ -5038,15 +5171,13 @@ sim_load (SIM_DESC sd, const char *prog, bfd *abfd, int from_tty) + free (h8_get_memory_buf (sd)); + if (h8_get_cache_idx_buf (sd)) + free (h8_get_cache_idx_buf (sd)); +- if (h8_get_eightbit_buf (sd)) +- free (h8_get_eightbit_buf (sd)); + + h8_set_memory_buf (sd, (unsigned char *) + calloc (sizeof (char), memory_size)); + h8_set_cache_idx_buf (sd, (unsigned short *) + calloc (sizeof (short), memory_size)); + sd->memory_size = memory_size; +- h8_set_eightbit_buf (sd, (unsigned char *) calloc (sizeof (char), 256)); ++ h8_set_eightbit_buf (sd, (unsigned char *)h8_get_memory_buf(sd) + 0xffff00); + + /* `msize' must be a power of two. */ + if ((memory_size & (memory_size - 1)) != 0) +@@ -5057,6 +5188,8 @@ sim_load (SIM_DESC sd, const char *prog, bfd *abfd, int from_tty) + } + h8_set_mask (sd, memory_size - 1); + ++ init_history(); ++ init_ioregs(sd); + if (sim_load_file (sd, myname, sim_callback, prog, prog_bfd, + sim_kind == SIM_OPEN_DEBUG, + 0, sim_write) +@@ -5107,3 +5240,187 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env) + + return SIM_RC_OK; + } ++ ++static void show_trace(int lines) ++{ ++ unsigned long idx; ++ idx = tracetail - lines; ++ for (; lines > 0; --lines) ++ { ++ if (trace_buffer[idx] != -1) ++ (*sim_callback->printf_filtered) (sim_callback, ++ "0x%06x\n", trace_buffer[idx]); ++ idx++; ++ } ++ (*sim_callback->printf_filtered) (sim_callback, "\n"); ++} ++ ++static void save_trace(const char *filename) ++{ ++ FILE *fp; ++ unsigned long idx; ++ fp = fopen(filename, "w"); ++ if (!fp) ++ { ++ (*sim_callback->printf_filtered) (sim_callback, ++ "save-history: file open failed.\n"); ++ return ; ++ } ++ for (idx = 0; idx < tracetail; idx++) ++ fprintf(fp, "0x%06x\n", trace_buffer[idx]); ++ fclose(fp); ++} ++ ++static const char *memtype_str[]={"RL","RW","RB","WL","WW","WB"}; ++ ++static void show_memlog(int lines) ++{ ++ unsigned long idx; ++ idx = memlogtail - lines; ++ if (memlog_buffer == NULL) ++ { ++ (*sim_callback->printf_filtered) (sim_callback, "no memlog\n"); ++ return; ++ } ++ for (; lines > 0; --lines) ++ { ++ (*sim_callback->printf_filtered) (sim_callback, ++ "0x%06x 0x%06x %s %08x\n", ++ memlog_buffer[idx].pc, ++ memlog_buffer[idx].addr, ++ memtype_str[memlog_buffer[idx].type], ++ memlog_buffer[idx].data); ++ idx++; ++ } ++ (*sim_callback->printf_filtered) (sim_callback, "\n"); ++} ++ ++static void save_memlog(const char *filename) ++{ ++ FILE *fp; ++ unsigned long idx; ++ if (memlog_buffer == NULL) ++ { ++ (*sim_callback->printf_filtered) (sim_callback, "no memlog\n"); ++ return; ++ } ++ fp = fopen(filename, "w"); ++ if (!fp) ++ { ++ (*sim_callback->printf_filtered) (sim_callback, ++ "save-history: file open failed.\n"); ++ return ; ++ } ++ for (idx = 0; idx < memlogtail; idx++) ++ fprintf(fp, "0x%06x 0x%06x %s %08x\n", ++ memlog_buffer[idx].pc, ++ memlog_buffer[idx].addr, ++ memtype_str[memlog_buffer[idx].type], ++ memlog_buffer[idx].data); ++ fclose(fp); ++} ++ ++void ++sim_do_command (SIM_DESC sd, const char *cmd) ++{ ++ if (cmd == NULL || *cmd == '\0') ++ cmd = "help"; ++ if (strncmp(cmd, "show-trace", 10) == 0) ++ { ++ int lines = 16; ++ cmd += 10; ++ if (*cmd) ++ lines = atoi(cmd); ++ if (lines > 0) ++ show_trace(lines); ++ else ++ (*sim_callback->printf_filtered) (sim_callback, ++ "Invalid lines\n"); ++ return; ++ } ++ else if (strncmp(cmd, "save-trace", 10) == 0) ++ { ++ cmd += 10; ++ while(isspace(*cmd)) ++ cmd++; ++ ++ if (*cmd) ++ save_trace(cmd); ++ else ++ (*sim_callback->printf_filtered) (sim_callback, ++ "Invalid filename\n"); ++ } ++ else if (strncmp(cmd, "show-mem", 8) == 0) ++ { ++ int lines = 16; ++ cmd += 8; ++ if (*cmd) ++ lines = atoi(cmd); ++ if (lines > 0) ++ show_memlog(lines); ++ else ++ (*sim_callback->printf_filtered) (sim_callback, ++ "Invalid lines\n"); ++ return; ++ } ++ else if (strncmp(cmd, "save-mem", 8) == 0) ++ { ++ cmd += 8; ++ while(isspace(*cmd)) ++ cmd++; ++ if (*cmd) ++ save_memlog(cmd); ++ else ++ (*sim_callback->printf_filtered) (sim_callback, ++ "Invalid filename\n"); ++ } ++ else if (strncmp (cmd, "sci", 3) == 0) ++ { ++ cmd += 3; ++ while(isspace(*cmd)) cmd++; ++ if (strncmp (cmd, "pty", 3) == 0) ++ sci_open_pty(sim_callback); ++ else if (strncmp(cmd, "net", 3) == 0) ++ { ++ cmd += 3; ++ while(isspace(*cmd)) cmd++; ++ sci_open_net(sim_callback, atoi(cmd)); ++ } ++ } ++ else if (strncmp (cmd, "verbose-int", 11) == 0) ++ { ++ cmd += 11; ++ while(isspace(*cmd)) cmd++; ++ verbose_interrupt = atoi(cmd); ++ } ++ else if (strncmp(cmd, "help", 4) == 0) ++ (*sim_callback->printf_filtered) (sim_callback, ++ "List of H8/300 Simulator commands\n\n" ++ "show-trace -- show trace history\n" ++ "save-trace filename -- save trace history\n" ++ "show-mem -- show memory access log\n" ++ "save-mem filename -- save memory access log\n" ++ "sci [pty|net port] -- open sci port\n" ++ "intmode mode -- set interrupt mode\n" ++ "verbose-int -- verbose interrupt\n" ++ "trace [on|off] -- trace switch\n" ++ ); ++ else if (strncmp(cmd, "intmode", 7) == 0) ++ { ++ cmd += 7; ++ while(isspace(*cmd)) cmd++; ++ h8300_interrupt_mode = atoi(cmd); ++ } ++ else if (strncmp (cmd, "trace", 5) == 0) ++ { ++ cmd += 5; ++ while(isspace(*cmd)) cmd++; ++ if (strncmp (cmd, "on", 2) == 0) ++ logging = 1; ++ else if (strncmp(cmd, "off", 3) == 0) ++ logging = 0; ++ } ++ else ++ (*sim_callback->printf_filtered) (sim_callback, ++ "Error: Unknown \"%s\" command\n", cmd); ++} +diff --git a/sim/h8300/io.c b/sim/h8300/io.c +new file mode 100644 +index 0000000..d1a12d3 +--- /dev/null ++++ b/sim/h8300/io.c +@@ -0,0 +1,1058 @@ ++/* ++ H8 simulator Internal Peripheral Support ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#define _XOPEN_SOURCE ++#include ++#include ++#include ++ ++#include "sim-main.h" ++#undef CSIZE ++#include ++ ++#define MAX_SCI_CH 3 ++ ++#define SMR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+0]) ++#define BRR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+1]) ++#define SCR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+2]) ++#define TDR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+3]) ++#define SSR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+4]) ++#define RDR(ch) (STATE_CPU(sd, 0)->eightbit[sci_base[ch]+5]) ++ ++#define TCR8(ch) (STATE_CPU(sd, 0)->eightbit[timer8_base[ch] + 0]) ++#define TCSR8(ch) (STATE_CPU(sd, 0)->eightbit[timer8_base[ch] + 2]) ++#define TCORA8(ch) (STATE_CPU(sd, 0)->eightbit[timer8_base[ch] + 4]) ++#define TCORB8(ch) (STATE_CPU(sd, 0)->eightbit[timer8_base[ch] + 6]) ++#define TCNT8(ch) (STATE_CPU(sd, 0)->eightbit[timer8_base[ch] + 8]) ++ ++#define TSTR16 (STATE_CPU(sd, 0)->eightbit[0x60]) ++#define TISRA16 (STATE_CPU(sd, 0)->eightbit[0x64]) ++#define TISRB16 (STATE_CPU(sd, 0)->eightbit[0x65]) ++#define TISRC16 (STATE_CPU(sd, 0)->eightbit[0x66]) ++#define TCR16(ch) (STATE_CPU(sd, 0)->eightbit[0x68 + (ch) * 8]) ++#define TCNT16H(ch) (STATE_CPU(sd, 0)->eightbit[0x6a + (ch) * 8]) ++#define TCNT16L(ch) (STATE_CPU(sd, 0)->eightbit[0x6b + (ch) * 8]) ++#define GRA16H(ch) (STATE_CPU(sd, 0)->eightbit[0x6c + (ch) * 8]) ++#define GRA16L(ch) (STATE_CPU(sd, 0)->eightbit[0x6d + (ch) * 8]) ++#define GRB16H(ch) (STATE_CPU(sd, 0)->eightbit[0x6e + (ch) * 8]) ++#define GRB16L(ch) (STATE_CPU(sd, 0)->eightbit[0x6f + (ch) * 8]) ++ ++#define TPU_CH 6 ++#define TPU_TSTR (STATE_CPU(sd, 0)->eightbit[0xc0]) ++#define TPU_TCR(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 0]) ++#define TPU_TSR(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 5]) ++#define TPU_TCNTH(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 6]) ++#define TPU_TCNTL(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 7]) ++#define TPU_GRAH(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 8]) ++#define TPU_GRAL(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 9]) ++#define TPU_GRBH(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 10]) ++#define TPU_GRBL(ch) (STATE_CPU(sd, 0)->memory[tpubase[ch] + 11]) ++ ++#define IPRA_H8300H 0xfee018 ++#define IPRB_H8300H 0xfee019 ++ ++#define IPRA_H8300S 0xfffe00 ++ ++struct int_list_t { ++ int vector; ++ unsigned int isr_adr; ++ unsigned char isr_mask; ++ unsigned int ier_adr; ++ unsigned char ier_mask; ++}; ++ ++static const unsigned char *sci_base; ++static unsigned char ssr[MAX_SCI_CH]; ++static const unsigned char *timer8_base; ++static const struct int_list_t *int_table; ++ ++static const unsigned char h8300h_timer8_base[] = {0x80,0x81,0x90,0x91,0}; ++static const unsigned char h8300s_timer8_base[] = {0xb0,0xb1,0}; ++static const unsigned int tpubase[] = {0xffffd0,0xffffe0,0xfffff0, ++ 0xfffe80,0xfffe90,0xfffea0}; ++static const unsigned char h8300h_sci_base[] = {0xb0,0xb8,0xc0}; ++static const unsigned char h8300s_sci_base[] = {0x78,0x80,0x88}; ++static const unsigned char h8300sx_sci_base[] = {0x80,0x88,0x60}; ++ ++extern int h8300hmode; ++extern int h8300smode; ++extern int h8300sxmode; ++ ++static const struct int_list_t h8300h_int_table[]= { ++ {24,0xffff64,0x01,0xffff64,0x10}, /* IMIA0 */ ++ {25,0xffff65,0x01,0xffff65,0x10}, /* IMIB0 */ ++ {26,0xffff66,0x01,0xffff66,0x10}, /* OVI0 */ ++ {28,0xffff64,0x02,0xffff64,0x20}, /* IMIA1 */ ++ {29,0xffff65,0x02,0xffff65,0x20}, /* IMIB1 */ ++ {30,0xffff66,0x02,0xffff66,0x20}, /* OVI1 */ ++ {32,0xffff64,0x04,0xffff64,0x40}, /* IMIA2 */ ++ {33,0xffff65,0x04,0xffff65,0x40}, /* IMIB2 */ ++ {34,0xffff66,0x04,0xffff66,0x40}, /* OVI2 */ ++ {36,0xffff82,0x40,0xffff80,0x40}, /* CMIA0 */ ++ {37,0xffff82,0x80,0xffff80,0x80}, /* CMIB0 */ ++ {38,0xffff83,0x40,0xffff81,0x40}, /* CMIA1 */ ++ {38,0xffff83,0x80,0xffff81,0x40}, /* CMIB1 */ ++ {39,0xffff82,0x20,0xffff80,0x20}, /* TOVI0 */ ++ {39,0xffff83,0x20,0xffff81,0x20}, /* TOVI1 */ ++ {40,0xffff92,0x40,0xffff90,0x40}, /* CMIA2 */ ++ {41,0xffff92,0x80,0xffff90,0x80}, /* CMIB2 */ ++ {42,0xffff93,0x40,0xffff91,0x40}, /* CMIA3 */ ++ {42,0xffff93,0x80,0xffff91,0x40}, /* CMIB3 */ ++ {43,0xffff92,0x20,0xffff90,0x20}, /* TOVI2 */ ++ {43,0xffff93,0x20,0xffff91,0x20}, /* TOVI3 */ ++ {52,0xffffb4,0x38,0xffffb2,0x40}, /* ERI0 */ ++ {53,0xffffb4,0x40,0xffffb2,0x40}, /* RXI0 */ ++ {54,0xffffb4,0x80,0xffffb2,0x80}, /* TXI0 */ ++ {55,0xffffb4,0x04,0xffffb2,0x04}, /* TEI0 */ ++ {56,0xffffbc,0x38,0xffffba,0x40}, /* ERI1 */ ++ {57,0xffffbc,0x40,0xffffba,0x40}, /* RXI1 */ ++ {58,0xffffbc,0x80,0xffffba,0x80}, /* TXI1 */ ++ {59,0xffffbc,0x04,0xffffba,0x04}, /* TEI1 */ ++ {60,0xffffc4,0x38,0xffffc2,0x40}, /* ERI2 */ ++ {61,0xffffc4,0x40,0xffffc2,0x40}, /* RXI2 */ ++ {62,0xffffc4,0x80,0xffffc2,0x80}, /* TXI2 */ ++ {63,0xffffc4,0x04,0xffffc2,0x04}, /* TEI2 */ ++ {-1,0,0,0,0} ++}; ++ ++static const struct int_list_t h8300s_int_table[]= { ++ {40,0xffffd5,0x01,0xffffd4,0x01}, /* TGI0A */ ++ {41,0xffffd5,0x02,0xffffd4,0x02}, /* TGI0B */ ++ {43,0xffffd5,0x10,0xffffd4,0x10}, /* TGI0V */ ++ {48,0xffffe5,0x01,0xffffe4,0x01}, /* TGI1A */ ++ {49,0xffffe5,0x01,0xffffe4,0x02}, /* TGI1B */ ++ {50,0xffffe5,0x10,0xffffe4,0x10}, /* TGI1V */ ++ {52,0xfffff5,0x01,0xfffff4,0x01}, /* TGI2A */ ++ {53,0xfffff5,0x02,0xfffff4,0x02}, /* TGI2B */ ++ {54,0xfffff5,0x10,0xfffff4,0x10}, /* TGI2V */ ++ {56,0xfffe85,0x01,0xfffe84,0x01}, /* TGI3A */ ++ {57,0xfffe85,0x02,0xfffe84,0x02}, /* TGI3B */ ++ {60,0xfffe85,0x10,0xfffe84,0x10}, /* TGI3V */ ++ {64,0xfffe95,0x01,0xfffe94,0x01}, /* TGI4A */ ++ {65,0xfffe95,0x02,0xfffe94,0x02}, /* TGI4B */ ++ {66,0xfffe95,0x10,0xfffe94,0x10}, /* TGI4V */ ++ {68,0xfffea5,0x01,0xfffea4,0x01}, /* TGI5A */ ++ {69,0xfffea5,0x02,0xfffea4,0x02}, /* TGI5B */ ++ {70,0xfffea5,0x10,0xfffea4,0x10}, /* TGI5V */ ++ {72,0xffffb2,0x40,0xffffb0,0x40}, /* CMIA0 */ ++ {73,0xffffb2,0x80,0xffffb0,0x80}, /* CMIB0 */ ++ {74,0xffffb2,0x20,0xffffb0,0x20}, /* CMIA1 */ ++ {76,0xffffb3,0x40,0xffffb1,0x40}, /* CMIB1 */ ++ {77,0xffffb3,0x80,0xffffb1,0x40}, /* TOVI0 */ ++ {78,0xffffb3,0x20,0xffffb1,0x20}, /* TOVI1 */ ++ {88,0xffff7c,0x38,0xffff7a,0x40}, /* ERI0 */ ++ {89,0xffff7c,0x40,0xffff7a,0x40}, /* RXI0 */ ++ {90,0xffff7c,0x80,0xffff7a,0x80}, /* TXI0 */ ++ {91,0xffff7c,0x04,0xffff7a,0x04}, /* TEI0 */ ++ {92,0xffff84,0x38,0xffff82,0x40}, /* ERI1 */ ++ {93,0xffff84,0x40,0xffff82,0x40}, /* RXI1 */ ++ {94,0xffff84,0x80,0xffff82,0x80}, /* TXI1 */ ++ {95,0xffff84,0x04,0xffff82,0x04}, /* TEI1 */ ++ {96,0xffff8c,0x38,0xffff8a,0x40}, /* ERI2 */ ++ {97,0xffff8c,0x40,0xffff8a,0x40}, /* RXI2 */ ++ {98,0xffff8c,0x80,0xffff8a,0x80}, /* TXI2 */ ++ {99,0xffff8c,0x04,0xffff8a,0x04}, /* TEI2 */ ++ {-1,0,0,0,0} ++}; ++static const struct int_list_t h8300sx_int_table[]= { ++ {88,0xffffd5,0x01,0xffffd4,0x01}, /* TGI0A */ ++ {89,0xffffd5,0x02,0xffffd4,0x02}, /* TGI0B */ ++ {90,0xffffd5,0x01,0xffffd4,0x01}, /* TGI0C */ ++ {91,0xffffd5,0x02,0xffffd4,0x02}, /* TGI0D */ ++ {93,0xffffe5,0x01,0xffffe4,0x01}, /* TGI1A */ ++ {94,0xffffe5,0x01,0xffffe4,0x02}, /* TGI1B */ ++ {95,0xffffe5,0x10,0xffffe4,0x10}, /* TGI1V */ ++ {96,0xffffe5,0x10,0xffffe4,0x10}, /* TGI1U */ ++ {97,0xfffff5,0x01,0xfffff4,0x01}, /* TGI2A */ ++ {98,0xfffff5,0x02,0xfffff4,0x02}, /* TGI2B */ ++ {99,0xfffff5,0x10,0xfffff4,0x10}, /* TGI2V */ ++ {100,0xfffff5,0x10,0xfffff4,0x10}, /* TGI2U */ ++ {101,0xfffe85,0x01,0xfffe84,0x01}, /* TGI3A */ ++ {102,0xfffe85,0x02,0xfffe84,0x02}, /* TGI3B */ ++ {103,0xfffe85,0x01,0xfffe84,0x01}, /* TGI3A */ ++ {104,0xfffe85,0x02,0xfffe84,0x02}, /* TGI3B */ ++ {105,0xfffe85,0x10,0xfffe84,0x10}, /* TGI3V */ ++ {106,0xfffe95,0x01,0xfffe94,0x01}, /* TGI4A */ ++ {107,0xfffe95,0x02,0xfffe94,0x02}, /* TGI4B */ ++ {108,0xfffe95,0x10,0xfffe94,0x10}, /* TGI4V */ ++ {109,0xfffe95,0x10,0xfffe94,0x10}, /* TGI4U */ ++ {110,0xfffea5,0x01,0xfffea4,0x01}, /* TGI5A */ ++ {111,0xfffea5,0x02,0xfffea4,0x02}, /* TGI5B */ ++ {112,0xfffea5,0x10,0xfffea4,0x10}, /* TGI5V */ ++ {113,0xfffea5,0x10,0xfffea4,0x10}, /* TGI5V */ ++ {116,0xffffb2,0x40,0xffffb0,0x40}, /* CMIA0 */ ++ {117,0xffffb2,0x80,0xffffb0,0x80}, /* CMIB0 */ ++ {118,0xffffb3,0x80,0xffffb1,0x40}, /* OVI0 */ ++ {119,0xffffb2,0x20,0xffffb0,0x20}, /* CMIA1 */ ++ {120,0xffffb3,0x40,0xffffb1,0x40}, /* CMIB1 */ ++ {121,0xffffb3,0x20,0xffffb1,0x20}, /* OVI1 */ ++ {144,0xffff7c,0x38,0xffff7a,0x40}, /* ERI0 */ ++ {145,0xffff7c,0x40,0xffff7a,0x40}, /* RXI0 */ ++ {146,0xffff7c,0x80,0xffff7a,0x80}, /* TXI0 */ ++ {147,0xffff7c,0x04,0xffff7a,0x04}, /* TEI0 */ ++ {148,0xffff84,0x38,0xffff82,0x40}, /* ERI1 */ ++ {149,0xffff84,0x40,0xffff82,0x40}, /* RXI1 */ ++ {150,0xffff84,0x80,0xffff82,0x80}, /* TXI1 */ ++ {151,0xffff84,0x04,0xffff82,0x04}, /* TEI1 */ ++ {152,0xffff8c,0x38,0xffff8a,0x40}, /* ERI2 */ ++ {153,0xffff8c,0x40,0xffff8a,0x40}, /* RXI2 */ ++ {154,0xffff8c,0x80,0xffff8a,0x80}, /* TXI2 */ ++ {155,0xffff8c,0x04,0xffff8a,0x04}, /* TEI2 */ ++ {-1,0,0,0,0} ++}; ++ ++void ++timer8(SIM_DESC sd, unsigned int cycles_diff) ++{ ++ static int prescale[3]={8,64,8192}; ++ const int prescale_div[3]={8,64,8192}; ++ static unsigned char tcsr[4]={0x00,0x00,0x00,0x00}; ++ int tm, cnt, pcnt, cor; ++ for (pcnt = 0; pcnt < 3; pcnt++) ++ { ++ prescale[pcnt] -= cycles_diff; ++ ++ if (prescale[pcnt]<=0) ++ { ++ /* input time pulse */ ++ for(tm=0; timer8_base[tm] != 0; tm++) ++ { ++ if ((TCR8(tm) & 0x07) == 0) ++ continue; ++ /* internal TCSR status clear */ ++ tcsr[tm] &= (TCSR8(tm) & 0xf0); ++ ++ if ((TCR8(tm & 2) & 0x7) == 0x04) ++ { ++ /* 16bit mode */ ++ if (tm & 1) ++ continue; ++ tcsr[tm+1] &= (TCSR8(tm+1) & 0xf0); ++ cnt = TCNT8(tm) << 8 | TCNT8(tm+1); ++ cnt++; ++ if (cnt >= 0x10000) ++ { ++ tcsr[tm] |= 0x20; ++ cnt = 0; ++ } ++ TCNT8(tm) = cnt >> 8; ++ TCNT8(tm-1) = cnt & 0xff; ++ /* TCORA compare match check */ ++ cor = TCORA8(tm) << 8 | TCORA8(tm+1); ++ if (cnt >= cor) ++ { ++ tcsr[tm]|=0x40; ++ if ((TCR8(tm) & 0x18) == 0x08) ++ cnt = 0; ++ } ++ if ((cnt & 0xff) >= (cor & 0xff)) ++ tcsr[tm+1]|=0x40; ++ /* TCORB compare match check */ ++ cor = TCORB8(tm) << 8 | TCORB8(tm+1); ++ if (cnt >= cor) ++ { ++ tcsr[tm]|=0x80; ++ if ((TCR8(tm) & 0x18) == 0x10) ++ cnt = 0; ++ } ++ if ((cnt & 0xff) >= (cor & 0xff)) ++ tcsr[tm+1]|=0x80; ++ TCNT8(tm) = cnt >> 8; ++ TCNT8(tm+1) = cnt & 0xff; ++ /* update TSCR */ ++ TCSR8(tm) &= 0x1f; ++ TCSR8(tm) |= (tcsr[tm] & 0xe0); ++ TCSR8(tm+1) &= 0x1f; ++ TCSR8(tm+1) |= (tcsr[tm+1] & 0xe0); ++ } ++ else ++ { ++ /* 8bit mode */ ++ /* update counter */ ++ if ((TCR8(tm) & 0x07) == (pcnt+1)) ++ { ++ cnt = ++TCNT8(tm); ++ if (cnt>=0x100) ++ { ++ tcsr[tm] |= 0x20; ++ cnt = 0; ++ } ++ } ++ /* TCORA compare match check*/ ++ if (cnt >= TCORA8(tm)) ++ { ++ tcsr[tm]|=0x40; ++ if ((TCR8(tm) & 0x18) == 0x08) ++ cnt = 0; ++ } ++ /* TCORB compare match check*/ ++ if (cnt >= TCORB8(tm)) ++ { ++ tcsr[tm]|=0x80; ++ if ((TCR8(tm) & 0x18) == 0x10) ++ cnt = 0; ++ } ++ TCNT8(tm) = cnt; ++ /* update TSCR */ ++ TCSR8(tm) &= 0x1f; ++ TCSR8(tm) |= (tcsr[tm] & 0xe0); ++ } ++ } ++ prescale[pcnt]+=prescale_div[pcnt]; ++ } ++ } ++} ++ ++static void ++h8300sx_timer16(SIM_DESC sd, unsigned int cycles_diff) ++{ ++ static int prescale[4]={1,4,16,64}; ++ const int prescale_div[4]={1,4,16,64}; ++ static int tsr[TPU_CH]; ++ int tm, cnt, pcnt, gr, pulse; ++ for (pcnt = 0; pcnt < 4; pcnt++) { ++ prescale[pcnt] -= cycles_diff; ++ pulse = -prescale[pcnt] / prescale_div[cnt] + 1; ++ if (prescale[pcnt]<=0) ++ { ++ /* input time pulse */ ++ for(tm=0; tm < TPU_CH; tm++) { ++ ++ /* Timer enable check */ ++ if (!(TPU_TSTR & (1 << tm))) ++ continue; ++ ++ /* internal TCSR status clear */ ++ tsr[tm] &= TPU_TSR(tm); ++ /* update counter */ ++ if ((TPU_TCR(tm) & 0x07) == pcnt) ++ { ++ cnt = ((TPU_TCNTH(tm) << 8) | TPU_TCNTL(tm)); ++ cnt += pulse; ++ ++ /* CNT overflow check */ ++ if (cnt>=0x10000) ++ { ++ tsr[tm] |= 0x10; ++ cnt = 0; ++ } ++ ++ /* GRA compare match check*/ ++ gr = (TPU_GRAH(tm) << 8) | TPU_GRAL(tm); ++ if (cnt >= gr) ++ { ++ tsr[tm] |= 0x1; ++ if ((TPU_TCR(tm) & 0x60) == 0x20) ++ cnt = 0; ++ } ++ ++ /* GRB compare match check*/ ++ gr = (TPU_GRBH(tm) << 8) | TPU_GRBL(tm); ++ if (cnt >= gr) ++ { ++ tsr[tm] |= 0x2; ++ if ((TPU_TCR(tm) & 0x60) == 0x20) ++ cnt = 0; ++ } ++ ++ /* update TCNT */ ++ TPU_TCNTH(tm) = (cnt >> 8); ++ TPU_TCNTL(tm) = cnt & 0xff; ++ } ++ ++ } ++ prescale[pcnt]+=prescale_div[pcnt]; ++ /* update TSR */ ++ TPU_TSR(tm) |= tsr[tm]; ++ } ++ } ++} ++ ++static void ++h8300s_timer16(SIM_DESC sd, unsigned int cycles_diff) ++{ ++ static int prescale[4]={1,4,16,64}; ++ const int prescale_div[4]={1,4,16,64}; ++ static int tsr[TPU_CH]; ++ int tm, cnt, pcnt, gr, pulse; ++ for (pcnt = 0; pcnt < 4; pcnt++) { ++ prescale[pcnt] -= cycles_diff; ++ pulse = -prescale[pcnt] / prescale_div[pcnt] + 1; ++ if (prescale[pcnt]<=0) ++ { ++ /* input time pulse */ ++ for(tm=0; tm < TPU_CH; tm++) { ++ ++ /* Timer enable check */ ++ if (!(TPU_TSTR & (1 << tm))) ++ continue; ++ ++ /* internal TCSR status clear */ ++ tsr[tm] &= TPU_TSR(tm); ++ /* update counter */ ++ if ((TPU_TCR(tm) & 0x0f) == pcnt) ++ { ++ cnt = ((TPU_TCNTH(tm) << 8) | TPU_TCNTL(tm)); ++ cnt += pulse; ++ ++ /* CNT overflow check */ ++ if (cnt>=0x10000) ++ { ++ int cascade_low = tm % 3; ++ tsr[tm] |= 0x10; ++ cnt -= 0x10000; ++ if (cascade_low == 2) ++ { ++ int cascade_high = tm - cascade_low + 1; ++ if (TPU_TCR(cascade_high) & 0x0f == 0x0f) ++ { ++ int cascade_cnt; ++ cascade_cnt = ((TPU_TCNTH(cascade_high) << 8) | ++ TPU_TCNTL(cascade_high)); ++ cascade_cnt++; ++ TPU_TCNTH(cascade_high) = (cascade_cnt >> 8); ++ TPU_TCNTL(cascade_high) = cascade_cnt & 0xff; ++ } ++ } ++ } ++ ++ /* GRA compare match check*/ ++ gr = (TPU_GRAH(tm) << 8) | TPU_GRAL(tm); ++ if (cnt >= gr) ++ { ++ tsr[tm] |= 0x1; ++ if ((TPU_TCR(tm) & 0xe0) == 0x20) ++ cnt = 0; ++ } ++ ++ /* GRB compare match check*/ ++ gr = (TPU_GRBH(tm) << 8) | TPU_GRBL(tm); ++ if (cnt >= gr) ++ { ++ tsr[tm] |= 0x2; ++ if ((TPU_TCR(tm) & 0xe0) == 0x40) ++ cnt = 0; ++ } ++ ++ /* update TCNT */ ++ TPU_TCNTH(tm) = (cnt >> 8); ++ TPU_TCNTL(tm) = cnt & 0xff; ++ } ++ ++ } ++ prescale[pcnt]+=prescale_div[pcnt]; ++ /* update TSR */ ++ TPU_TSR(tm) |= tsr[tm]; ++ } ++ } ++} ++ ++static void ++h8300h_timer16(SIM_DESC sd, unsigned int cycles_diff) ++{ ++ static int prescale[4]={1,2,4,8}; ++ const int prescale_div[4]={1,2,4,8}; ++ static int tisra, tisrb, tisrc; ++ int tm, cnt, pcnt, gr, pulse; ++ for (pcnt = 0; pcnt < 4; pcnt++) { ++ prescale[pcnt] -= cycles_diff; ++ if (prescale[pcnt]<=0) ++ { ++ pulse = -prescale[pcnt] / prescale_div[pcnt] + 1; ++ prescale[pcnt]+=prescale_div[pcnt]; ++ /* input time pulse */ ++ for(tm=0; tm < 3; tm++) { ++ ++ /* Timer enable check */ ++ if (!(TSTR16 & (1 << tm))) ++ continue; ++ ++ /* internal TCSR status clear */ ++ tisra &= (0x07 & (TISRA16 & (1 << tm))); ++ tisrb &= (0x07 & (TISRB16 & (1 << tm))); ++ tisrc &= (0x07 & (TISRC16 & (1 << tm))); ++ /* update counter */ ++ if ((TCR16(tm) & 0x07) == pcnt) ++ { ++ cnt = ((TCNT16H(tm) << 8) | TCNT16L(tm)); ++ cnt += pulse; ++ ++ /* CNT overflow check */ ++ if (cnt>=0x10000) ++ { ++ tisrc |= (1 << tm); ++ cnt = 0; ++ } ++ ++ /* GRA compare match check*/ ++ gr = (GRA16H(tm) << 8) | GRA16L(tm); ++ if (cnt >= gr) ++ { ++ tisra |= (1 << tm); ++ if ((TCR16(tm) & 0x60) == 0x20) ++ cnt = 0; ++ } ++ ++ /* GRB compare match check*/ ++ gr = (GRB16H(tm) << 8) | GRB16L(tm); ++ if (cnt >= gr) ++ { ++ tisrb |= (1 << tm); ++ if ((TCR16(tm) & 0x60) == 0x40) ++ cnt = 0; ++ } ++ /* update TCNT */ ++ TCNT16H(tm) = (cnt >> 8); ++ TCNT16L(tm) = cnt & 0xff; ++ } ++ ++ } ++ /* update TSCR */ ++ TISRA16 &= 0x70; ++ TISRA16 |= tisra; ++ TISRB16 &= 0x70; ++ TISRB16 |= tisrb; ++ TISRC16 &= 0x70; ++ TISRC16 |= tisrc; ++ } ++ } ++} ++ ++static struct { ++ int fd; ++ int socket; ++ int iac; ++ unsigned char cmd; ++ struct sockaddr_in local; ++ struct sockaddr_in remote; ++ struct termios old_attr; ++} sci_port[MAX_SCI_CH]; ++ ++enum {PORT_NONE, PORT_PTY,PORT_NET}; ++static int sci_port_type = PORT_NONE; ++ ++static unsigned int ++sci_complete_time(SIM_DESC sd, int ch) ++{ ++ int length; ++ int div[]={1,4,16,64}; ++ length = (SMR(ch) & 0x40)?7:8; ++ length += (SMR(ch) & 0x20)?1:0; ++ length += (SMR(ch) & 0x08)?1:0; ++ length += 2; ++ return length * 32 * div[SMR(ch) & 0x03] * BRR(ch); ++} ++ ++static void ++sci_send_data(int ch, int txd) ++{ ++ char dt = txd; ++ if (sci_port[ch].fd >= 0) { ++ if (write(sci_port[ch].fd, &dt, 1) > 0) ++ fsync(sci_port[ch].fd); ++ else ++ if (errno != EAGAIN) ++ sci_port[ch].fd = -1; ++ } ++} ++ ++static void ++telnet_escape(int ch, char rd) ++{ ++ unsigned char cmd = sci_port[ch].cmd; ++ unsigned char rep[3]; ++ switch(sci_port[ch].iac) ++ { ++ case 1: ++ sci_port[ch].cmd = rd; ++ sci_port[ch].iac++; ++ break; ++ case 2: ++ if ((rd == 1 || rd == 3) && cmd == 0xfd) ++ { ++ sci_port[ch].iac = 0; ++ return; ++ } ++ else if (rd == 1 || rd == 3) ++ { ++ if (cmd == 0xfb) ++ cmd = 0xfd; ++ else if (cmd == 0xfd) ++ cmd = 0xfb; ++ } ++ else ++ { ++ if (cmd == 0xfb) ++ cmd = 0xfe; ++ else if (cmd == 0xfd) ++ cmd = 0xfc; ++ } ++ rep[0] = 0xff; ++ rep[1] = cmd; ++ rep[2] = rd; ++ write(sci_port[ch].fd, rep, sizeof(rep)); ++ sci_port[ch].iac = 0; ++ break; ++ } ++} ++ ++static void ++telnet_request(int fd) ++{ ++ static unsigned char req[6] = {0xff, 0xfb, 0x03, 0xff, 0xfb, 0x01}; ++ write(fd, req, sizeof(req)); ++} ++ ++ ++int ++sci_rcv_data(int ch, int *rxd) ++{ ++ unsigned char rd; ++ if (sci_port[ch].fd >= 0) ++ { ++ if( read(sci_port[ch].fd, &rd , 1) > 0 ) ++ { ++ if (sci_port_type == PORT_NET) ++ { ++ if (sci_port[ch].iac > 0) ++ { ++ telnet_escape(ch, rd); ++ return 0; ++ } ++ else ++ if (rd == 0xff) ++ { ++ sci_port[ch].iac = 1; ++ return 0; ++ } ++ } ++ *rxd = rd; ++ return 1; ++ } ++ else ++ { ++ if (errno == EAGAIN) ++ { ++ return 0; ++ } ++ else ++ { ++ close(sci_port[ch].fd); ++ sci_port[ch].fd = -1; ++ } ++ } ++ } ++ return 0; ++} ++ ++static int net_accept(void) ++{ ++ int ch; ++ for (ch = 0; ch < MAX_SCI_CH; ch++) ++ { ++ if(sci_port[ch].fd == -1) ++ { ++ int connectfd; ++ socklen_t rem_size = sizeof(sci_port[ch].remote); ++ connectfd = accept(sci_port[ch].socket, ++ (struct sockaddr *)&sci_port[ch].remote, ++ &rem_size); ++ if (connectfd > 0) ++ { ++ unsigned char rd; ++ int flag; ++ sci_port[ch].fd = connectfd; ++ telnet_request(connectfd); ++ sci_port[ch].iac = 0; ++ flag = fcntl(sci_port[ch].fd, F_GETFL, 0); ++ fcntl(sci_port[ch].fd, F_SETFL, flag | O_NONBLOCK); ++ ++ while ( read(sci_port[ch].fd, &rd , 1) > 0 ) ++ { ++ if (sci_port[ch].iac > 0) ++ { ++ telnet_escape(ch, rd); ++ return 1; ++ } ++ else ++ if (rd == 0xff) ++ { ++ sci_port[ch].iac = 1; ++ return 1; ++ } ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++static void ++sci(SIM_DESC sd, unsigned int cycles_diff) ++{ ++ static int tx_end_time[MAX_SCI_CH]; ++ static int rx_end_time[MAX_SCI_CH]; ++ static int txstate = 0; ++ int data; ++ int ch; ++ ++ if (sci_port_type == PORT_NET && net_accept()) ++ return; ++ ++ for (ch = 0; ch < MAX_SCI_CH; ch++) ++ { ++ /* clear internal ssr */ ++ ssr[ch] &= SSR(ch); ++ ++ /* Tx request */ ++ if((SCR(ch) & 0x20) && !(ssr[ch] & 0x80) && (txstate == 0)) ++ { ++ sci_send_data(ch,TDR(ch)); ++ ssr[ch] &= ~0x04; ++ /* TSR shift time */ ++ tx_end_time[ch] = 1; ++ txstate = 1; ++ } ++ tx_end_time[ch] -= cycles_diff; ++ /* Tx complete check */ ++ if(((ssr[ch] & 0x84) != 0x84) && (tx_end_time[ch] <= 0)) ++ if (!(ssr[ch] & 0x80)) ++ { ++ ssr[ch] |= 0x80; ++ tx_end_time[ch] = sci_complete_time(sd, ch); ++ txstate = 0; ++ } ++ else ++ ssr[ch] |= 0x04; /* All data transmit done */ ++ rx_end_time[ch] -= cycles_diff; ++ /* Rx check */ ++ if (rx_end_time[ch] <= 0) ++ /* RSR free & Rx Enabled */ ++ if ((SCR(ch) & 0x10) && sci_rcv_data(ch, &data)) ++ { ++ /* Rx Overrun */ ++ if(ssr[ch] & 0x40) ++ ssr[ch] |= 0x20; ++ else ++ /* Rx ok */ ++ { ++ RDR(ch)=data; ++ ssr[ch] |= 0x40; ++ } ++ /* RSR shift time */ ++ rx_end_time[ch] = sci_complete_time(sd, ch); ++ } ++ ++ /* update SSR */ ++ SSR(ch) = ssr[ch]; ++ } ++} ++ ++static int ++get_priority(SIM_DESC sd, int vec) ++{ ++ const static int ipr_bit[] = { ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, 7, 6, 5, 5, ++ 4, 4, 4, 4, 3, 3, 3, 3, ++ 2, 2, 2, 2, 1, 1, 1, 1, ++ 0, 0, 0, 0, 15, 15, 15, 15, ++ 14, 14, 14, 14, 13, 13, 13, 13, ++ -1, -1, -1, -1, 11, 11, 11, 11, ++ 10, 10, 10, 10, 9, 9, 9, 9, ++ }; ++ const static unsigned char ipr_table[] = { ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ ++ 0x03, 0x02, 0x01, 0x00, 0x13, 0x12, 0x11, 0x10, /* 16 - 23 */ ++ 0x23, 0x22, 0x21, 0x20, 0x33, 0x32, 0x31, 0x30, /* 24 - 31 */ ++ 0x43, 0x42, 0x41, 0x40, 0x53, 0x53, 0x52, 0x52, /* 32 - 39 */ ++ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, /* 40 - 47 */ ++ 0x50, 0x50, 0x50, 0x50, 0x63, 0x63, 0x63, 0x63, /* 48 - 55 */ ++ 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, /* 56 - 63 */ ++ 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, 0x60, 0x60, /* 64 - 71 */ ++ 0x73, 0x73, 0x73, 0x73, 0x72, 0x72, 0x72, 0x72, /* 72 - 79 */ ++ 0x71, 0x71, 0x71, 0x71, 0x70, 0x83, 0x82, 0x81, /* 80 - 87 */ ++ 0x80, 0x80, 0x80, 0x80, 0x93, 0x93, 0x93, 0x93, /* 88 - 95 */ ++ 0x92, 0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, /* 96 - 103 */ ++ 0x90, 0x90, 0x90, 0x90, 0xa3, 0xa3, 0xa3, 0xa3, /* 104 - 111 */ ++ 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, /* 112 - 119 */ ++ 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, /* 120 - 127 */ ++ }; ++ ++ ++ if (h8300smode) ++ { ++ unsigned short ipr; ++ int pos; ++ if ((pos = ipr_table[vec]) == 0xff) ++ return 0; ++ ipr = (STATE_CPU(sd, 0)->memory[IPRA_H8300S + ((pos & 0xf0) >> 3)] << 8) | ++ (STATE_CPU(sd, 0)->memory[IPRA_H8300S + ((pos & 0xf0) >> 3) + 1]); ++ return vec + ((ipr >> ((pos & 0x0f) * 4)) & 7) * 0x100; ++ } ++ else if (h8300hmode) ++ { ++ int b; ++ unsigned char ipr; ++ if ((b = ipr_bit[vec]) < 0) ++ return 0; ++ ipr = (b < 8)?STATE_CPU(sd, 0)->memory[IPRA_H8300H]: ++ STATE_CPU(sd, 0)->memory[IPRB_H8300H]; ++ b = 1 << (b & 7); ++ if (ipr & b) ++ return vec + 0x100; ++ else ++ return vec; ++ } ++} ++ ++static int ++intcont(SIM_DESC sd) ++{ ++ int irqno; ++ for (irqno=0; int_table[irqno].vector > 0; irqno++) ++ { ++ if((STATE_CPU(sd, 0)->memory[int_table[irqno].ier_adr] & ++ int_table[irqno].ier_mask) && ++ (STATE_CPU(sd, 0)->memory[int_table[irqno].isr_adr] & ++ int_table[irqno].isr_mask)) ++ return get_priority(sd, int_table[irqno].vector); ++ } ++ return 0; ++} ++ ++int ++iosimulation(SIM_DESC sd, int cycles) ++{ ++ static unsigned int prev_cycles = 0; ++ unsigned int cycles_diff; ++ cycles_diff = (cycles < prev_cycles)?cycles:(cycles - prev_cycles); ++ prev_cycles = cycles; ++ timer8(sd, cycles_diff); ++ if (h8300smode) ++ h8300s_timer16(sd, cycles_diff); ++ else if (h8300hmode) ++ h8300h_timer16(sd, cycles_diff); ++ sci(sd, cycles_diff); ++ return intcont(sd); ++} ++ ++void init_ioregs(SIM_DESC sd) ++{ ++ struct INITTABLE { ++ unsigned char addr; ++ unsigned char data; ++ }; ++ const struct INITTABLE h8300h_reg_ini[] = { ++ 0x80,0x00, ++ 0x81,0x00, ++ 0x82,0x00, ++ 0x83,0x00, ++ 0x84,0xff, ++ 0x85,0xff, ++ 0x86,0xff, ++ 0x87,0xff, ++ 0x88,0x00, ++ 0x89,0x00, ++ 0x90,0x00, ++ 0x91,0x00, ++ 0x92,0x00, ++ 0x93,0x00, ++ 0x94,0xff, ++ 0x95,0xff, ++ 0x96,0xff, ++ 0x97,0xff, ++ 0x98,0x00, ++ 0x99,0x00, ++ 0xb0,0x00, ++ 0xb1,0xff, ++ 0xb2,0x00, ++ 0xb3,0xff, ++ 0xb4,0x84, ++ 0xb8,0x00, ++ 0xb9,0xff, ++ 0xba,0x00, ++ 0xbb,0xff, ++ 0xbc,0x84, ++ 0xc0,0x00, ++ 0xc1,0xff, ++ 0xc2,0x00, ++ 0xc3,0xff, ++ 0xc4,0x84, ++ }; ++ const struct INITTABLE h8300s_reg_ini[] = { ++ 0xb0,0x00, ++ 0xb1,0x00, ++ 0xb2,0x00, ++ 0xb3,0x00, ++ 0xb4,0xff, ++ 0xb5,0xff, ++ 0xb6,0xff, ++ 0xb7,0xff, ++ 0xb8,0x00, ++ 0xb9,0x00, ++ 0x78,0x00, ++ 0x79,0xff, ++ 0x7a,0x00, ++ 0x7b,0xff, ++ 0x7c,0x84, ++ 0x80,0x00, ++ 0x81,0xff, ++ 0x82,0x00, ++ 0x83,0xff, ++ 0x84,0x84, ++ 0x88,0x00, ++ 0x89,0xff, ++ 0x8a,0x00, ++ 0x8b,0xff, ++ 0x8c,0x84, ++ }; ++ const struct INITTABLE h8300sx_reg_ini[] = { ++ 0xb0,0x00, ++ 0xb1,0x00, ++ 0xb2,0x00, ++ 0xb3,0x00, ++ 0xb4,0xff, ++ 0xb5,0xff, ++ 0xb6,0xff, ++ 0xb7,0xff, ++ 0xb8,0x00, ++ 0xb9,0x00, ++ 0x80,0x00, ++ 0x81,0xff, ++ 0x82,0x00, ++ 0x83,0xff, ++ 0x84,0x84, ++ 0x88,0x00, ++ 0x89,0xff, ++ 0x8a,0x00, ++ 0x8b,0xff, ++ 0x8c,0x84, ++ 0x60,0x00, ++ 0x61,0xff, ++ 0x62,0x00, ++ 0x63,0xff, ++ 0x64,0x84, ++ }; ++ int c; ++ if (h8300sxmode) { ++ sci_base = h8300sx_sci_base; ++ timer8_base = h8300s_timer8_base; ++ int_table = h8300sx_int_table; ++ for(c=0;ceightbit[h8300sx_reg_ini[c].addr]=h8300sx_reg_ini[c].data; ++ } ++ else if (h8300smode) { ++ sci_base = h8300s_sci_base; ++ timer8_base = h8300s_timer8_base; ++ int_table = h8300s_int_table; ++ for(c=0;ceightbit[h8300s_reg_ini[c].addr]=h8300s_reg_ini[c].data; ++ } ++ else if (h8300hmode) { ++ sci_base = h8300h_sci_base; ++ timer8_base = h8300h_timer8_base; ++ int_table = h8300h_int_table; ++ for(c=0;ceightbit[h8300h_reg_ini[c].addr]=h8300h_reg_ini[c].data; ++ } ++ for(c = 0; c< MAX_SCI_CH; c++) ++ ssr[c] = 0x84; ++} ++ ++static char *openpty(int ch) ++{ ++ const char nm[]="0123456789ABCDEF"; ++ static char ptyname[16]; ++ int c1,c2,fd; ++ struct termios attr; ++ fd = open("/dev/ptmx",O_RDWR|O_NONBLOCK); ++ if(fd >= 0) { ++ grantpt(fd); ++ unlockpt(fd); ++ ptsname_r(fd, ptyname, sizeof(ptyname)); ++ } else { ++ for(c1='a';c1<='z';c1++) ++ for(c2=0;c2= 0) { ++ sci_port[ch].fd = fd; ++ tcgetattr(fd, &attr); ++ memcpy(&sci_port[ch].old_attr, &attr, sizeof(struct termios)); ++ attr.c_lflag &= ~ICANON; ++ attr.c_cc[VMIN] = 0; ++ attr.c_cc[VTIME] =0; ++ tcsetattr(fd, TCSAFLUSH, &attr); ++ return ptyname; ++ } else { ++ sci_port[ch].fd = -1; ++ return NULL; ++ } ++} ++ ++void sci_open_pty(struct host_callback_struct *callback) ++{ ++ int ch; ++ int max_ch; ++ char *pty; ++ for (ch = 0; ch < MAX_SCI_CH; ch++) ++ { ++ pty = openpty(ch); ++ if (pty) ++ (*callback->printf_filtered) (callback, "SCI%d = %s\n",ch ,pty); ++ } ++} ++ ++void sci_open_net(struct host_callback_struct *callback, int port) ++{ ++ int c; ++ int flag; ++ int socketfd; ++ sci_port_type = PORT_NET; ++ for (c = 0; c < MAX_SCI_CH; c++) { ++ memset(&sci_port[c].local, 0, sizeof(sci_port[c].local)); ++ sci_port[c].local.sin_family = AF_INET; ++ sci_port[c].local.sin_addr.s_addr = htonl(INADDR_ANY); ++ sci_port[c].local.sin_port = htons(port + c); ++ sci_port[c].fd = -1; ++ socketfd = socket(AF_INET, SOCK_STREAM, 0); ++ if (socketfd >= 0) ++ { ++ bind(socketfd, (struct sockaddr *)&sci_port[c].local, sizeof(sci_port[c].local)); ++ flag = fcntl(socketfd, F_GETFL, 0); ++ fcntl(socketfd, F_SETFL, flag | O_NONBLOCK); ++ listen(socketfd, 1); ++ sci_port[c].socket = socketfd; ++ (*callback->printf_filtered) (callback, "SCI%d = %d\n",c ,port+c); ++ } ++ } ++} ++ ++void sci_close(void) ++{ ++ int ch; ++ if (sci_port_type == PORT_NONE) ++ return; ++ for (ch = 0; ch < MAX_SCI_CH; ch++) { ++ if(sci_port[ch].fd != -1) { ++ if (sci_port_type == PORT_PTY) ++ tcsetattr(sci_port[ch].fd, TCSAFLUSH, &sci_port[ch].old_attr); ++ close(sci_port[ch].fd); ++ if (sci_port_type == PORT_NET) ++ close(sci_port[ch].socket); ++ } ++ } ++} -- cgit v1.2.3