X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=sim%2Fh8300%2Fcompile.c;h=8e4b55d6a2807d280fc74104eba1448fbb337331;hb=2ee563b53258d390d7446e90a67f465d504ae44c;hp=2545b1db7eb4508589061d6a24e28df30a6835e0;hpb=5d06fa80b20ad5cb5729eadc128b6ac970875eaf;p=binutils-gdb.git diff --git a/sim/h8300/compile.c b/sim/h8300/compile.c index 2545b1db7eb..8e4b55d6a28 100644 --- a/sim/h8300/compile.c +++ b/sim/h8300/compile.c @@ -19,6 +19,7 @@ #include "config.h" +#include #include #ifdef HAVE_TIME_H #include @@ -26,19 +27,35 @@ #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_SYS_PARAM_H #include -#include "wait.h" +#endif #include "ansidecl.h" -#include "callback.h" -#include "remote-sim.h" #include "bfd.h" +#include "gdb/callback.h" +#include "gdb/remote-sim.h" +#include "gdb/sim-h8300.h" + +#ifndef SIGTRAP +# define SIGTRAP 5 +#endif int debug; +host_callback *sim_callback; + +static SIM_OPEN_KIND sim_kind; +static char *myname; + +/* 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)); -#define X(op, size) op*4+size +#define X(op, size) op * 4 + size -#define SP (h8300hmode ? SL:SW) +#define SP (h8300hmode ? SL : SW) #define SB 0 #define SW 1 #define SL 2 @@ -51,50 +68,65 @@ int debug; #define OP_CCR 7 #define OP_IMM 8 #define OP_ABS 10 +#define OP_EXR 11 #define h8_opcodes ops #define DEFINE_TABLE #include "opcode/h8300.h" #include "inst.h" +/* The rate at which to call the host's poll_quit callback. */ + +#define POLL_QUIT_INTERVAL 0x80000 + #define LOW_BYTE(x) ((x) & 0xff) -#define HIGH_BYTE(x) (((x)>>8) & 0xff) -#define P(X,Y) ((X<<8) | Y) +#define HIGH_BYTE(x) (((x) >> 8) & 0xff) +#define P(X,Y) ((X << 8) | Y) -#define BUILDSR() cpu.ccr = (N << 3) | (Z << 2) | (V<<1) | C; +#define BUILDSR() cpu.ccr = (I << 7) | (UI << 6)| (H<<5) | (U<<4) | \ + (N << 3) | (Z << 2) | (V<<1) | C; + +#define BUILDEXR() \ + if (h8300smode) cpu.exr = (trace<<7) | intMask; #define GETSR() \ c = (cpu.ccr >> 0) & 1;\ v = (cpu.ccr >> 1) & 1;\ nz = !((cpu.ccr >> 2) & 1);\ - n = (cpu.ccr >> 3) & 1; + n = (cpu.ccr >> 3) & 1;\ + u = (cpu.ccr >> 4) & 1;\ + h = (cpu.ccr >> 5) & 1;\ + ui = ((cpu.ccr >> 6) & 1);\ + intMaskBit = (cpu.ccr >> 7) & 1; + +#define GETEXR() \ + if (h8300smode) { \ + trace = (cpu.exr >> 7) & 1;\ + intMask = cpu.exr & 7; } #ifdef __CHAR_IS_SIGNED__ -#define SEXTCHAR(x) ((char)(x)) +#define SEXTCHAR(x) ((char) (x)) #endif #ifndef SEXTCHAR -#define SEXTCHAR(x) ((x & 0x80) ? (x | ~0xff):x) +#define SEXTCHAR(x) ((x & 0x80) ? (x | ~0xff): x & 0xff) #endif #define UEXTCHAR(x) ((x) & 0xff) #define UEXTSHORT(x) ((x) & 0xffff) -#define SEXTSHORT(x) ((short)(x)) +#define SEXTSHORT(x) ((short) (x)) static cpu_state_type cpu; int h8300hmode = 0; +int h8300smode = 0; static int memory_size; - static int get_now () { -#ifndef WIN32 - return time (0); -#endif - return 0; + return time (0); /* WinXX HAS UNIX like 'time', so why not using it? */ } static int @@ -103,7 +135,6 @@ now_persec () return 1; } - static int bitfrom (x) { @@ -120,8 +151,7 @@ bitfrom (x) } } -static -unsigned int +static unsigned int lvalue (x, rn) { switch (x / 4) @@ -134,10 +164,10 @@ lvalue (x, rn) return X (OP_REG, SP); case OP_MEM: - return X (OP_MEM, SP); + default: - abort (); + abort (); /* ?? May be something more usefull? */ } } @@ -152,20 +182,20 @@ decode (addr, data, dst) int rd = 0; int rdisp = 0; int abs = 0; + int bit = 0; int plen = 0; - - struct h8_opcode *q = h8_opcodes; + struct h8_opcode *q; int size = 0; + dst->dst.type = -1; dst->src.type = -1; - /* Find the exact opcode/arg combo */ - while (q->name) + + /* Find the exact opcode/arg combo. */ + for (q = h8_opcodes; q->name; q++) { - op_type *nib; + op_type *nib = q->data.nib; unsigned int len = 0; - nib = q->data.nib; - while (1) { op_type looking_for = *nib; @@ -184,40 +214,40 @@ decode (addr, data, dst) { if (!(((int) thisnib & 0x8) != 0)) goto fail; - looking_for = (op_type) ((int) looking_for & ~(int) - B31); + + looking_for = (op_type) ((int) looking_for & ~(int) B31); thisnib &= 0x7; } + if ((int) looking_for & (int) B30) { if (!(((int) thisnib & 0x8) == 0)) goto fail; + looking_for = (op_type) ((int) looking_for & ~(int) B30); } + if (looking_for & DBIT) { - if ((looking_for & 5) != (thisnib & 5)) + /* Exclude adds/subs by looking at bit 0 and 2, and + make sure the operand size, either w or l, + matches by looking at bit 1. */ + if ((looking_for & 7) != (thisnib & 7)) goto fail; + abs = (thisnib & 0x8) ? 2 : 1; } else if (looking_for & (REG | IND | INC | DEC)) { if (looking_for & REG) { - /* - * Can work out size from the - * register - */ + /* Can work out size from the register. */ size = bitfrom (looking_for); } if (looking_for & SRC) - { - rs = thisnib; - } + rs = thisnib; else - { - rd = thisnib; - } + rd = thisnib; } else if (looking_for & L_16) { @@ -230,10 +260,7 @@ decode (addr, data, dst) } else if (looking_for & ABSJMP) { - abs = - (data[1] << 16) - | (data[2] << 8) - | (data[3]); + abs = (data[1] << 16) | (data[2] << 8) | (data[3]); } else if (looking_for & MEMIND) { @@ -242,6 +269,7 @@ decode (addr, data, dst) else if (looking_for & L_32) { int i = len >> 1; + abs = (data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) @@ -252,12 +280,13 @@ decode (addr, data, dst) else if (looking_for & L_24) { int i = len >> 1; + abs = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]); plen = 24; } else if (looking_for & IGNORE) { - /* nothing to do */ + ; } else if (looking_for & DISPREG) { @@ -276,6 +305,8 @@ decode (addr, data, dst) case 0: abs = 1; break; + default: + goto fail; } } else if (looking_for & L_8) @@ -286,6 +317,12 @@ decode (addr, data, dst) { abs = SEXTCHAR (data[len >> 1]); } + else if (looking_for & ABS8MEM) + { + plen = 8; + abs = h8300hmode ? ~0xff0000ff : ~0xffff00ff; + abs |= data[len >> 1] & 0xff; + } else { abs = data[len >> 1] & 0xff; @@ -295,13 +332,13 @@ decode (addr, data, dst) { plen = 3; - abs = thisnib; + bit = thisnib; } else if (looking_for == E) { dst->op = q; - /* Fill in the args */ + /* Fill in the args. */ { op_type *args = q->args.nib; int hadone = 0; @@ -313,23 +350,24 @@ decode (addr, data, dst) ea_type *p; if (x & DST) - { - p = &(dst->dst); - } + p = &(dst->dst); else + p = &(dst->src); + + if (x & L_3) { - p = &(dst->src); + p->type = X (OP_IMM, size); + p->literal = bit; } - - if (x & (IMM | KBIT | DBIT)) + else if (x & (IMM | KBIT | DBIT)) { p->type = X (OP_IMM, size); p->literal = abs; } else if (x & REG) { - /* Reset the size, some - ops (like mul) have two sizes */ + /* Reset the size. + Some ops (like mul) have two sizes. */ size = bitfrom (x); p->type = X (OP_REG, size); @@ -351,7 +389,7 @@ decode (addr, data, dst) p->reg = rn & 0x7; p->literal = 0; } - else if (x & (ABS | ABSJMP | ABSMOV)) + else if (x & (ABS | ABSJMP | ABS8MEM)) { p->type = X (OP_DISP, size); p->literal = abs; @@ -384,6 +422,10 @@ decode (addr, data, dst) { p->type = OP_CCR; } + else if (x & EXR) + { + p->type = OP_EXR; + } else printf ("Hmmmm %x", x); @@ -391,12 +433,9 @@ decode (addr, data, dst) } } - /* - * But a jmp or a jsr gets - * automagically lvalued, since we - * branch to their address not their - * contents - */ + /* But a jmp or a jsr gets automagically lvalued, + since we branch to their address not their + contents. */ if (q->how == O (O_JSR, SB) || q->how == O (O_JMP, SB)) { @@ -409,7 +448,7 @@ decode (addr, data, dst) dst->opcode = q->how; dst->cycles = q->time; - /* And a jsr to 0xc4 is turned into a magic trap */ + /* And a jsr to 0xc4 is turned into a magic trap. */ if (dst->opcode == O (O_JSR, SB)) { @@ -423,9 +462,7 @@ decode (addr, data, dst) return; } else - { - printf ("Dont understand %x \n", looking_for); - } + printf ("Don't understand %x \n", looking_for); } len++; @@ -433,20 +470,19 @@ decode (addr, data, dst) } fail: - q++; + ; } + /* Fell off the end. */ dst->opcode = O (O_ILL, SB); } - static void compile (pc) { int idx; - /* find the next cache entry to use */ - + /* Find the next cache entry to use. */ idx = cpu.cache_top + 1; cpu.compiles++; if (idx >= cpu.csize) @@ -455,16 +491,16 @@ compile (pc) } cpu.cache_top = idx; - /* Throw away its old meaning */ + /* Throw away its old meaning. */ cpu.cache_idx[cpu.cache[idx].oldpc] = 0; - /* set to new address */ + /* Set to new address. */ cpu.cache[idx].oldpc = pc; - /* fill in instruction info */ + /* Fill in instruction info. */ decode (pc, cpu.memory + pc, cpu.cache + idx); - /* point to new cache entry */ + /* Point to new cache entry. */ cpu.cache_idx[pc] = idx; } @@ -482,26 +518,34 @@ static unsigned int *lreg[18]; #define SET_L_REG(x,y) (*(lreg[x])) = (y) #define GET_MEMORY_L(x) \ - ((cpu.memory[x+0] << 24) | (cpu.memory[x+1] << 16) | (cpu.memory[x+2] << 8) | cpu.memory[x+3]) + (x < memory_size \ + ? ((cpu.memory[x+0] << 24) | (cpu.memory[x+1] << 16) \ + | (cpu.memory[x+2] << 8) | cpu.memory[x+3]) \ + : ((cpu.eightbit[(x+0) & 0xff] << 24) | (cpu.eightbit[(x+1) & 0xff] << 16) \ + | (cpu.eightbit[(x+2) & 0xff] << 8) | cpu.eightbit[(x+3) & 0xff])) #define GET_MEMORY_W(x) \ - ((cpu.memory[x+0] << 8) | (cpu.memory[x+1] << 0)) + (x < memory_size \ + ? ((cpu.memory[x+0] << 8) | (cpu.memory[x+1] << 0)) \ + : ((cpu.eightbit[(x+0) & 0xff] << 8) | (cpu.eightbit[(x+1) & 0xff] << 0))) -#define SET_MEMORY_B(x,y) \ - (cpu.memory[(x)] = y) - -#define SET_MEMORY_W(x,y) \ -{register unsigned char *_p = cpu.memory+x;\ - register int __y = y;\ - _p[0] = (__y)>>8;\ - _p[1] =(__y); } +#define GET_MEMORY_B(x) \ + (x < memory_size ? (cpu.memory[x]) : (cpu.eightbit[x & 0xff])) #define SET_MEMORY_L(x,y) \ -{register unsigned char *_p = cpu.memory+x;register int __y = y;\ - _p[0] = (__y)>>24; _p[1] = (__y)>>16; _p[2] = (__y)>>8; _p[3] = (__y)>>0;} +{ register unsigned char *_p; register int __y = y; \ + _p = (x < memory_size ? cpu.memory+x : cpu.eightbit + (x & 0xff)); \ + _p[0] = (__y)>>24; _p[1] = (__y)>>16; \ + _p[2] = (__y)>>8; _p[3] = (__y)>>0;} + +#define SET_MEMORY_W(x,y) \ +{ register unsigned char *_p; register int __y = y; \ + _p = (x < memory_size ? cpu.memory+x : cpu.eightbit + (x & 0xff)); \ + _p[0] = (__y)>>8; _p[1] =(__y);} -#define GET_MEMORY_B(x) (cpu.memory[x]) +#define SET_MEMORY_B(x,y) \ + (x < memory_size ? (cpu.memory[(x)] = y) : (cpu.eightbit[x & 0xff] = y)) int fetch (arg, n) @@ -574,15 +618,19 @@ fetch (arg, n) t &= cpu.mask; return t; + case X (OP_MEM, SW): + t = GET_MEMORY_W (abs); + t &= cpu.mask; + return t; + default: - abort (); + abort (); /* ?? May be something more usefull? */ } } -static -void +static void store (arg, n) ea_type *arg; int n; @@ -658,8 +706,7 @@ static union littleendian; -static -void +static void init_pointers () { static int init; @@ -671,14 +718,17 @@ init_pointers () init = 1; littleendian.i = 1; - if (h8300hmode) + if (h8300smode) + memory_size = H8300S_MSIZE; + else if (h8300hmode) memory_size = H8300H_MSIZE; else memory_size = H8300_MSIZE; cpu.memory = (unsigned char *) calloc (sizeof (char), memory_size); cpu.cache_idx = (unsigned short *) calloc (sizeof (short), memory_size); + cpu.eightbit = (unsigned char *) calloc (sizeof (char), 256); - /* `msize' must be a power of two */ + /* `msize' must be a power of two. */ if ((memory_size & (memory_size - 1)) != 0) abort (); cpu.mask = memory_size - 1; @@ -725,9 +775,9 @@ init_pointers () lreg[8] = &cpu.regs[8]; - /* initialize the seg registers */ + /* Initialize the seg registers. */ if (!cpu.cache) - sim_csize (CSIZE); + sim_set_simcache_size (CSIZE); } } @@ -738,6 +788,7 @@ control_c (sig, code, scp, addr) char *scp; char *addr; { + cpu.state = SIM_STATE_STOPPED; cpu.exception = SIGINT; } @@ -745,6 +796,10 @@ control_c (sig, code, scp, addr) #define Z (nz == 0) #define V (v != 0) #define N (n != 0) +#define U (u != 0) +#define H (h != 0) +#define UI (ui != 0) +#define I (intMaskBit != 0) static int mop (code, bsize, sign) @@ -790,12 +845,13 @@ mop (code, bsize, sign) { SET_L_REG (code->dst.reg, result); } -/* return ((n==1) << 1) | (nz==1); */ - +#if 0 + return ((n == 1) << 1) | (nz == 1); +#endif } -#define OSHIFTS(name, how) \ -case O(name, SB): \ +#define ONOT(name, how) \ +case O (name, SB): \ { \ int t; \ int hm = 0x80; \ @@ -803,7 +859,7 @@ case O(name, SB): \ how; \ goto shift8; \ } \ -case O(name, SW): \ +case O (name, SW): \ { \ int t; \ int hm = 0x8000; \ @@ -811,7 +867,7 @@ case O(name, SW): \ how; \ goto shift16; \ } \ -case O(name, SL): \ +case O (name, SL): \ { \ int t; \ int hm = 0x80000000; \ @@ -820,19 +876,98 @@ case O(name, SL): \ goto shift32; \ } +#define OSHIFTS(name, how1, how2) \ +case O (name, SB): \ +{ \ + int t; \ + int hm = 0x80; \ + rd = GET_B_REG (code->src.reg); \ + if ((GET_MEMORY_B (pc + 1) & 0x40) == 0) \ + { \ + how1; \ + } \ + else \ + { \ + how2; \ + } \ + goto shift8; \ +} \ +case O (name, SW): \ +{ \ + int t; \ + int hm = 0x8000; \ + rd = GET_W_REG (code->src.reg); \ + if ((GET_MEMORY_B (pc + 1) & 0x40) == 0) \ + { \ + how1; \ + } \ + else \ + { \ + how2; \ + } \ + goto shift16; \ +} \ +case O (name, SL): \ +{ \ + int t; \ + int hm = 0x80000000; \ + rd = GET_L_REG (code->src.reg); \ + if ((GET_MEMORY_B (pc + 1) & 0x40) == 0) \ + { \ + how1; \ + } \ + else \ + { \ + how2; \ + } \ + goto shift32; \ +} + #define OBITOP(name,f, s, op) \ -case O(name, SB): \ +case O (name, SB): \ { \ int m; \ int b; \ if (f) ea = fetch (&code->dst); \ - m=1<< fetch(&code->src); \ + m=1<< fetch (&code->src); \ op; \ - if(s) store (&code->dst,ea); goto next; \ + if (s) store (&code->dst,ea); goto next; \ +} + +int +sim_stop (sd) + SIM_DESC sd; +{ + cpu.state = SIM_STATE_STOPPED; + cpu.exception = SIGINT; + return 1; } +#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 + +#define SP_REGNUM R7_REGNUM /* Contains address of top of stack */ +#define FP_REGNUM R6_REGNUM /* Contains address of executing + * stack frame */ + +#define CCR_REGNUM 8 /* Contains processor status */ +#define PC_REGNUM 9 /* Contains program counter */ + +#define CYCLE_REGNUM 10 + +#define EXR_REGNUM 11 +#define INST_REGNUM 12 +#define TICK_REGNUM 13 + void -sim_resume (step, siggnal) +sim_resume (sd, step, siggnal) + SIM_DESC sd; { static int init1; int cycles = 0; @@ -846,7 +981,8 @@ sim_resume (step, siggnal) int ea; int bit; int pc; - int c, nz, v, n; + int c, nz, v, n, u, h, ui, intMaskBit; + int trace, intMask; int oldmask; init_pointers (); @@ -854,16 +990,24 @@ sim_resume (step, siggnal) if (step) { + cpu.state = SIM_STATE_STOPPED; cpu.exception = SIGTRAP; } else { + cpu.state = SIM_STATE_RUNNING; cpu.exception = 0; } pc = cpu.pc; + /* The PC should never be odd. */ + if (pc & 0x1) + abort (); + GETSR (); + GETEXR (); + oldmask = cpu.mask; if (!h8300hmode) cpu.mask = 0xffff; @@ -878,15 +1022,15 @@ sim_resume (step, siggnal) #define ALUOP(STORE, NAME, HOW) \ - case O(NAME,SB): HOW; if(STORE)goto alu8;else goto just_flags_alu8; \ - case O(NAME, SW): HOW; if(STORE)goto alu16;else goto just_flags_alu16; \ - case O(NAME,SL): HOW; if(STORE)goto alu32;else goto just_flags_alu32; + case O (NAME,SB): HOW; if (STORE)goto alu8;else goto just_flags_alu8; \ + case O (NAME, SW): HOW; if (STORE)goto alu16;else goto just_flags_alu16; \ + case O (NAME,SL): HOW; if (STORE)goto alu32;else goto just_flags_alu32; #define LOGOP(NAME, HOW) \ - case O(NAME,SB): HOW; goto log8;\ - case O(NAME, SW): HOW; goto log16;\ - case O(NAME,SL): HOW; goto log32; + case O (NAME,SB): HOW; goto log8;\ + case O (NAME, SW): HOW; goto log16;\ + case O (NAME,SL): HOW; goto log32; @@ -900,8 +1044,12 @@ sim_resume (step, siggnal) #endif - cycles += code->cycles; - insts++; + if (code->opcode) + { + cycles += code->cycles; + insts++; + } + switch (code->opcode) { case 0: @@ -928,8 +1076,8 @@ sim_resume (step, siggnal) res = rd + ea; goto alu8; -#define EA ea = fetch(&code->src); -#define RD_EA ea = fetch(&code->src); rd = fetch(&code->dst); +#define EA ea = fetch (&code->src); +#define RD_EA ea = fetch (&code->src); rd = fetch (&code->dst); ALUOP (1, O_SUB, RD_EA; ea = -ea; @@ -990,6 +1138,37 @@ sim_resume (step, siggnal) SET_L_REG (code->dst.reg, res); goto just_flags_log32; + case O (O_EEPMOV, SB): + case O (O_EEPMOV, SW): + if (h8300hmode||h8300smode) + { + register unsigned char *_src,*_dst; + unsigned int count = (code->opcode == O(O_EEPMOV, SW))?cpu.regs[R4_REGNUM]&0xffff: + cpu.regs[R4_REGNUM]&0xff; + + _src = cpu.regs[R5_REGNUM] < memory_size ? cpu.memory+cpu.regs[R5_REGNUM] : + cpu.eightbit + (cpu.regs[R5_REGNUM] & 0xff); + if ((_src+count)>=(cpu.memory+memory_size)) + { + if ((_src+count)>=(cpu.eightbit+0x100)) + goto illegal; + } + _dst = cpu.regs[R6_REGNUM] < memory_size ? cpu.memory+cpu.regs[R6_REGNUM] : + cpu.eightbit + (cpu.regs[R6_REGNUM] & 0xff); + if ((_dst+count)>=(cpu.memory+memory_size)) + { + if ((_dst+count)>=(cpu.eightbit+0x100)) + goto illegal; + } + memcpy(_dst,_src,count); + + cpu.regs[R5_REGNUM]+=count; + cpu.regs[R6_REGNUM]+=count; + cpu.regs[R4_REGNUM]&=(code->opcode == O(O_EEPMOV, SW))?(~0xffff):(~0xff); + cycles += 2*count; + goto next; + } + goto illegal; case O (O_ADDS, SL): SET_L_REG (code->dst.reg, @@ -1069,23 +1248,69 @@ sim_resume (step, siggnal) SET_L_REG (code->dst.reg, res); goto just_flags_inc32; - #define GET_CCR(x) BUILDSR();x = cpu.ccr +#define GET_EXR(x) BUILDEXR ();x = cpu.exr + + case O (O_LDC, SB): + case O (O_LDC, SW): + res = fetch (&code->src); + goto setc; + case O (O_STC, SB): + case O (O_STC, SW): + if (code->src.type == OP_CCR) + { + GET_CCR (res); + } + else if (code->src.type == OP_EXR && h8300smode) + { + GET_EXR (res); + } + else + goto illegal; + store (&code->dst, res); + goto next; case O (O_ANDC, SB): - GET_CCR (rd); + if (code->dst.type == OP_CCR) + { + GET_CCR (rd); + } + else if (code->dst.type == OP_EXR && h8300smode) + { + GET_EXR (rd); + } + else + goto illegal; ea = code->src.literal; res = rd & ea; goto setc; case O (O_ORC, SB): - GET_CCR (rd); + if (code->dst.type == OP_CCR) + { + GET_CCR (rd); + } + else if (code->dst.type == OP_EXR && h8300smode) + { + GET_EXR (rd); + } + else + goto illegal; ea = code->src.literal; res = rd | ea; goto setc; case O (O_XORC, SB): - GET_CCR (rd); + if (code->dst.type == OP_CCR) + { + GET_CCR (rd); + } + else if (code->dst.type == OP_EXR && h8300smode) + { + GET_EXR (rd); + } + else + goto illegal; ea = code->src.literal; res = rd ^ ea; goto setc; @@ -1168,41 +1393,37 @@ sim_resume (step, siggnal) goto next; case O (O_SYSCALL, SB): - printf ("%c", cpu.regs[2]); + { + char c = cpu.regs[2]; + sim_callback->write_stdout (sim_callback, &c, 1); + } goto next; - OSHIFTS (O_NOT, rd = ~rd; v = 0;); - OSHIFTS (O_SHLL, c = rd & hm; v = 0; - rd <<= 1); - OSHIFTS (O_SHLR, c = rd & 1; v = 0; - rd = (unsigned int) rd >> 1); - OSHIFTS (O_SHAL, c = rd & hm; - v = (rd & hm) != ((rd & (hm >> 1)) << 1); - rd <<= 1); - OSHIFTS (O_SHAR, t = rd & hm; - c = rd & 1; - v = 0; - rd >>= 1; - rd |= t; - ); - OSHIFTS (O_ROTL, c = rd & hm; - v = 0; - rd <<= 1; - rd |= C); - OSHIFTS (O_ROTR, c = rd & 1; - v = 0; - rd = (unsigned int) rd >> 1; - if (c) rd |= hm;); - OSHIFTS (O_ROTXL, t = rd & hm; - rd <<= 1; - rd |= C; - c = t; - v = 0; - ); - OSHIFTS (O_ROTXR, t = rd & 1; - rd = (unsigned int) rd >> 1; - if (C) rd |= hm; c = t; - v = 0;); + ONOT (O_NOT, rd = ~rd; v = 0;); + OSHIFTS (O_SHLL, + c = rd & hm; v = 0; rd <<= 1, + c = rd & (hm >> 1); v = 0; rd <<= 2); + OSHIFTS (O_SHLR, + c = rd & 1; v = 0; rd = (unsigned int) rd >> 1, + c = rd & 2; v = 0; rd = (unsigned int) rd >> 2); + OSHIFTS (O_SHAL, + c = rd & hm; v = (rd & hm) != ((rd & (hm >> 1)) << 1); rd <<= 1, + c = rd & (hm >> 1); v = (rd & (hm >> 1)) != ((rd & (hm >> 2)) << 2); rd <<= 2); + OSHIFTS (O_SHAR, + t = rd & hm; c = rd & 1; v = 0; rd >>= 1; rd |= t, + t = rd & hm; c = rd & 2; v = 0; rd >>= 2; rd |= t | t >> 1); + OSHIFTS (O_ROTL, + c = rd & hm; v = 0; rd <<= 1; rd |= C, + c = rd & hm; v = 0; rd <<= 1; rd |= C; c = rd & hm; rd <<= 1; rd |= C); + OSHIFTS (O_ROTR, + c = rd & 1; v = 0; rd = (unsigned int) rd >> 1; if (c) rd |= hm, + c = rd & 1; v = 0; rd = (unsigned int) rd >> 1; if (c) rd |= hm; c = rd & 1; rd = (unsigned int) rd >> 1; if (c) rd |= hm); + OSHIFTS (O_ROTXL, + t = rd & hm; rd <<= 1; rd |= C; c = t; v = 0, + t = rd & hm; rd <<= 1; rd |= C; c = t; v = 0; t = rd & hm; rd <<= 1; rd |= C; c = t); + OSHIFTS (O_ROTXR, + t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t; v = 0, + t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t; v = 0; t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t); case O (O_JMP, SB): { @@ -1236,7 +1457,7 @@ sim_resume (step, siggnal) pc = code->src.literal; goto call; - case O (O_RTS, SB): + case O (O_RTS, SN): { int tmp; @@ -1258,25 +1479,31 @@ sim_resume (step, siggnal) } case O (O_ILL, SB): + cpu.state = SIM_STATE_STOPPED; cpu.exception = SIGILL; goto end; - case O (O_SLEEP, SB): - /* The format of r0 is defined by devo/include/wait.h. - cpu.exception handling needs some cleanup: we need to make the - the handling of normal exits vs signals, etc. more sensible. */ - if (! WIFEXITED (cpu.regs[0]) && WIFSIGNALED (cpu.regs[0])) + case O (O_SLEEP, SN): + /* FIXME: Doesn't this break for breakpoints when r0 + contains just the right (er, wrong) value? */ + cpu.state = SIM_STATE_STOPPED; + /* The format of r0 is defined by target newlib. Expand + the macros here instead of looking for .../sys/wait.h. */ +#define SIM_WIFEXITED(v) (((v) & 0xff) == 0) +#define SIM_WIFSIGNALED(v) (((v) & 0x7f) > 0 && (((v) & 0x7f) < 0x7f)) + if (! SIM_WIFEXITED (cpu.regs[0]) && SIM_WIFSIGNALED (cpu.regs[0])) cpu.exception = SIGILL; else cpu.exception = SIGTRAP; goto end; - case O (O_BPT, SB): + case O (O_BPT, SN): + cpu.state = SIM_STATE_STOPPED; cpu.exception = SIGTRAP; goto end; OBITOP (O_BNOT, 1, 1, ea ^= m); OBITOP (O_BTST, 1, 0, nz = ea & m); OBITOP (O_BCLR, 1, 1, ea &= ~m); - OBITOP (O_BSET, 1, 1, ea |= m); + OBITOP (O_BSET, 1, 1, ea |= m); OBITOP (O_BLD, 1, 0, c = ea & m); OBITOP (O_BILD, 1, 0, c = !(ea & m)); OBITOP (O_BST, 1, 1, ea &= ~m; @@ -1290,8 +1517,9 @@ sim_resume (step, siggnal) OBITOP (O_BXOR, 1, 0, c = (ea & m) != C); OBITOP (O_BIXOR, 1, 0, c = !(ea & m) != C); - -#define MOP(bsize, signed) mop(code, bsize,signed); goto next; +#define MOP(bsize, signed) \ + mop (code, bsize, signed); \ + goto next; case O (O_MULS, SB): MOP (1, 1); @@ -1306,6 +1534,22 @@ sim_resume (step, siggnal) MOP (0, 0); break; + case O (O_TAS, SB): + if (!h8300smode || code->src.type != X (OP_REG, SL)) + goto illegal; + switch (code->src.reg) + { + case R0_REGNUM: + case R1_REGNUM: + case R4_REGNUM: + case R5_REGNUM: + break; + default: + goto illegal; + } + res = fetch (&code->src); + store (&code->src,res|0x80); + goto just_flags_log8; case O (O_DIVU, SB): { @@ -1313,8 +1557,8 @@ sim_resume (step, siggnal) ea = GET_B_REG (code->src.reg); if (ea) { - tmp = rd % ea; - rd = rd / ea; + tmp = (unsigned) rd % ea; + rd = (unsigned) rd / ea; } SET_W_REG (code->dst.reg, (rd & 0xff) | (tmp << 8)); n = ea & 0x80; @@ -1330,8 +1574,8 @@ sim_resume (step, siggnal) nz = ea & 0xffff; if (ea) { - tmp = rd % ea; - rd = rd / ea; + tmp = (unsigned) rd % ea; + rd = (unsigned) rd / ea; } SET_L_REG (code->dst.reg, (rd & 0xffff) | (tmp << 16)); goto next; @@ -1391,10 +1635,46 @@ sim_resume (step, siggnal) res = rd + ea; goto log32; - case O (O_NOP, SB): + case O (O_NOP, SN): + goto next; + + case O (O_STM, SL): + { + int nregs, firstreg, i; + + nregs = GET_MEMORY_B (pc + 1); + nregs >>= 4; + nregs &= 0xf; + firstreg = GET_MEMORY_B (pc + 3); + firstreg &= 0xf; + for (i = firstreg; i <= firstreg + nregs; i++) + { + cpu.regs[7] -= 4; + SET_MEMORY_L (cpu.regs[7], cpu.regs[i]); + } + } + goto next; + + case O (O_LDM, SL): + { + int nregs, firstreg, i; + + nregs = GET_MEMORY_B (pc + 1); + nregs >>= 4; + nregs &= 0xf; + firstreg = GET_MEMORY_B (pc + 3); + firstreg &= 0xf; + for (i = firstreg; i >= firstreg - nregs; i--) + { + cpu.regs[i] = GET_MEMORY_L (cpu.regs[7]); + cpu.regs[7] += 4; + } + } goto next; default: + illegal: + cpu.state = SIM_STATE_STOPPED; cpu.exception = SIGILL; goto end; @@ -1402,8 +1682,19 @@ sim_resume (step, siggnal) abort (); setc: - cpu.ccr = res; - GETSR (); + if (code->dst.type == OP_CCR) + { + cpu.ccr = res; + GETSR (); + } + else if (code->dst.type == OP_EXR && h8300smode) + { + cpu.exr = res; + GETEXR (); + } + else + goto illegal; + goto next; condtrue: @@ -1491,8 +1782,22 @@ sim_resume (step, siggnal) just_flags_alu8: n = res & 0x80; nz = res & 0xff; - v = ((ea & 0x80) == (rd & 0x80)) && ((ea & 0x80) != (res & 0x80)); c = (res & 0x100); + switch (code->opcode / 4) + { + case O_ADD: + v = ((rd & 0x80) == (ea & 0x80) + && (rd & 0x80) != (res & 0x80)); + break; + case O_SUB: + case O_CMP: + v = ((rd & 0x80) != (-ea & 0x80) + && (rd & 0x80) != (res & 0x80)); + break; + case O_NEG: + v = (rd == 0x80); + break; + } goto next; alu16: @@ -1500,8 +1805,22 @@ sim_resume (step, siggnal) just_flags_alu16: n = res & 0x8000; nz = res & 0xffff; - v = ((ea & 0x8000) == (rd & 0x8000)) && ((ea & 0x8000) != (res & 0x8000)); c = (res & 0x10000); + switch (code->opcode / 4) + { + case O_ADD: + v = ((rd & 0x8000) == (ea & 0x8000) + && (rd & 0x8000) != (res & 0x8000)); + break; + case O_SUB: + case O_CMP: + v = ((rd & 0x8000) != (-ea & 0x8000) + && (rd & 0x8000) != (res & 0x8000)); + break; + case O_NEG: + v = (rd == 0x8000); + break; + } goto next; alu32: @@ -1509,18 +1828,21 @@ sim_resume (step, siggnal) just_flags_alu32: n = res & 0x80000000; nz = res & 0xffffffff; - v = ((ea & 0x80000000) == (rd & 0x80000000)) - && ((ea & 0x80000000) != (res & 0x80000000)); switch (code->opcode / 4) { case O_ADD: + v = ((rd & 0x80000000) == (ea & 0x80000000) + && (rd & 0x80000000) != (res & 0x80000000)); c = ((unsigned) res < (unsigned) rd) || ((unsigned) res < (unsigned) ea); break; case O_SUB: case O_CMP: + v = ((rd & 0x80000000) != (-ea & 0x80000000) + && (rd & 0x80000000) != (res & 0x80000000)); c = (unsigned) rd < (unsigned) -ea; break; case O_NEG: + v = (rd == 0x80000000); c = res != 0; break; } @@ -1531,47 +1853,43 @@ sim_resume (step, siggnal) end: ; - /* if (cpu.regs[8] ) abort(); */ - -#if defined (WIN32) - /* Poll after every 100th insn, */ - if (poll_count++ > 100) - { - poll_count = 0; - if (win32pollquit()) - { - control_c(); - } - } +#if 0 + if (cpu.regs[8]) + abort (); #endif -#if defined(__GO32__) - /* Poll after every 100th insn, */ - if (poll_count++ > 100) + + if (--poll_count < 0) { - poll_count = 0; - if (kbhit ()) - { - int c = getkey (); - control_c (); - } + poll_count = POLL_QUIT_INTERVAL; + if ((*sim_callback->poll_quit) != NULL + && (*sim_callback->poll_quit) (sim_callback)) + sim_stop (sd); } -#endif } - while (!cpu.exception); + while (cpu.state == SIM_STATE_RUNNING); cpu.ticks += get_now () - tick_start; cpu.cycles += cycles; cpu.insts += insts; - + cpu.pc = pc; BUILDSR (); + BUILDEXR (); cpu.mask = oldmask; signal (SIGINT, prev); } +int +sim_trace (sd) + SIM_DESC sd; +{ + /* FIXME: Unfinished. */ + abort (); +} int -sim_write (addr, buffer, size) +sim_write (sd, addr, buffer, size) + SIM_DESC sd; SIM_ADDR addr; unsigned char *buffer; int size; @@ -1579,55 +1897,45 @@ sim_write (addr, buffer, size) int i; init_pointers (); - if (addr < 0 || addr + size > memory_size) + if (addr < 0) return 0; for (i = 0; i < size; i++) { - cpu.memory[addr + i] = buffer[i]; - cpu.cache_idx[addr + i] = 0; + if (addr < memory_size) + { + cpu.memory[addr + i] = buffer[i]; + cpu.cache_idx[addr + i] = 0; + } + else + cpu.eightbit[(addr + i) & 0xff] = buffer[i]; } return size; } int -sim_read (addr, buffer, size) +sim_read (sd, addr, buffer, size) + SIM_DESC sd; SIM_ADDR addr; unsigned char *buffer; int size; { init_pointers (); - if (addr < 0 || addr + size > memory_size) + if (addr < 0) return 0; - memcpy (buffer, cpu.memory + addr, size); + if (addr < memory_size) + memcpy (buffer, cpu.memory + addr, size); + else + memcpy (buffer, cpu.eightbit + (addr & 0xff), size); return size; } -#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 - -#define SP_REGNUM R7_REGNUM /* Contains address of top of stack */ -#define FP_REGNUM R6_REGNUM /* Contains address of executing - * stack frame */ - -#define CCR_REGNUM 8 /* Contains processor status */ -#define PC_REGNUM 9 /* Contains program counter */ - -#define CYCLE_REGNUM 10 -#define INST_REGNUM 11 -#define TICK_REGNUM 12 - - -void -sim_store_register (rn, value) +int +sim_store_register (sd, rn, value, length) + SIM_DESC sd; int rn; unsigned char *value; + int length; { int longval; int shortval; @@ -1657,6 +1965,9 @@ sim_store_register (rn, value) case CCR_REGNUM: cpu.ccr = intval; break; + case EXR_REGNUM: + cpu.exr = intval; + break; case CYCLE_REGNUM: cpu.cycles = longval; break; @@ -1669,26 +1980,34 @@ sim_store_register (rn, value) cpu.ticks = longval; break; } + return -1; } -void -sim_fetch_register (rn, buf) +int +sim_fetch_register (sd, rn, buf, length) + SIM_DESC sd; int rn; unsigned char *buf; + int length; { int v; int longreg = 0; init_pointers (); + if (!h8300smode && rn >=EXR_REGNUM) + rn++; switch (rn) { default: abort (); - case 8: + case CCR_REGNUM: v = cpu.ccr; break; - case 9: + case EXR_REGNUM: + v = cpu.exr; + break; + case PC_REGNUM: v = cpu.pc; break; case R0_REGNUM: @@ -1701,15 +2020,15 @@ sim_fetch_register (rn, buf) case R7_REGNUM: v = cpu.regs[rn]; break; - case 10: + case CYCLE_REGNUM: v = cpu.cycles; longreg = 1; break; - case 11: + case TICK_REGNUM: v = cpu.ticks; longreg = 1; break; - case 12: + case INST_REGNUM: v = cpu.insts; longreg = 1; break; @@ -1726,18 +2045,41 @@ sim_fetch_register (rn, buf) buf[0] = v >> 8; buf[1] = v; } + return -1; } void -sim_stop_reason (reason, sigrc) +sim_stop_reason (sd, reason, sigrc) + SIM_DESC sd; enum sim_stop *reason; int *sigrc; { +#if 0 /* FIXME: This should work but we can't use it. + grep for SLEEP above. */ + switch (cpu.state) + { + case SIM_STATE_EXITED : *reason = sim_exited; break; + case SIM_STATE_SIGNALLED : *reason = sim_signalled; break; + case SIM_STATE_STOPPED : *reason = sim_stopped; break; + default : abort (); + } +#else *reason = sim_stopped; +#endif *sigrc = cpu.exception; } -sim_csize (n) +/* FIXME: Rename to sim_set_mem_size. */ + +void +sim_size (n) + int n; +{ + /* Memory size is fixed. */ +} + +void +sim_set_simcache_size (n) { if (cpu.cache) free (cpu.cache); @@ -1750,109 +2092,204 @@ sim_csize (n) void -sim_info (verbose) +sim_info (sd, verbose) + SIM_DESC sd; int verbose; { double timetaken = (double) cpu.ticks / (double) now_persec (); double virttime = cpu.cycles / 10.0e6; - printf_filtered ("\n\n#instructions executed %10d\n", cpu.insts); - printf_filtered ("#cycles (v approximate) %10d\n", cpu.cycles); - printf_filtered ("#real time taken %10.4f\n", timetaken); - printf_filtered ("#virtual time taked %10.4f\n", virttime); + (*sim_callback->printf_filtered) (sim_callback, + "\n\n#instructions 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 != 0.0) - printf_filtered ("#simulation ratio %10.4f\n", virttime / timetaken); - printf_filtered ("#compiles %10d\n", cpu.compiles); - printf_filtered ("#cache size %10d\n", cpu.csize); + (*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); #ifdef ADEBUG - if (verbose) + /* This to be conditional on `what' (aka `verbose'), + however it was never passed as non-zero. */ + if (1) { int i; for (i = 0; i < O_LAST; i++) { if (cpu.stats[i]) - printf_filtered ("%d: %d\n", i, cpu.stats[i]); + (*sim_callback->printf_filtered) (sim_callback, + "%d: %d\n", i, cpu.stats[i]); } } #endif } -/* Indicate whether the cpu is an h8/300 or h8/300h. - FLAG is non-zero for the h8/300h. */ +/* Indicate whether the cpu is an H8/300 or H8/300H. + FLAG is non-zero for the H8/300H. */ void -set_h8300h (flag) - int flag; +set_h8300h (h_flag, s_flag) + int h_flag, s_flag; { - h8300hmode = flag; + /* FIXME: Much of the code in sim_load can be moved to sim_open. + This function being replaced by a sim_open:ARGV configuration + option. */ + h8300hmode = h_flag; + h8300smode = s_flag; } -void -sim_kill () +SIM_DESC +sim_open (kind, ptr, abfd, argv) + SIM_OPEN_KIND kind; + struct host_callback_struct *ptr; + struct _bfd *abfd; + char **argv; { - /* nothing to do */ -} + /* FIXME: Much of the code in sim_load can be moved here. */ -void -sim_open (args) - char *args; -{ - /* nothing to do */ + sim_kind = kind; + myname = argv[0]; + sim_callback = ptr; + /* Fudge our descriptor. */ + return (SIM_DESC) 1; } void -sim_close (quitting) +sim_close (sd, quitting) + SIM_DESC sd; int quitting; { - /* nothing to do */ + /* Nothing to do. */ } /* Called by gdb to load a program into memory. */ -int -sim_load (prog, from_tty) +SIM_RC +sim_load (sd, prog, abfd, from_tty) + SIM_DESC sd; char *prog; + bfd *abfd; int from_tty; { - bfd *abfd; + bfd *prog_bfd; + + /* FIXME: The code below that sets a specific variant of the H8/300 + being simulated should be moved to sim_open(). */ - /* See if the file is for the h8/300 or h8/300h. */ + /* See if the file is for the H8/300 or H8/300H. */ /* ??? This may not be the most efficient way. The z8k simulator does this via a different mechanism (INIT_EXTRA_SYMTAB_INFO). */ - if ((abfd = bfd_openr (prog, "coff-h8300")) != 0) + if (abfd != NULL) + prog_bfd = abfd; + else + prog_bfd = bfd_openr (prog, "coff-h8300"); + if (prog_bfd != NULL) { - if (bfd_check_format (abfd, bfd_object)) - set_h8300h (abfd->arch_info->mach == bfd_mach_h8300h); - bfd_close (abfd); + /* Set the cpu type. We ignore failure from bfd_check_format + and bfd_openr as sim_load_file checks too. */ + if (bfd_check_format (prog_bfd, bfd_object)) + { + unsigned long mach = bfd_get_mach (prog_bfd); + set_h8300h (mach == bfd_mach_h8300h || mach == bfd_mach_h8300s, + mach == bfd_mach_h8300s); + } } - /* Return non-zero so gdb will handle it. */ - return 1; + /* If we're using gdb attached to the simulator, then we have to + reallocate memory for the simulator. + + When gdb first starts, it calls fetch_registers (among other + functions), which in turn calls init_pointers, which allocates + simulator memory. + + The problem is when we do that, we don't know whether we're + debugging an H8/300 or H8/300H program. + + This is the first point at which we can make that determination, + so we just reallocate memory now; this will also allow us to handle + switching between H8/300 and H8/300H programs without exiting + gdb. */ + + if (h8300smode) + memory_size = H8300S_MSIZE; + else if (h8300hmode) + memory_size = H8300H_MSIZE; + else + memory_size = H8300_MSIZE; + + if (cpu.memory) + free (cpu.memory); + if (cpu.cache_idx) + free (cpu.cache_idx); + if (cpu.eightbit) + free (cpu.eightbit); + + cpu.memory = (unsigned char *) calloc (sizeof (char), memory_size); + cpu.cache_idx = (unsigned short *) calloc (sizeof (short), memory_size); + cpu.eightbit = (unsigned char *) calloc (sizeof (char), 256); + + /* `msize' must be a power of two. */ + if ((memory_size & (memory_size - 1)) != 0) + abort (); + cpu.mask = memory_size - 1; + + if (sim_load_file (sd, myname, sim_callback, prog, prog_bfd, + sim_kind == SIM_OPEN_DEBUG, + 0, sim_write) + == NULL) + { + /* Close the bfd if we opened it. */ + if (abfd == NULL && prog_bfd != NULL) + bfd_close (prog_bfd); + return SIM_RC_FAIL; + } + + /* Close the bfd if we opened it. */ + if (abfd == NULL && prog_bfd != NULL) + bfd_close (prog_bfd); + return SIM_RC_OK; } -void -sim_create_inferior (start_address, argv, env) - SIM_ADDR start_address; +SIM_RC +sim_create_inferior (sd, abfd, argv, env) + SIM_DESC sd; + struct _bfd *abfd; char **argv; char **env; { - cpu.pc = start_address; + if (abfd != NULL) + cpu.pc = bfd_get_start_address (abfd); + else + cpu.pc = 0; + return SIM_RC_OK; } void -sim_do_command (cmd) +sim_do_command (sd, cmd) + SIM_DESC sd; char *cmd; { - printf_filtered ("This simulator does not accept any commands.\n"); + (*sim_callback->printf_filtered) (sim_callback, + "This simulator does not accept any commands.\n"); } - - void sim_set_callbacks (ptr) -struct host_callback_struct *ptr; + struct host_callback_struct *ptr; { - + sim_callback = ptr; } -