OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/tags/gdb/gdb-6.8/gdb-6.8.openrisc-2.1/sim/m32c
    from Rev 24 to Rev 33
    Reverse comparison

Rev 24 → Rev 33

/trace.c
0,0 → 1,313
/* trace.c --- tracing output for the M32C simulator.
 
Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
 
This file is part of the GNU simulators.
 
This program 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 3 of the License, or
(at your option) any later version.
 
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
 
 
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
 
#include "bfd.h"
#include "dis-asm.h"
#include "m32c-desc.h"
 
#include "cpu.h"
#include "mem.h"
#include "load.h"
 
static int
sim_dis_read (bfd_vma memaddr, bfd_byte * ptr, unsigned int length,
struct disassemble_info *info)
{
mem_get_blk (memaddr, ptr, length);
return 0;
}
 
/* Filter out (in place) symbols that are useless for disassembly.
COUNT is the number of elements in SYMBOLS.
Return the number of useful symbols. */
 
static long
remove_useless_symbols (asymbol ** symbols, long count)
{
register asymbol **in_ptr = symbols, **out_ptr = symbols;
 
while (--count >= 0)
{
asymbol *sym = *in_ptr++;
 
if (strstr (sym->name, "gcc2_compiled"))
continue;
if (sym->name == NULL || sym->name[0] == '\0')
continue;
if (sym->flags & (BSF_DEBUGGING))
continue;
if (bfd_is_und_section (sym->section)
|| bfd_is_com_section (sym->section))
continue;
 
*out_ptr++ = sym;
}
return out_ptr - symbols;
}
 
static int
compare_symbols (const PTR ap, const PTR bp)
{
const asymbol *a = *(const asymbol **) ap;
const asymbol *b = *(const asymbol **) bp;
 
if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
return 1;
else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
return -1;
return 0;
}
 
static char opbuf[1000];
 
static int
op_printf (char *buf, char *fmt, ...)
{
int ret;
va_list ap;
 
va_start (ap, fmt);
ret = vsprintf (opbuf + strlen (opbuf), fmt, ap);
va_end (ap);
return ret;
}
 
static bfd *current_bfd;
 
void
sim_disasm_init (bfd *prog)
{
current_bfd = prog;
}
 
typedef struct Files
{
struct Files *next;
char *filename;
int nlines;
char **lines;
char *data;
} Files;
Files *files = 0;
 
static char *
load_file_and_line (const char *filename, int lineno)
{
Files *f;
for (f = files; f; f = f->next)
if (strcmp (f->filename, filename) == 0)
break;
if (!f)
{
int i;
struct stat s;
const char *found_filename, *slash;
 
found_filename = filename;
while (1)
{
if (stat (found_filename, &s) == 0)
break;
slash = strchr (found_filename, '/');
if (!slash)
return "";
found_filename = slash + 1;
}
 
f = (Files *) malloc (sizeof (Files));
f->next = files;
files = f;
f->filename = strdup (filename);
f->data = (char *) malloc (s.st_size + 2);
FILE *file = fopen (found_filename, "rb");
fread (f->data, 1, s.st_size, file);
f->data[s.st_size] = 0;
fclose (file);
 
f->nlines = 1;
for (i = 0; i < s.st_size; i++)
if (f->data[i] == '\n')
f->nlines++;
f->lines = (char **) malloc (f->nlines * sizeof (char *));
f->lines[0] = f->data;
f->nlines = 1;
for (i = 0; i < s.st_size; i++)
if (f->data[i] == '\n')
{
f->lines[f->nlines] = f->data + i + 1;
while (*f->lines[f->nlines] == ' '
|| *f->lines[f->nlines] == '\t')
f->lines[f->nlines]++;
f->nlines++;
f->data[i] = 0;
}
}
if (lineno < 1 || lineno > f->nlines)
return "";
return f->lines[lineno - 1];
}
 
void
sim_disasm_one ()
{
static int initted = 0;
static asymbol **symtab = 0;
static int symcount = 0;
static int last_sym = -1;
static struct disassemble_info info;
int storage, sym, bestaddr;
int min, max, i;
static asection *code_section = 0;
static bfd_vma code_base = 0;
asection *s;
int save_trace = trace;
 
static const char *prev_filename = "";
static int prev_lineno = 0;
const char *filename;
const char *functionname;
unsigned int lineno;
 
int mypc = get_reg (pc);
 
if (current_bfd == 0)
return;
 
trace = 0;
 
if (!initted)
{
initted = 1;
memset (&info, 0, sizeof (info));
INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
info.read_memory_func = sim_dis_read;
info.arch = bfd_get_arch (current_bfd);
info.mach = bfd_get_mach (current_bfd);
if (info.mach == 0)
{
info.arch = bfd_arch_m32c;
info.mach = default_machine;
}
disassemble_init_for_target (&info);
 
storage = bfd_get_symtab_upper_bound (current_bfd);
if (storage > 0)
{
symtab = (asymbol **) malloc (storage);
symcount = bfd_canonicalize_symtab (current_bfd, symtab);
symcount = remove_useless_symbols (symtab, symcount);
qsort (symtab, symcount, sizeof (asymbol *), compare_symbols);
}
for (s = current_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_CODE || code_section == 0)
{
code_section = s;
code_base = bfd_section_lma (current_bfd, s);
break;
}
}
}
 
filename = functionname = 0;
lineno = 0;
if (bfd_find_nearest_line
(current_bfd, code_section, symtab, mypc - code_base, &filename,
&functionname, &lineno))
{
if (filename && functionname && lineno)
{
if (lineno != prev_lineno || strcmp (prev_filename, filename))
{
char *the_line = load_file_and_line (filename, lineno);
const char *slash = strrchr (filename, '/');
if (!slash)
slash = filename;
else
slash++;
printf
("========================================"
"=====================================\n");
printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n",
slash, lineno, the_line);
}
prev_lineno = lineno;
prev_filename = filename;
}
}
 
{
min = -1;
max = symcount;
while (min < max - 1)
{
bfd_vma sa;
sym = (min + max) / 2;
sa = bfd_asymbol_value (symtab[sym]);
/*printf("checking %4d %08x %s\n",
sym, sa, bfd_asymbol_name (symtab[sym])); */
if (sa > mypc)
max = sym;
else if (sa < mypc)
min = sym;
else
{
min = sym;
break;
}
}
if (min != -1 && min != last_sym)
{
bestaddr = bfd_asymbol_value (symtab[min]);
printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min]));
if (bestaddr != mypc)
printf ("+%d", mypc - bestaddr);
printf (":\t\t\t\033[0m\n");
last_sym = min;
#if 0
if (trace == 1)
if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0
|| strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0)
trace = 0;
#endif
}
}
 
opbuf[0] = 0;
printf ("\033[33m%06x: ", mypc);
max = print_insn_m32c (mypc, &info);
for (i = 0; i < max; i++)
printf ("%02x", mem_get_qi (mypc + i));
for (; i < 6; i++)
printf (" ");
printf ("%-16s ", opbuf);
 
printf ("\033[0m\n");
trace = save_trace;
}
trace.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: sample.ld =================================================================== --- sample.ld (nonexistent) +++ sample.ld (revision 33) @@ -0,0 +1,41 @@ +/* sample2.ld --- linker script for sample2.x + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + +/* See the 'sample2.x' target in Makefile.in. */ + +ENTRY(_start) + +MEMORY { + RAM1 (w) : ORIGIN = 0xc800, LENGTH = 0x0200 + RAM2 (w) : ORIGIN = 0xca56, LENGTH = 0x1000 + ROM (w) : ORIGIN = 0x30000, LENGTH = 0x1000 +} + +SECTIONS { + .data : { + *(.data*) + } > RAM1 + .text : { + *(.text*) + } > RAM2 + .fardata : { + *(.fardata*) + } > ROM +} Index: int.h =================================================================== --- int.h (nonexistent) +++ int.h (revision 33) @@ -0,0 +1,23 @@ +/* int.h --- interface to M32C interrupt handling. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +extern void trigger_fixed_interrupt (int addr); +extern void trigger_based_interrupt (int vector);
int.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: misc.h =================================================================== --- misc.h (nonexistent) +++ misc.h (revision 33) @@ -0,0 +1,25 @@ +/* misc.h --- interface to miscellaneous utility functions for M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +int bcd2int (int bcd, int w); +int int2bcd (int val, int w); + +char *comma (unsigned int u);
misc.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: sample.S =================================================================== --- sample.S (nonexistent) +++ sample.S (revision 33) @@ -0,0 +1,29 @@ +;;; sample.S --- simple test program for M32C simulator +;;; +;;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +;;; Contributed by Red Hat, Inc. +;;; +;;; This file is part of the GNU simulators. +;;; +;;; This program 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 3 of the License, or +;;; (at your option) any later version. +;;; +;;; This program 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 this program. If not, see . + +;;; See the 'sample.x' and sample.mot targets in Makefile.in. + + .text + + .global _start +_start: + mov.w #0x1234,r1 + mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3 + brk
sample.S Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: syscalls.h =================================================================== --- syscalls.h (nonexistent) +++ syscalls.h (revision 33) @@ -0,0 +1,24 @@ +/* syscalls.h --- interface to syscalls for the M32C sim. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +struct host_callback_struct; +extern void set_callbacks (struct host_callback_struct *); +extern void m32c_syscall (int id);
syscalls.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: trace.h =================================================================== --- trace.h (nonexistent) +++ trace.h (revision 33) @@ -0,0 +1,23 @@ +/* trace.h --- interface to tracing output for the M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +void sim_disasm_init (bfd *prog); +extern void sim_disasm_one (void);
trace.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: sample2.c =================================================================== --- sample2.c (nonexistent) +++ sample2.c (revision 33) @@ -0,0 +1,28 @@ +/* sample2.c --- main source for sample2.x test program for M32C simulator + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + +/* See the 'sample2.x' target in Makefile.in. */ +void exit (int); + +start () +{ + foo (1, 2, 3, 4); + exit (5); +}
sample2.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: m32c.opc =================================================================== --- m32c.opc (nonexistent) +++ m32c.opc (revision 33) @@ -0,0 +1,2102 @@ +/* m32c.opc --- semantics for m32c opcodes. -*- mode: c -*- + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include + +#include "cpu.h" +#include "mem.h" +#include "misc.h" +#include "int.h" + +#define AU __attribute__((unused)) + +#define tprintf if (trace) printf + +static unsigned char +getbyte () +{ + int tsave = trace; + unsigned char b; + + if (trace == 1) + trace = 0; + b = mem_get_pc (); + regs.r_pc ++; + trace = tsave; + return b; +} + +#define M32C_ONLY() /* FIXME: add something here */ + +#define GETBYTE() (op[opi++] = getbyte()) + +#define UNSUPPORTED() unsupported("unsupported", orig_pc) +#define NOTYET() unsupported("unimplemented", orig_pc) + +static void +unsupported (char *tag, int orig_pc) +{ + int i; + printf("%s opcode at %08x\n", tag, orig_pc); + regs.r_pc = orig_pc; + for (i=0; i<2; i++) + { + int b = mem_get_pc(); + printf(" %s", bits(b>>4, 4)); + printf(" %s", bits(b, 4)); + regs.r_pc ++; + } + printf("\n"); + regs.r_pc = orig_pc; + for (i=0; i<6; i++) + { + printf(" %02x", mem_get_pc ()); + regs.r_pc ++; + } + printf("\n"); + exit(1); +} + +static int +IMM(int bytes) +{ + int rv = 0; + switch (bytes) + { + case 1: + rv = mem_get_qi (get_reg(pc)); + break; + case 2: + rv = mem_get_hi (get_reg(pc)); + break; + case 3: + rv = mem_get_psi (get_reg(pc)); + break; + case 4: + rv = mem_get_si (get_reg(pc)); + break; + } + regs.r_pc += bytes; + return rv; +} + +#define IMM4() (immm >= 8 ? 7 - immm : immm + 1) + +#define NO_PREFIX() PREFIX(0,0,0) + +/* Indicate which sorts of prefixes are allowed for the current + opcode. */ +void +prefix (src_allowed, dest_allowed, index_bytewidth) +{ + /* At the moment, we don't do anything with this information. We + just wanted to get the information entered in some + machine-readable form while we were going through all the + opcodes. */ +} + +#define MATH_OP(dc,s,c,op) \ +{ \ + int ma, mb; \ + ma = get_src(dc); \ + mb = s & b2mask[dc.bytes]; \ + ll = (long long)ma op (long long)mb op c; \ + tprintf("0x%x " #op " 0x%x " #op " 0x%x = 0x%llx\n", ma, mb, c, ll); \ + ma = sign_ext (ma, dc.bytes * 8); \ + mb = sign_ext (s, dc.bytes * 8); \ + v = ma op mb op c; \ + tprintf("%d " #op " %d " #op " %d = %d\n", ma, mb, c, v); \ + set_oszc (v, dc.bytes, ll > ((1 op 1) ? b2mask[dc.bytes] : 0)); \ + put_dest (dc, v); \ +} + +#define LOGIC_OP(dc,s,op) \ +{ \ + int ma, mb; \ + ma = get_src(dc); \ + mb = s & b2mask[dc.bytes]; \ + v = ma op mb; \ + tprintf("0x%x " #op " 0x%x = 0x%x\n", ma, mb, v); \ + set_sz (v, dc.bytes); \ + put_dest (dc, v); \ +} + +#define BIT_OP(dc,bit,expr) \ + b = get_bit2 (dc, bitindex == -1 ? bit : bitindex); \ + v = expr; \ + tprintf ("b=%d, bit=%d, carry=%d, %s = %d\n", \ + b, bitindex == -1 ? bit : bitindex, carry, #expr, v); \ + put_bit2 (dc, bitindex == -1 ? bit : bitindex, v); + +#define BIT_OPC(dc,bit,expr) \ + b = get_bit2 (dc, bitindex == -1 ? bit : bitindex); \ + v = expr; \ + tprintf ("b=%d, bit=%d, carry=%d, %s = %d\n", \ + b, bitindex == -1 ? bit : bitindex, carry, #expr, v); \ + set_c (v); + +#define carry (FLAG_C ? 1 : 0) + +static void +cmp (int d, int s, int bytes) +{ + int a, b, f=0; + a = d - s; + b = sign_ext (d, bytes*8) - sign_ext (s, bytes*8); + tprintf ("cmp: %x - %x = %08x, %x - %x = %d\n", + d, s, a, + sign_ext(d,bytes*8), sign_ext(s,bytes*8), b); + + if (b == 0) + f |= FLAGBIT_Z; + if (b & b2signbit[bytes]) + f |= FLAGBIT_S; + if ((d & b2mask[bytes]) >= (s & b2mask[bytes])) + f |= FLAGBIT_C; + if (b < b2minsigned[bytes] || b > b2maxsigned[bytes]) + f |= FLAGBIT_O; + + set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f); +} + +static void +dadd_op (int ddd, int dd, int sss, int ss, int imm, int add, int cy, int w) +{ + srcdest sc, dc; + int a, b=0, res; + + prefix (0, 0, 0); + + if (!imm) + { + sc = decode_src23 (sss, ss, w+1); + b = get_src (sc); + } + dc = decode_dest23 (ddd, dd, w+1); + a = get_src (dc); + if (imm) + b = IMM(w+1); + + a = bcd2int(a, w); + b = bcd2int(b, w); + + tprintf("decimal: %d %s %d", a, add?"+":"-", b); + if (cy) + tprintf(" c=%d", carry); + + if (add) + { + res = a + b; + if (cy) + res += carry; + cy = res > (w ? 9999 : 99); + } + else + { + res = a - b; + if (cy) + res -= (1-carry); + cy = res >= 0; + if (res < 0) + res += w ? 10000 : 100; + } + + res = int2bcd (res, w); + tprintf(" = %x\n", res); + + set_szc (res, w+1, cy); + + put_dest (dc, res); +} +#define DADDV(A,C) dadd_op(ddd, dd, sss, ss, 0, A, C, w) +#define DADDI(A,C) dadd_op(ddd, dd, 0, 0, 1, A, C, w) + +static void +div_op (int sss, int ss, int u, int x, int bytes) +{ + srcdest sc; + int s, v, a, b; + + if (sss == -1) + s = IMM(bytes); + else + { + sc = decode_dest23 (sss, ss, bytes); + s = get_src (sc); + } + + v = get_reg (bytes > 1 ? r2r0 : r0); + + if (!u) + { + /* FIXME? do we sign extend a0/a1 to .L? Docs say zero extend. */ + s = sign_ext (s, bytes*8); + v = sign_ext (v, bytes*8); + } + + if (s == 0) + { + set_flags (FLAGBIT_O, FLAGBIT_O); + return; + } + + if (u) + { + a = (unsigned int)v / (unsigned int)s; + b = (unsigned int)v % (unsigned int)s; + } + else + { + a = v / s; + b = v % s; + } + if (x) + { + if ((s > 0 && b < 0) + || (s < 0 && b > 0)) + { + a --; + b += s; + } + } + tprintf ("%d / %d = %d rem %d\n", v, s, a, b); + if ((!u && (a > b2maxsigned[bytes] + || a < b2minsigned[bytes])) + || (u && (a > b2mask[bytes]))) + set_flags (FLAGBIT_O, FLAGBIT_O); + else + set_flags (FLAGBIT_O, 0); + + switch (bytes) + { + case 1: + put_reg (r0l, a); + put_reg (r0h, b); + break; + case 2: + put_reg (r0, a); + put_reg (r2, b); + break; + case 4: + put_reg (r2r0, a); + break; + } +} + +static void +index_op (int sss, int ss, int do_s, int do_d, int scale, int w) +{ + srcdest sc = decode_src23 (sss, ss, w+1); + int v = get_src (sc) * scale; + tprintf("%d = %d * %d, %d %d\n", v, get_src(sc), scale, do_s, do_d); + decode_index (do_s * v, do_d * v); +} +#define INDEXOP(scale,do_s,do_d) \ + index_op (sss, ss, do_s, do_d, scale, w); goto next_opcode + +static void +rot_op (srcdest sd, int rotc, int count) +{ + int mask = (sd.bytes == 2) ? 0xffff : 0xff; + int msb = (sd.bytes == 2) ? 0x8000 : 0x80; + int v = get_src (sd); + int c = carry, ct; + + tprintf("%s %x by %d\n", rotc ? "rotc" : "rot", v, count); + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + while (count > 0) + { + ct = (v & msb) ? 1 : 0; + v <<= 1; + v |= rotc ? c : ct; + v &= mask; + c = ct; + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count --; + } + while (count < 0) + { + ct = v & 1; + v >>= 1; + v |= (rotc ? c : ct) * msb; + c = ct; + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count ++; + } + put_dest (sd, v); + set_szc (v, sd.bytes, c); +} + +static void +shift_op (srcdest sd, int arith, int count, int setc) +{ + int mask = (sd.bytes == 2) ? 0xffff : 0xff; + int msb = (sd.bytes == 2) ? 0x8000 : 0x80; + int v = get_src (sd); + int c = 0; + int o = 0; + + if (sd.bytes == 4) + { + mask = 0xffffffffU; + msb = 0x80000000U; + } + + tprintf("%s %x by %d\n", arith ? "sha" : "shl", v, count); + tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o); + while (count > 0) + { + c = (v & msb) ? 1 : 0; + v <<= 1; + v &= mask; + if (c != ((v & msb) ? 1 : 0)) + o = 1; + tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o); + count --; + } + while (count < 0) + { + c = v & 1; + if (arith) + v = (v & msb) | (v >> 1); + else + v = (v >> 1) & (msb - 1); + tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o); + count ++; + } + put_dest (sd, v); + set_sz (v, sd.bytes); + if (setc) + set_c (c); + set_flags (FLAGBIT_O, o ? FLAGBIT_O : 0); +} + +int +decode_m32c() +{ + unsigned char op[40]; + int opi; + int orig_pc; + int v, a, b; + long long ll; + srcdest sc, dc; + int imm; + int bitindex = -1; + int t0, t1=0, t2, t3=0; + int ta0, ta1, dif; + + step_result = M32C_MAKE_STEPPED (); + + decode_indirect (0, 0); + decode_index (0, 0); + +next_opcode: + opi = 0; + orig_pc = get_reg (pc); + + tprintf("trace: decode pc = %06x\n", orig_pc); + + /** VARY sss 000 001 010 011 100 */ + /** VARY ddd 000 001 010 011 100 */ + + /** 0000 1001 indirect dest */ + + decode_indirect (0, 1); + goto next_opcode; + + /** 0100 0001 indirect src */ + + decode_indirect (1, 0); + goto next_opcode; + + /** 0100 1001 indirect src and dest */ + + decode_indirect (1, 1); + goto next_opcode; + + /** 1010 ddd w dd01 1111 ABS.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + v = sign_ext (get_src (dc), w?16:8); + a = v<0 ? -v : v; + tprintf("abs(%d) = %d\n", v, a); + set_osz(a, w+1); + put_dest (dc, a); + + /** 0000 0001 1000 ddd w dd10 1110 ADC.size #IMM,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM (w+1); + MATH_OP (dc, imm, carry, +); + + /** 0000 0001 1sss ddd w dd ss 0100 ADC.size src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, w+1); + dc = decode_dest23 (ddd, dd, w+1); + b = get_src (sc); + MATH_OP (dc, b, carry, +); + + /** 1011 ddd w dd01 1110 ADCF.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + MATH_OP (dc, 0, carry, +); + + /** 1000 ddd w dd10 1110 ADD.size:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, w+1); + imm = IMM(w+1); + MATH_OP (dc, imm, 0, +); + + /** 1000 ddd0 dd11 0001 ADD.L:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, 4); + imm = IMM(4); + MATH_OP (dc, imm, 0, +); + + /** 111L ddd w dd11 immm ADD.size:Q #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, L ? 4 : (w+1)); + imm = sign_ext (immm, 4); + MATH_OP (dc, imm, 0, +); + + /** 00dd 011w ADD.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2(dd, w+1); + imm = IMM (w+1); + MATH_OP (dc, imm, 0, +); + + /** 10i0 110d ADD.L:S #IMM,A0/A1 */ + + prefix (0, 0, 0); + dc = reg_sd (d ? a1 : a0); + imm = i ? 2 : 1; + MATH_OP (dc, imm, 0, +); + + /** 1sss ddd w dd ss 1000 ADD.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, w+1); + dc = decode_dest23(ddd, dd, w+1); + b = get_src (sc); + MATH_OP (dc, b, 0, +); + + /** 1sss ddd1 dd ss 0010 ADD.L:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, 4); + dc = decode_dest23(ddd, dd, 4); + b = get_src (sc); + MATH_OP (dc, b, 0, +); + + /** 1011 0110 0001 0011 ADD.L:G #IMM16,SP */ + + prefix (0, 0, 0); + dc = reg_sd (sp); + b = sign_ext (IMM(2), 16); + MATH_OP (dc, b, 0, +); + + /** 01ii 001i ADD.L:Q #IMM3,SP */ + + prefix (0, 0, 0); + dc = reg_sd (sp); + b = ii * 2 + i + 1; + MATH_OP (dc, b, 0, +); + + /** 1011 0110 0000 0011 ADD.L:S #IMM8,SP */ + + prefix (0, 0, 0); + dc = reg_sd (sp); + b = sign_ext (IMM(1), 8); + MATH_OP (dc, b, 0, +); + + /** 1000 ddd0 dd01 0001 ADDX #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + MATH_OP (dc, imm, 0, +); + + /** 1sss ddd0 dd ss 0010 ADDX src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, 1); + dc = decode_dest23(ddd, dd, 4); + b = sign_ext (get_src (sc), 8); + MATH_OP (dc, b, 0, +); + + /** 1111 ddd w dd01 immm ADJNZ.size #IMM,dest,label */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + v = get_src (dc); + imm = sign_ext(immm, 4); + tprintf("%d + %d = %d\n", v, imm, v+imm); + v += imm; + put_dest (dc, v); + a = sign_ext (IMM(1), 8); + if ((v & (w ? 0xffff : 0xff)) != 0) + { + tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a); + put_reg (pc, orig_pc + 2 + a); + tprintf("%x\n", get_reg (pc)); + } + + /** 1000 ddd w dd11 1111 AND.size:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, w+1); + imm = IMM(w+1); + LOGIC_OP (dc, imm, &); + + /** 01dd 110w AND.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2(dd, w+1); + imm = IMM (w+1); + LOGIC_OP (dc, imm, &); + + /** 1sss ddd w dd ss 1101 AND.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, w+1); + dc = decode_dest23(ddd, dd, w+1); + b = get_src (sc); + LOGIC_OP (dc, b, &); + + /** 0000 0001 1101 sss0 ss00 1bit BAND src */ + + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, b & carry); + + /** 1101 ddd0 dd11 0bit BCLR dest */ + + dc = decode_dest23 (ddd, dd, 1); + BIT_OP (dc, bit, 0); + + /** 1100 ddd w dd10 1110 BITINDEX.size src */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + bitindex = get_src (dc); + tprintf ("bitindex set to %d\n", bitindex); + goto next_opcode; + + /** 1101 ddd0 dd01 0bit BMcnd dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 1); + if (condition_true (IMM (1))) + put_bit2 (dc, bit, 1); + else + put_bit2 (dc, bit, 0); + + /** 1101 1001 0c10 1cnd BMcnd C */ + + prefix (0, 0, 0); + if (condition_true (c * 8 + cnd)) + set_c (1); + else + set_c (0); + + /** 0000 0001 1101 sss0 ss01 1bit BNAND src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, !b & carry); + + /** 0000 0001 1101 sss0 ss11 0bit BNOR src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, !b | carry); + + /** 1101 ddd0 dd01 1bit BNOT dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 1); + BIT_OP (dc, bit, !b); + + /** 0000 0001 1101 sss0 ss00 0bit BNTST src */ + + prefix (0, 0, 0); + sc = decode_dest23 (sss, ss, 1); + b = get_bit2 (sc, bit); + set_zc (!b, !b); + + /** 0000 0001 1101 sss0 ss11 1bit BNXOR src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, !b ^ carry); + + /** 0000 0001 1101 sss0 ss10 0bit BOR src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, b | carry); + + /** 0000 0000 BRK */ + + /* We report the break to our caller with the PC still pointing at the + breakpoint instruction. */ + put_reg (pc, orig_pc); + if (verbose) + printf("[break]\n"); + return M32C_MAKE_HIT_BREAK (); + + /** 0000 1000 BRK */ + + if (verbose) + printf("[break2]\n"); + return M32C_MAKE_HIT_BREAK (); + + /** 1101 ddd0 dd11 1bit BSET dest */ + + dc = decode_dest23 (ddd, dd, 1); + BIT_OP (dc, bit, 1); + + /** 1101 sss0 ss00 0bit BTST:G src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + b = get_bit2 (sc, bit); + set_zc (!b, b); + + /** 00bb 101b BTST:S src */ + + sc = decode_src23 (3, 3, 1); /* bit,base:19 */ + b = get_bit2 (sc, bb*2 + b); + set_zc (!b, b); + + /** 1101 ddd0 dd10 0bit BTSTC dest */ + + prefix (0, 0, 0); + sc = decode_dest23 (ddd, dd, 1); + b = get_bit2 (sc, bit); + set_zc (!b, b); + put_bit2 (sc, bit, 0); + + /** 1101 ddd0 dd10 1bit BTSTS dest */ + + prefix (0, 0, 0); + sc = decode_dest23 (ddd, dd, 1); + b = get_bit2 (sc, bit); + set_zc (!b, b); + put_bit2 (sc, bit, 1); + + /** 0000 0001 1101 sss0 ss10 1bit BXOR src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + BIT_OPC (sc, bit, b ^ carry); + + /** 0000 0001 1000 ddd w dd11 1110 CLIP.size #IMM1,#IMM2,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = sign_ext (IMM(w+1), w*8+8); + b = sign_ext (IMM(w+1), w*8+8); + v = sign_ext (get_src (dc), w*8+8); + tprintf("clip %d <= %d <= %d : ", a, v, b); + if (a > v) + v = a; + if (v > b) + v = b; + tprintf("%d\n", v); + put_dest (dc, v); + + /** 1001 ddd w dd10 1110 CMP.size:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + v = get_src (dc); + imm = IMM(w+1); + cmp (v, imm, w+1); + + /** 1010 ddd0 dd11 0001 CMP.L:G #IMM32,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + v = get_src (dc); + imm = IMM(4); + cmp (v, imm, 4); + + /** 1110 ddd w dd01 immm CMP.size:Q #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + v = get_src (dc); + immm = sign_ext (immm, 4); + cmp (v, immm, w+1); + + /** 01dd 011w CMP.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2 (dd, w+1); + v = get_src (dc); + imm = sign_ext (IMM(w+1),w*8+8); + cmp (v, imm, w+1); + + /** 1sss ddd w dd ss 0110 CMP.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23 (sss, ss, w+1); + dc = decode_dest23 (ddd, dd, w+1); + a = get_src (dc); + b = get_src (sc); + cmp (a, b, w+1); + + /** 1sss ddd1 dd ss 0001 CMP.L:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23 (sss, ss, 4); + dc = decode_dest23 (ddd, dd, 4); + a = get_src (dc); + b = get_src (sc); + cmp (a, b, 4); + + /** 01dd 000w CMP.size:S src,R0/R0L */ + + prefix (0, 1, 0); + dc = decode_dest2 (dd, w+1); + a = get_reg (w ? r0 : r0l); + b = get_src (dc); + cmp (a, b, w+1); + + /** 1010 ddd0 dd01 0001 CMPX #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + v = get_src (dc); + imm = sign_ext (IMM(1), 8); + cmp (v, imm, 4); + + /** 0000 0001 1000 ddd w dd00 1110 DADC.size #IMM,dest */ + + DADDI(1,1); + + /** 0000 0001 1sss ddd w dd ss 1000 DADC.size src,dest */ + + DADDV(1,1); + + /** 0000 0001 1000 ddd w dd01 1110 DADD.size #IMM,dest */ + + DADDI(1,0); + + /** 0000 0001 1sss ddd w dd ss 0000 DADD.size src,dest */ + + DADDV(1,0); + + /** 1011 ddd w dd00 1110 DEC.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = get_src (dc); + v = a-1; + tprintf ("%x -- = %x\n", a, v); + set_sz (v, w+1); + put_dest (dc, v); + + /** 1011 0000 010w 0011 DIV.size #IMM */ + + prefix (0, 0, 0); + div_op (-1, 0, 0, 0, w+1); + + /** 1000 sss w ss01 1110 DIV.size src */ + + prefix (0, 1, 0); + div_op (sss, ss, 0, 0, w+1); + + /** 0000 0001 1010 sss1 ss01 1111 DIV.L src */ + + M32C_ONLY(); + prefix (0, 0, 0); + div_op (sss, ss, 0, 0, 4); + + /** 1011 0000 000w 0011 DIVU.size #IMM */ + + prefix (0, 0, 0); + div_op (-1, 0, 1, 0, w+1); + + /** 1000 sss w ss00 1110 DIVU.size src */ + + prefix (0, 1, 0); + div_op (sss, ss, 1, 0, w+1); + + /** 0000 0001 1010 sss1 ss00 1111 DIVU.L src */ + + M32C_ONLY(); + prefix (0, 0, 0); + div_op (sss, ss, 1, 0, 4); + + /** 1011 0010 010w 0011 DIVX.size #IMM */ + + prefix (0, 0, 0); + div_op (-1, 0, 0, 1, w+1); + + /** 1001 sss w ss01 1110 DIVX.size src */ + + prefix (0, 1, 0); + div_op (sss, ss, 0, 1, w+1); + + /** 0000 0001 1010 sss1 ss10 1111 DIVX.L src */ + + M32C_ONLY(); + prefix (0, 0, 0); + div_op (sss, ss, 0, 1, 4); + + /** 0000 0001 1001 ddd w dd00 1110 DSBB.size #IMM,dest */ + + DADDI(0,1); + + /** 0000 0001 1sss ddd w dd ss 1010 DSBB.size src,dest */ + + DADDV(0,1); + + /** 0000 0001 1001 ddd w dd01 1110 DSUB.size #IMM,dest */ + + DADDI(0,0); + + /** 0000 0001 1sss ddd w dd ss 0010 DSUB.size src,dest */ + + DADDV(0,0); + + /** 1110 1100 ENTER #IMM */ + + imm = IMM(1); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (fb)); + put_reg (fb, get_reg (sp)); + put_reg (sp, get_reg (sp) - imm); + + /** 1111 1100 EXITD */ + + put_reg (sp, get_reg (fb)); + put_reg (fb, mem_get_si (get_reg (sp))); + put_reg (sp, get_reg (sp) + 4); + put_reg (pc, mem_get_si (get_reg (sp))); + put_reg (sp, get_reg (sp) + 4); + + /** 1100 ddd w dd01 1110 EXTS.size dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + v = sign_ext (get_src (dc), (w+1)*8); + dc = widen_sd (dc); + put_dest (dc, v); + set_sz (v, (w+1)*2); + + /** 0000 0001 1sss ddd0 dd ss 0111 EXTS.B src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + dc = decode_dest23 (ddd, dd, 2); + v = sign_ext (get_src (sc), 8); + put_dest (dc, v); + set_sz (v, 16); + + /** 0000 0001 1sss ddd0 dd ss 1011 EXTZ src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + dc = decode_dest23 (ddd, dd, 2); + v = get_src (sc); + put_dest (dc, v); + set_sz (v, 16); + + /** 1101 0011 1110 1dst FCLR dest */ + + set_flags (1 << dst, 0); + + /** 1001 1111 FREIT */ + + NOTYET(); + + /** 1101 0001 1110 1dst FSET dest */ + + set_flags (1 << dst, 1 << dst); + + /** 1010 ddd w dd00 1110 INC.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = get_src (dc); + v = a+1; + tprintf ("%x ++ = %x\n", a, v); + set_sz (v, w+1); + put_dest (dc, v); + + /** 1000 sss0 ss0w 0011 INDEXB.size src */ + INDEXOP(1, 1, 1); + /** 1010 sss0 ss0w 0011 INDEXBD.size src */ + INDEXOP(1, 0, 1); + /** 1100 sss0 ss0w 0011 INDEXBS.size src */ + INDEXOP(1, 1, 0); + /** 1001 sss0 ss1w 0011 INDEXL.size src */ + INDEXOP(4, 1, 1); + /** 1011 sss0 ss1w 0011 INDEXLD.size src */ + INDEXOP(4, 0, 1); + /** 1001 sss0 ss0w 0011 INDEXLS.size src */ + INDEXOP(4, 1, 0); + /** 1000 sss0 ss1w 0011 INDEXW.size src */ + INDEXOP(2, 1, 1); + /** 1010 sss0 ss1w 0011 INDEXWD.size src */ + INDEXOP(2, 0, 1); + /** 1100 sss0 ss1w 0011 INDEXWS.size src */ + INDEXOP(2, 1, 0); + + /** 1011 1110 vector00 INT #IMM */ + + prefix (0, 0, 0); + trigger_based_interrupt (vector); + + /** 1011 1111 INTO */ + + prefix (0, 0, 0); + if (FLAG_O) + trigger_fixed_interrupt (0xffffe0); + + /** 1ccc 101c Jcnd label */ + + prefix (0, 0, 0); + v = sign_ext (IMM(1), 8); + if (condition_true (ccc*2+c)) + put_reg (pc, orig_pc + 1 + v); + + /** 01dd 101d JMP.S label */ + + prefix (0, 0, 0); + put_reg (pc, orig_pc + (dd*2+d) + 2); + + /** 1011 1011 JMP.B label */ + + prefix (0, 0, 0); + imm = sign_ext (IMM(1), 8); + if (imm == -1) + { + if (verbose) + printf("[jmp-to-self detected as exit]\n"); + return M32C_MAKE_HIT_BREAK (); + } + put_reg (pc, orig_pc + 1 + imm); + + /** 1100 1110 JMP.W label */ + + prefix (0, 0, 0); + imm = sign_ext (IMM(2), 16); + put_reg (pc, orig_pc + 1 + imm); + + /** 1100 1100 JMP.A label */ + + prefix (0, 0, 0); + imm = IMM(3); + put_reg (pc, imm); + + /** 1100 sss1 ss00 1111 JMPI.W src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 2); + a = get_src (sc); + a = sign_ext (a, 16); + put_reg (pc, orig_pc + a); + + /** 1000 sss0 ss00 0001 JMPI.A src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 3); + a = get_src (sc); + put_reg (pc, a); + + /** 1101 1100 JMPS #IMM8 */ + + prefix (0, 0, 0); + imm = IMM(1); + a = 0xff0000 + mem_get_hi (0xfffe00 - imm * 2); + put_reg (pc, a); + + /** 1100 1111 JSR.W label */ + + prefix (0, 0, 0); + imm = sign_ext (IMM(2), 16); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (pc)); + put_reg (pc, orig_pc + imm + 1); + + /** 1100 1101 JSR.A label */ + + prefix (0, 0, 0); + imm = IMM(3); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (pc)); + put_reg (pc, imm); + + /** 1100 sss1 ss01 1111 JSRI.W src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 2); + a = get_src (sc); + a = sign_ext (a, 16); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (pc)); + put_reg (pc, orig_pc + a); + + /** 1001 sss0 ss00 0001 JSRI.A src */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 3); + a = get_src (sc); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (pc)); + put_reg (pc, a); + + /** 1101 1101 JSRS #IMM8 */ + + prefix (0, 0, 0); + imm = IMM(1); + a = 0xff0000 + mem_get_hi (0xfffe00 - imm * 2); + put_reg (sp, get_reg (sp) - 4); + mem_put_si (get_reg (sp), get_reg (pc)); + put_reg (pc, a); + + /** 1101 0101 1010 1dst LDC #IMM16,dest */ + + imm = IMM(2); + dc = decode_cr_b (dst, CR_B_DCT0); + put_dest (dc, imm); + + /** 1101 0101 0010 1dst LDC #IMM24,dest */ + + imm = IMM(3); + dc = decode_cr_b (dst, CR_B_INTB); + put_dest (dc, imm); + + /** 1101 0101 0110 1dst LDC #IMM24,dest */ + + imm = IMM(3); + dc = decode_cr_b (dst, CR_B_DMA0); + put_dest (dc, imm); + + /** 0000 0001 1101 sss1 ss00 1dst LDC src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 2); + dc = decode_cr_b (dst, CR_B_DCT0); + a = get_src (sc); + put_dest (dc, a); + + /** 1101 sss1 ss00 0dst LDC src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 3); + dc = decode_cr_b (dst, CR_B_INTB); + a = get_src (sc); + put_dest (dc, a); + + /** 0000 0001 1101 sss1 ss00 0dst LDC src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 3); + dc = decode_cr_b (dst, CR_B_DMA0); + a = get_src (sc); + put_dest (dc, a); + + /** 1011 0110 1100 0011 LDCTX */ + + NOTYET(); + + /** 1101 0101 1110 1imm LDIPL #IMM */ + + set_flags (0x7000, imm*0x1000); + + /** 0000 0001 1000 ddd w dd11 1111 MAX.size #IMM,dest */ + + prefix (0, 0, 0); + w++; + dc = decode_dest23 (ddd, dd, w); + imm = sign_ext (IMM(w), w*8); + a = sign_ext (get_src (dc), w*8); + tprintf ("max %d %d\n", imm, a); + if (imm > a) + put_dest (dc, imm); + + /** 0000 0001 1sss ddd w dd ss 1101 MAX.size src,dest */ + + prefix (0, 0, 0); + w++; + sc = decode_src23 (sss, ss, w); + dc = decode_dest23 (ddd, dd, w); + b = sign_ext (get_src (sc), w*8); + a = sign_ext (get_src (dc), w*8); + tprintf ("max %d %d\n", b, a); + if (b > a) + put_dest (dc, b); + + /** 0000 0001 1000 ddd w dd10 1111 MIN.size #IMM,dest */ + + prefix (0, 0, 0); + w++; + dc = decode_dest23 (ddd, dd, w); + imm = sign_ext (IMM(w), w*8); + a = sign_ext (get_src (dc), w*8); + tprintf ("min %d %d\n", imm, a); + if (imm < a) + put_dest (dc, imm); + + /** 0000 0001 1sss ddd w dd ss 1100 MIN.size src,dest */ + + prefix (0, 0, 0); + w++; + sc = decode_src23 (sss, ss, w); + dc = decode_dest23 (ddd, dd, w); + b = sign_ext (get_src (sc), w*8); + a = sign_ext (get_src (dc), w*8); + tprintf ("min %d %d\n", b, a); + if (b < a) + put_dest (dc, b); + + /** 1001 ddd w dd10 1111 MOV.size:G #IMM,dest */ + + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM(w+1); + v = imm; + tprintf("%x = %x\n", v, v); + set_sz(v, w+1); + put_dest (dc, v); + + /** 1011 ddd0 dd11 0001 MOV.L:G #IMM,dest */ + + dc = decode_dest23 (ddd, dd, 4); + imm = IMM(4); + v = imm; + tprintf("%x = %x\n", v, v); + set_sz(v, 4); + put_dest (dc, v); + + /** 1111 ddd w dd10 immm MOV.size:Q #IMM4,dest */ + + dc = decode_dest23 (ddd, dd, w+1); + imm = sign_ext (immm, 4); + v = imm; + tprintf("%x = %d\n", v, v); + set_sz(v, w+1); + put_dest (dc, v); + + /** 00dd 010w MOV.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2 (dd, w+1); + imm = IMM(w+1); + put_dest (dc, imm); + set_sz (imm, w+1); + + /** 10w1 110d MOV.size:S #IMM,a0/a1 */ + + imm = IMM(w ? 3 : 2); + put_reg (d ? a1 : a0, imm); + set_sz (imm & addr_mask, w+1); + + /** 00dd 001w MOV.size:Z #0,dest */ + + prefix (0, 1, 0); + dc = decode_dest2 (dd, w+1); + put_dest (dc, 0); + set_sz (0, w+1); + + /** 1sss ddd w dd ss 1011 MOV.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23 (sss, ss, w+1); + dc = decode_dest23 (ddd, dd, w+1); + v = get_src (sc); + put_dest (dc, v); + set_sz (v, w+1); + + /** 1sss ddd1 dd ss 0011 MOV.L:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23 (sss, ss, 4); + dc = decode_dest23 (ddd, dd, 4); + v = get_src (sc); + put_dest (dc, v); + set_sz (v, 4); + + /** VARY SS 01 10 11 */ + /** 00SS 100w MOV.size:S src,R0L/R0 */ + + prefix (0, 1, 0); + sc = decode_dest2 (SS, w+1); + v = get_src (sc); + put_reg (w ? r0 : r0l, v); + set_sz (v, w+1); + + /** 01ss 111w MOV.size:S src,R1L/R1 */ + + prefix (0, 1, 0); + sc = decode_dest2 (ss, w+1); + v = get_src (sc); + put_reg (w ? r1 : r1l, v); + set_sz (v, w+1); + + /** VARY DD 01 10 11 */ + /** 00DD 000w MOV.size:S R0L/R0,dest */ + + prefix (0, 1, 0); + dc = decode_dest2 (DD, w+1); + v = get_reg (w ? r0 : r0l); + put_dest (dc, v); + set_sz (v, w+1); + + /** 01ss 100d MOV.L:S src,A0/A1 */ + + prefix (0, 1, 0); + sc = decode_dest2 (ss, 4); + v = get_src (sc); + put_reg (d ? a1 : a0, v); + set_sz (v, 4); + + /** 1011 ddd w dd00 1111 MOV.size:G dsp:8[SP], dest */ + + prefix (0, 0, 0); + imm = IMM(1); + dc = decode_dest23 (ddd, dd, w+1); + a = get_reg (sp) + sign_ext (imm, 8); + a &= addr_mask; + if (w) + v = mem_get_hi (a); + else + v = mem_get_qi (a); + put_dest (dc, v); + set_sz (v, w+1); + + /** 1010 sss w ss00 1111 MOV.size:G src,dsp:8[SP] */ + + prefix (0, 0, 0); + sc = decode_dest23 (sss, ss, w+1); + imm = IMM(1); + a = get_reg (sp) + sign_ext (imm, 8); + a &= addr_mask; + v = get_src (sc); + if (w) + mem_put_hi (a, v); + else + mem_put_qi (a, v); + set_sz (v, w+1); + + /** 1101 sss1 ss01 1dst MOVA src,dest */ + + static reg_id map[8] = { r2r0, r3r1, a0, a1 }; + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 1); + if (!sc.mem || !map[dst]) + UNSUPPORTED(); + put_reg (map[dst], sc.u.addr); + + /** 0000 0001 1011 ddd0 dd hl 1110 MOVdir R0L,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 1); + a = get_src (dc); + b = get_reg (r0l); + switch (hl) + { + case 0: a = (a & 0xf0) | (b & 0x0f); break; + case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break; + case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break; + case 3: a = (a & 0x0f) | (b & 0xf0); break; + } + put_dest (dc, a); + + /** 0000 0001 1010 sss0 ss hl 1110 MOVdir src,R0L */ + + prefix (0, 0, 0); + sc = decode_dest23 (sss, ss, 1); + a = get_reg (r0l); + b = get_src (dc); + switch (hl) + { + case 0: a = (a & 0xf0) | (b & 0x0f); break; + case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break; + case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break; + case 3: a = (a & 0x0f) | (b & 0xf0); break; + } + put_reg (r0l, a); + + /** 1011 ddd0 dd01 0001 MOVX #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + put_dest (dc, imm); + set_sz (imm, 1); + + /** 1000 ddd w dd01 1111 MUL.size #IMM,dest */ + + prefix (0, 1, 0); + w ++; + dc = decode_dest23 (ddd, dd, w); + v = sign_ext (get_src (dc), w*8); + imm = sign_ext (IMM(w), w*8); + tprintf("%d * %d = %d\n", v, imm, v*imm); + v *= imm; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 1sss ddd w dd ss 1100 MUL.size src,dest */ + + prefix (1, 1, 0); + w ++; + sc = decode_src23 (sss, ss, w); + dc = decode_dest23 (ddd, dd, w); + a = sign_ext (get_src (sc), w*8); + b = sign_ext (get_src (dc), w*8); + tprintf("%d * %d = %d\n", a, b, a*b); + v = a * b; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0000 0001 1000 sss1 ss01 1111 MUL.L src,R2R0 */ + + M32C_ONLY(); + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 4); + a = sign_ext (get_src (sc), 32); + b = sign_ext (get_reg (r2r0), 32); + ll = (long long)a * (long long)b; + tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll); + if (ll < b2minsigned[4] || ll > b2maxsigned[4]) + set_flags (FLAGBIT_O, FLAGBIT_O); + else + set_flags (FLAGBIT_O, 0); + put_reg (r2r0, (int)ll); + + /** 1100 sss1 ss11 1110 MULEX src */ + + prefix (0, 1, 0); + sc = decode_dest23 (sss, ss, 2); + a = sign_ext (get_src (sc), 16); + b = sign_ext (get_reg (r2r0), 32); + ll = (long long)a * (long long)b; + tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll); + put_reg (r2r0, (int)ll); + put_reg (r1, (int)(ll >> 32)); + + /** 1000 ddd w dd00 1111 MULU.size #IMM,dest */ + + prefix (0, 1, 0); + w ++; + dc = decode_dest23 (ddd, dd, w); + v = get_src (dc); + imm = IMM(w); + tprintf("%d * %d = %d\n", v, imm, v*imm); + v *= imm; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 1sss ddd w dd ss 0100 MULU.size src,dest */ + + prefix (1, 1, 0); + w ++; + sc = decode_src23 (sss, ss, w); + dc = decode_dest23 (ddd, dd, w); + a = get_src (sc); + b = get_src (dc); + tprintf("%d * %d = %d\n", a, b, a*b); + v = a * b; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0000 0001 1000 sss1 ss00 1111 MULU.L src,R2R0 */ + + M32C_ONLY(); + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, 4); + a = get_src (sc); + b = get_reg (r2r0); + ll = (long long)a * (long long)b; + tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll); + if (ll < b2minsigned[4] || ll > b2maxsigned[4]) + set_flags (FLAGBIT_O, FLAGBIT_O); + else + set_flags (FLAGBIT_O, 0); + put_reg (r2r0, (int)ll); + + /** 1010 ddd w dd10 1111 NEG.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = sign_ext (get_src (dc), (w+1)*8); + v = -a; + tprintf("%d * -1 = %d\n", a, v); + set_oszc(v, w+1, v==0); + put_dest (dc, v); + + /** 1101 1110 NOP */ + + tprintf("nop\n"); + + /** 1010 ddd w dd01 1110 NOT.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = get_src (dc); + v = ~a; + tprintf("~ %x = %x\n", a, v); + set_sz(v, w+1); + put_dest (dc, v); + + /** 1000 ddd w dd10 1111 OR.size:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, w+1); + imm = IMM(w+1); + LOGIC_OP (dc, imm, |); + + /** 01dd 010w OR.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2(dd, w+1); + imm = IMM (w+1); + LOGIC_OP (dc, imm, |); + + /** 1sss ddd w dd ss 0101 OR.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, w+1); + dc = decode_dest23(ddd, dd, w+1); + b = get_src (sc); + LOGIC_OP (dc, b, |); + + /** 1011 ddd w dd10 1111 POP.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + if (w) + a = mem_get_hi (get_reg (sp)); + else + a = mem_get_qi (get_reg (sp)); + put_reg (sp, get_reg (sp) + 2); + tprintf("pop%s: %x\n", w ? "hi" : "qi", a); + put_dest (dc, a); + + /** 1101 0011 1010 1dst POPC dest */ + + prefix (0, 0, 0); + dc = decode_cr_b (dst, CR_B_DCT0); + a = mem_get_hi (get_reg (sp)); + put_reg (sp, get_reg (sp) + 2); + tprintf("pophi: %x\n", a); + put_dest (dc, a); + + /** 1101 0011 0010 1dst POPC dest */ + + prefix (0, 0, 0); + dc = decode_cr_b (dst, CR_B_INTB); + a = mem_get_si (get_reg (sp)); + put_reg (sp, get_reg (sp) + 4); + tprintf("popsi: %x\n", a); + put_dest (dc, a); + + /** 1000 1110 POPM dest */ + + static int map[] = { r0, r1, r2, r3, a0, a1, sb, fb }; + prefix (0, 0, 0); + imm = IMM(1); + tprintf("popm: %x\n", imm); + for (a=0; a<4; a++) + if (imm & (1<> 32)); + + /** 1011 ddd w dd10 1110 ROLC.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + rot_op (dc, 1, 1); + + /** 1010 ddd w dd10 1110 RORC.size dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + rot_op (dc, 1, -1); + + /** 1110 ddd w dd10 immm ROT.size #IMM, dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + rot_op (dc, IMM4(), -1); + + /** 1010 ddd w dd11 1111 ROT.size R1H,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = sign_ext (get_reg (r1h), 8); + rot_op (dc, a, -1); + + /** 1101 1111 RTS */ + + put_reg (pc, mem_get_si (get_reg (sp))); + put_reg (sp, get_reg (sp) + 4); + + /** 0000 0001 1001 ddd w dd10 1110 SBB.size #IMM, dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM (w+1); + MATH_OP (dc, imm, !carry, -); + + /** 0000 0001 1sss ddd w dd ss 0110 SBB.size src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, w+1); + dc = decode_dest23 (ddd, dd, w+1); + MATH_OP (dc, get_src (sc), !carry, -); + + /** 1101 ddd1 dd11 cond SCcond dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 2); + if (condition_true (cond)) + put_dest (dc, 1); + else + put_dest (dc, 0); + + /** 1011 1000 110w 0011 SCMPU.size */ + + ta0 = get_reg (a0); + ta1 = get_reg (a1); + + for (;;) + { + t0 = mem_get_qi (ta0); + t2 = mem_get_qi (ta1); + if (w) + { + t1 = mem_get_qi (ta0 + 1); + t3 = mem_get_qi (ta1 + 1); + } + dif = t0 - t2; + if (dif == 0 && t0 != 0 && w) + dif = t1 - t3; + set_oszc (dif, 1, dif > 0); + + ta0 += w ? 2 : 1; + ta1 += w ? 2 : 1; + + if (t0 == 0 || t0 != t2) + break; + if (w && (t1 == 0 || t1 != t3)) + break; + } + + /** 1111 ddd w dd00 immm SHA.size #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + shift_op (dc, 1, IMM4(), 1); + + /** 1010 ddd0 dd10 0001 SHA.L #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + shift_op (dc, 1, imm, 1); + + /** 1011 ddd w dd11 1110 SHA.size R1H,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 1, a, 1); + + /** 1100 ddd0 dd01 0001 SHA.L R1H,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 1, a, 1); + + /** 1100 ddd0 dd10 0001 SHANC.L #IMM,dest */ + + M32C_ONLY(); + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + shift_op (dc, 1, imm, 0); + + /** 1110 ddd w dd00 immm SHL.size #IMM, dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + shift_op (dc, 0, IMM4(), 1); + + /** 1001 ddd0 dd10 0001 SHL.L #IMM, dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + shift_op (dc, 0, imm, 1); + + /** 1010 ddd w dd11 1110 SHL.size R1H,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 0, a, 1); + + /** 1100 ddd0 dd00 0001 SHL.L R1H,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 0, a, 1); + + /** 1000 ddd0 dd10 0001 SHLNC.L #IMM,dest */ + + M32C_ONLY(); + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + shift_op (dc, 0, imm, 0); + + /** 1011 0010 100w 0011 SIN.size */ + + v = get_reg (a0); + a = get_reg (a1); + b = get_reg (r3); + if (b) for (;b;) + { + if (w) + mem_put_hi(a, mem_get_hi (v)); + else + mem_put_qi(a, mem_get_qi (v)); + a += w ? 2 : 1; + b --; + } + put_reg (a0, v); + put_reg (a1, a); + put_reg (r3, b); + + /** 1011 0110 100w 0011 SMOVB.size */ + + v = get_reg (a0); + a = get_reg (a1); + b = get_reg (r3); + if (b) for (;b;) + { + if (w) + mem_put_hi(a, mem_get_hi (v)); + else + mem_put_qi(a, mem_get_qi (v)); + v -= w ? 2 : 1; + a -= w ? 2 : 1; + b --; + } + put_reg (a0, v); + put_reg (a1, a); + put_reg (r3, b); + + /** 1011 0000 100w 0011 SMOVF.size */ + + v = get_reg (a0); + a = get_reg (a1); + b = get_reg (r3); + if (b) for (;b;) + { + if (w) + mem_put_hi(a, mem_get_hi (v)); + else + mem_put_qi(a, mem_get_qi (v)); + v += w ? 2 : 1; + a += w ? 2 : 1; + b --; + } + put_reg (a0, v); + put_reg (a1, a); + put_reg (r3, b); + + /** 1011 1000 100w 0011 SMOVU.size */ + + v = get_reg (a0); + a = get_reg (a1); + do + { + if (w) + mem_put_hi(a, (t0 = mem_get_hi (v))); + else + mem_put_qi(a, (t0 = mem_get_qi (v))); + v += w ? 2 : 1; + a += w ? 2 : 1; + if (t0 == 0 + || (w && ((t0 & 0xff) == 0 || (t0 & 0xff00) == 0))) + break; + } while (1); + put_reg (a0, v); + put_reg (a1, a); + + /** 1011 0100 100w 0011 SOUT.size */ + + v = get_reg (a0); + a = get_reg (a1); + b = get_reg (r3); + for (;b;) + { + if (w) + mem_put_hi(a, mem_get_hi (v)); + else + mem_put_qi(a, mem_get_qi (v)); + v += w ? 2 : 1; + b --; + } + put_reg (a0, v); + put_reg (a1, a); + put_reg (r3, b); + + /** 1011 1000 000w 0011 SSTR.size */ + + a = get_reg (a1); + b = get_reg (r3); + for (;b;) + { + if (w) + mem_put_hi(a, r0); + else + mem_put_qi(a, r0 & 0xff); + a += w ? 2 : 1; + b --; + } + put_reg (a1, a); + put_reg (r3, b); + + /** 0000 0001 1101 ddd1 dd01 0src STC src,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 4); + sc = decode_cr_b (src, CR_B_DMA0); + a = get_src (sc); + put_dest (dc, a); + + /** 0000 0001 1101 ddd1 dd01 1src STC src,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 2); + sc = decode_cr_b (src, CR_B_DCT0); + a = get_src (sc); + put_dest (dc, a); + + /** 1101 ddd1 dd01 0src STC src,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, 4); + sc = decode_cr_b (src, CR_B_INTB); + a = get_src (sc); + put_dest (dc, a); + + /** 1011 0110 1101 0011 STCX abs16,abs24 */ + + NOTYET(); + + /** 1001 ddd w dd01 1111 STNZ.size #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM(w+1); + if (! FLAG_Z) + put_dest (dc, imm); + + /** 1001 ddd w dd00 1111 STZ.size #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM(w+1); + if (FLAG_Z) + put_dest (dc, imm); + + /** 1001 ddd w dd11 1111 STZX.size #IMM1,#IMM2,dest */ + + prefix (0, 1, 0); + dc = decode_dest23 (ddd, dd, w+1); + a = IMM(w+1); + b = IMM(w+1); + if (FLAG_Z) + put_dest (dc, a); + else + put_dest (dc, b); + + /** 1000 ddd w dd11 1110 SUB.size:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, w+1); + imm = IMM(w+1); + MATH_OP (dc, imm, 0, -); + + /** 1001 ddd0 dd11 0001 SUB.L:G #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, 4); + imm = IMM(4); + MATH_OP (dc, imm, 0, -); + + /** 00dd 111w SUB.size:S #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest2(dd, w+1); + imm = IMM (w+1); + MATH_OP (dc, imm, 0, -); + + /** 1sss ddd w dd ss 1010 SUB.size:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, w+1); + dc = decode_dest23(ddd, dd, w+1); + b = get_src (sc); + MATH_OP (dc, b, 0, -); + + /** 1sss ddd1 dd ss 0000 SUB.L:G src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, 4); + dc = decode_dest23(ddd, dd, 4); + b = get_src (sc); + MATH_OP (dc, b, 0, -); + + /** 1001 ddd0 dd01 0001 SUBX #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, 4); + imm = sign_ext (IMM(1), 8); + MATH_OP (dc, imm, 0, -); + + /** 1sss ddd0 dd ss 0000 SUBX src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, 1); + dc = decode_dest23(ddd, dd, 4); + b = sign_ext (get_src (sc), 8); + MATH_OP (dc, b, 0, -); + + /** 1001 ddd w dd11 1110 TST.size:G #IMM,dest */ + + prefix (0, 0, 0); + dc = decode_dest23 (ddd, dd, w+1); + imm = IMM(w+1); + a = get_src (dc); + v = a & imm; + set_sz (v, w+1); + + /** 00dd 110w TST.size:S #IMM,dest */ + + prefix (0, 0, 0); + dc = decode_dest2 (dd, w+1); + imm = IMM(w+1); + a = get_src (dc); + v = a & imm; + set_sz (v, w+1); + + /** 0000 0001 1sss ddd w dd ss 1001 TST.size:G src,dest */ + + prefix (0, 0, 0); + sc = decode_src23 (sss, ss, w+1); + dc = decode_dest23 (ddd, dd, w+1); + b = get_src (sc); + a = get_src (dc); + v = a & b; + set_sz (v, w+1); + + /** 1111 1111 UND */ + + trigger_fixed_interrupt (0xffffdc); + + /** 1011 0010 0000 0011 WAIT */ + + ; + + /** 1101 ddd w dd00 1src XCHG.size src,dest */ + + dc = decode_dest23 (ddd, dd, w+1); + sc = decode_src3 (src, w+1); + a = get_src (dc); + b = get_src (sc); + put_dest (dc, b); + put_dest (sc, a); + + /** 1001 ddd w dd00 1110 XOR.size #IMM,dest */ + + prefix (0, 1, 0); + dc = decode_dest23(ddd, dd, w+1); + imm = IMM(w+1); + LOGIC_OP (dc, imm, ^); + + /** 1sss ddd w dd ss 1001 XOR.size src,dest */ + + prefix (1, 1, 0); + sc = decode_src23(sss, ss, w+1); + dc = decode_dest23(ddd, dd, w+1); + b = get_src (sc); + LOGIC_OP (dc, b, ^); + +/** */ + + return step_result; +} Index: configure.in =================================================================== --- configure.in (nonexistent) +++ configure.in (revision 33) @@ -0,0 +1,31 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +dnl Contributed by Red Hat, Inc. +dnl +dnl This file is part of the GNU simulators. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program. If not, see . +dnl +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) +AC_CONFIG_HEADER(config.h:config.in) + +sinclude(../common/aclocal.m4) + +# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around +# it by inlining the macro's contents. +sinclude(../common/common.m4) + +SIM_AC_OUTPUT
configure.in Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: opc2c.c =================================================================== --- opc2c.c (nonexistent) +++ opc2c.c (revision 33) @@ -0,0 +1,728 @@ +/* opc2c.c --- generate C simulator code from from .opc file + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include +#include + +#include "safe-fgets.h" + +static int errors = 0; + +#define MAX_BYTES 10 + +typedef struct +{ + int varyno:16; + int byte:8; + int shift:8; +} VaryRef; + +typedef struct +{ + char nbytes; + char dbytes; + char id[MAX_BYTES * 8 + 1]; + unsigned char var_start[MAX_BYTES * 8 + 1]; + struct + { + unsigned char decodable_mask; + unsigned char decodable_bits; + } b[MAX_BYTES]; + char *comment; + int lineno; + int nlines; + char **lines; + struct Indirect *last_ind; + int semantics_label; + int nvaries; + VaryRef *vary; +} opcode; + +int n_opcodes; +opcode **opcodes; +opcode *op; + +typedef struct +{ + char *name; + int nlen; + unsigned char mask; + int n_patterns; + unsigned char *patterns; +} Vary; + +Vary **vary = 0; +int n_varies = 0; + +unsigned char cur_bits[MAX_BYTES + 1]; + +char *orig_filename; + +FILE *sim_log = 0; +#define lprintf if (sim_log) fprintf + +opcode prefix_text, suffix_text; + +typedef enum +{ + T_unused, + T_op, + T_indirect, + T_done +} OpType; + +typedef struct Indirect +{ + OpType type; + union + { + struct Indirect *ind; + opcode *op; + } u; +} Indirect; + +Indirect indirect[256]; + +static int +next_varybits (int bits, opcode * op, int byte) +{ + int mask = op->b[byte].decodable_mask; + int i; + + for (i = 0; i < 8; i++) + if (!(mask & (1 << i))) + { + if (bits & (1 << i)) + { + bits &= ~(1 << i); + } + else + { + bits |= (1 << i); + return bits; + } + } + return 0; +} + +static int +valid_varybits (int bits, opcode * op, int byte) +{ + if (op->nvaries) + { + int vn; + for (vn = 0; vn < op->nvaries; vn++) + { + int found = 0; + int i; + int ob; + + if (byte != op->vary[vn].byte) + continue; + Vary *v = vary[op->vary[vn].varyno]; + ob = (bits >> op->vary[vn].shift) & v->mask; + lprintf (sim_log, "varybits: vary %s ob %x\n", v->name, ob); + + for (i = 0; i < v->n_patterns; i++) + if (ob == v->patterns[i]) + { + lprintf (sim_log, " found at %d\n", i); + found = 1; + break; + } + if (!found) + return 0; + } + } + return 1; +} + +char * +prmb (int mask, int bits) +{ + static char buf[8][30]; + static int bn = 0; + char *bp; + + bn = (bn + 1) % 8; + bp = buf[bn]; + int i; + for (i = 0; i < 8; i++) + { + int bit = 0x80 >> i; + if (!(mask & bit)) + *bp++ = '-'; + else if (bits & bit) + *bp++ = '1'; + else + *bp++ = '0'; + if (i % 4 == 3) + *bp++ = ' '; + } + *--bp = 0; + return buf[bn]; +} + +static int +op_cmp (const void *va, const void *vb) +{ + const opcode *a = *(const opcode **) va; + const opcode *b = *(const opcode **) vb; + + if (a->nbytes != b->nbytes) + return a->nbytes - b->nbytes; + + return strcmp (a->id, b->id); +} + +void +dump_lines (opcode * op, int level, Indirect * ind) +{ + char *varnames[40]; + int i, vn = 0; + + if (op->semantics_label) + { + printf ("%*sgoto op_semantics_%d;\n", level, "", op->semantics_label); + return; + } + + if (ind != op->last_ind) + { + static int labelno = 0; + labelno++; + printf ("%*sop_semantics_%d:\n", level, "", labelno); + op->semantics_label = labelno; + } + + if (op->comment) + { + level += 2; + printf ("%*s{\n", level, ""); + printf ("%*s %s\n", level, "", op->comment); + } + + for (i = 0; i < op->nbytes * 8;) + { + if (isalpha (op->id[i])) + { + int byte = i >> 3; + int mask = 0; + int shift = 0; + char name[33]; + char *np = name; + while (op->id[i] && isalpha (op->id[i])) + { + mask = (mask << 1) | 1; + shift = 7 - (i & 7); + *np++ = op->id[i++]; + if (op->var_start[i]) + break; + } + *np = 0; + varnames[vn++] = strdup (name); + printf ("#line %d \"%s\"\n", op->lineno, orig_filename); + if (mask & ~0xff) + { + fprintf (stderr, "Error: variable %s spans bytes: %s\n", + name, op->comment); + errors++; + } + else if (shift && (mask != 0xff)) + printf ("%*s int %s AU = (op[%d] >> %d) & 0x%02x;\n", + level, "", name, byte, shift, mask); + else if (mask != 0xff) + printf ("%*s int %s AU = op[%d] & 0x%02x;\n", + level, "", name, byte, mask); + else + printf ("%*s int %s AU = op[%d];\n", level, "", name, byte); + } + else + i++; + } + if (op->comment) + { + printf ("%*s if (trace) {\n", level, ""); + printf ("%*s printf(\"\\033[33m%%s\\033[0m ", level, ""); + for (i = 0; i < op->nbytes; i++) + printf (" %%02x"); + printf ("\\n\""); + printf (",\n%*s \"%s\"", level, "", op->comment); + for (i = 0; i < op->nbytes; i++) + { + if (i == 0) + printf (",\n%*s op[%d]", level, "", i); + else + printf (", op[%d]", i); + } + printf (");\n"); + for (i = 0; i < vn; i++) + printf ("%*s printf(\" %s = 0x%%x%s\", %s);\n", level, "", + varnames[i], (i < vn - 1) ? "," : "\\n", varnames[i]); + printf ("%*s }\n", level, ""); + } + printf ("#line %d \"%s\"\n", op->lineno + 1, orig_filename); + for (i = 0; i < op->nlines; i++) + printf ("%*s%s", level, "", op->lines[i]); + if (op->comment) + printf ("%*s}\n", level, ""); +} + +void +store_opcode_bits (opcode * op, int byte, Indirect * ind) +{ + int bits = op->b[byte].decodable_bits; + + do + { + if (!valid_varybits (bits, op, byte)) + continue; + + switch (ind[bits].type) + { + case T_unused: + if (byte == op->dbytes - 1) + { + ind[bits].type = T_op; + ind[bits].u.op = op; + op->last_ind = ind; + break; + } + else + { + int i2; + ind[bits].type = T_indirect; + ind[bits].u.ind = (Indirect *) malloc (256 * sizeof (Indirect)); + for (i2 = 0; i2 < 256; i2++) + ind[bits].u.ind[i2].type = T_unused; + store_opcode_bits (op, byte + 1, ind[bits].u.ind); + } + break; + + case T_indirect: + if (byte < op->dbytes - 1) + store_opcode_bits (op, byte + 1, ind[bits].u.ind); + break; + + case T_op: + break; + + case T_done: + break; + } + } + while ((bits = next_varybits (bits, op, byte)) != 0); +} + +void +emit_indirect (Indirect * ind, int byte) +{ + int unsup = 0; + int j, n, mask; + + mask = 0; + for (j = 0; j < 256; j++) + { + switch (ind[j].type) + { + case T_indirect: + mask = 0xff; + break; + case T_op: + mask |= ind[j].u.op->b[byte].decodable_mask; + break; + case T_done: + case T_unused: + break; + } + } + + printf ("%*s GETBYTE();\n", byte * 6, ""); + printf ("%*s switch (op[%d] & 0x%02x) {\n", byte * 6, "", byte, mask); + for (j = 0; j < 256; j++) + if ((j & ~mask) == 0) + { + switch (ind[j].type) + { + case T_done: + break; + case T_unused: + unsup = 1; + break; + case T_op: + for (n = j; n < 256; n++) + if ((n & ~mask) == 0 + && ind[n].type == T_op && ind[n].u.op == ind[j].u.op) + { + ind[n].type = T_done; + printf ("%*s case 0x%02x:\n", byte * 6, "", n); + } + for (n = byte; n < ind[j].u.op->nbytes - 1; n++) + printf ("%*s GETBYTE();\n", byte * 6, ""); + dump_lines (ind[j].u.op, byte * 6 + 6, ind); + printf ("%*s break;\n", byte * 6, ""); + break; + case T_indirect: + printf ("%*s case 0x%02x:\n", byte * 6, "", j); + emit_indirect (ind[j].u.ind, byte + 1); + printf ("%*s break;\n", byte * 6, ""); + break; + } + } + if (unsup) + printf ("%*s default: UNSUPPORTED(); break;\n", byte * 6, ""); + printf ("%*s }\n", byte * 6, ""); +} + +static char * +pv_dup (char *p, char *ep) +{ + int n = ep - p; + char *rv = (char *) malloc (n + 1); + memcpy (rv, p, n); + rv[n] = 0; + return rv; +} + +static unsigned char +str2mask (char *str, char *ep) +{ + unsigned char rv = 0; + while (str < ep) + { + rv *= 2; + if (*str == '1') + rv += 1; + str++; + } + return rv; +} + +static void +process_vary (char *line) +{ + char *cp, *ep; + Vary *v = (Vary *) malloc (sizeof (Vary)); + + n_varies++; + if (vary) + vary = (Vary **) realloc (vary, n_varies * sizeof (Vary *)); + else + vary = (Vary **) malloc (n_varies * sizeof (Vary *)); + vary[n_varies - 1] = v; + + cp = line; + + for (cp = line; isspace (*cp); cp++); + for (ep = cp; *ep && !isspace (*ep); ep++); + + v->name = pv_dup (cp, ep); + v->nlen = strlen (v->name); + v->mask = (1 << v->nlen) - 1; + + v->n_patterns = 0; + v->patterns = (unsigned char *) malloc (1); + while (1) + { + for (cp = ep; isspace (*cp); cp++); + if (!isdigit (*cp)) + break; + for (ep = cp; *ep && !isspace (*ep); ep++); + v->n_patterns++; + v->patterns = (unsigned char *) realloc (v->patterns, v->n_patterns); + v->patterns[v->n_patterns - 1] = str2mask (cp, ep); + } +} + +static int +fieldcmp (opcode * op, int bit, char *name) +{ + int n = strlen (name); + if (memcmp (op->id + bit, name, n) == 0 + && (!isalpha (op->id[bit + n]) || op->var_start[bit + n])) + return 1; + return 0; +} + +static void +log_indirect (Indirect * ind, int byte) +{ + int i, j; + char *last_c = 0; + + for (i = 0; i < 256; i++) + { + if (ind[i].type == T_unused) + continue; + + for (j = 0; j < byte; j++) + fprintf (sim_log, "%s ", prmb (255, cur_bits[j])); + fprintf (sim_log, "%s ", prmb (255, i)); + + switch (ind[i].type) + { + case T_op: + case T_done: + if (last_c && (ind[i].u.op->comment == last_c)) + fprintf (sim_log, "''\n"); + else + fprintf (sim_log, "%s\n", ind[i].u.op->comment); + last_c = ind[i].u.op->comment; + break; + case T_unused: + fprintf (sim_log, "-\n"); + break; + case T_indirect: + fprintf (sim_log, "indirect\n"); + cur_bits[byte] = i; + log_indirect (ind[i].u.ind, byte + 1); + last_c = 0; + break; + } + } +} + +int +main (int argc, char **argv) +{ + char *line; + FILE *in; + int lineno = 0; + int i; + VaryRef *vlist; + + if (argc > 2 && strcmp (argv[1], "-l") == 0) + { + sim_log = fopen (argv[2], "w"); + fprintf (stderr, "sim_log: %s\n", argv[2]); + argc -= 2; + argv += 2; + } + + if (argc < 2) + { + fprintf (stderr, "usage: opc2c infile.opc > outfile.opc\n"); + exit (1); + } + + orig_filename = argv[1]; + in = fopen (argv[1], "r"); + if (!in) + { + fprintf (stderr, "Unable to open file %s for reading\n", argv[1]); + perror ("The error was"); + exit (1); + } + + n_opcodes = 0; + opcodes = (opcode **) malloc (sizeof (opcode *)); + op = &prefix_text; + op->lineno = 1; + while ((line = safe_fgets (in)) != 0) + { + lineno++; + if (strncmp (line, " /** ", 6) == 0 + && (isdigit (line[6]) || memcmp (line + 6, "VARY", 4) == 0)) + line += 2; + if (line[0] == '/' && line[1] == '*' && line[2] == '*') + { + if (strncmp (line, "/** */", 6) == 0) + { + op = &suffix_text; + op->lineno = lineno; + } + else if (strncmp (line, "/** VARY ", 9) == 0) + process_vary (line + 9); + else + { + char *lp; + int i, bit, byte; + int var_start = 1; + + n_opcodes++; + opcodes = + (opcode **) realloc (opcodes, n_opcodes * sizeof (opcode *)); + op = (opcode *) malloc (sizeof (opcode)); + opcodes[n_opcodes - 1] = op; + + op->nbytes = op->dbytes = 0; + memset (op->id, 0, sizeof (op->id)); + memset (op->var_start, 0, sizeof (op->var_start)); + for (i = 0; i < MAX_BYTES; i++) + { + op->b[i].decodable_mask = 0; + op->b[i].decodable_bits = 0; + } + op->comment = strdup (line); + op->comment[strlen (op->comment) - 1] = 0; + while (op->comment[0] && isspace (op->comment[0])) + op->comment++; + op->lineno = lineno; + op->nlines = 0; + op->lines = 0; + op->last_ind = 0; + op->semantics_label = 0; + op->nvaries = 0; + op->vary = 0; + + i = 0; + for (lp = line + 4; *lp; lp++) + { + bit = 7 - (i & 7); + byte = i >> 3; + + if (strncmp (lp, "*/", 2) == 0) + break; + else if ((lp[0] == ' ' && lp[1] == ' ') || (lp[0] == '\t')) + break; + else if (*lp == ' ') + var_start = 1; + else + { + if (*lp == '0' || *lp == '1') + { + op->b[byte].decodable_mask |= 1 << bit; + var_start = 1; + if (op->dbytes < byte + 1) + op->dbytes = byte + 1; + } + else if (var_start) + { + op->var_start[i] = 1; + var_start = 0; + } + if (*lp == '1') + op->b[byte].decodable_bits |= 1 << bit; + + op->nbytes = byte + 1; + op->id[i++] = *lp; + } + } + } + } + else + { + op->nlines++; + if (op->lines) + op->lines = + (char **) realloc (op->lines, op->nlines * sizeof (char *)); + else + op->lines = (char **) malloc (op->nlines * sizeof (char *)); + op->lines[op->nlines - 1] = strdup (line); + } + } + + { + int i, j; + for (i = 0; i < n_varies; i++) + { + Vary *v = vary[i]; + lprintf (sim_log, "V[%s] %d\n", v->name, v->nlen); + for (j = 0; j < v->n_patterns; j++) + lprintf (sim_log, " P %02x\n", v->patterns[j]); + } + } + + for (i = n_opcodes - 2; i >= 0; i--) + { + if (opcodes[i]->nlines == 0) + { + opcodes[i]->nlines = opcodes[i + 1]->nlines; + opcodes[i]->lines = opcodes[i + 1]->lines; + } + } + + for (i = 0; i < 256; i++) + indirect[i].type = T_unused; + + qsort (opcodes, n_opcodes, sizeof (opcodes[0]), op_cmp); + + vlist = (VaryRef *) malloc (n_varies * sizeof (VaryRef)); + + for (i = 0; i < n_opcodes; i++) + { + int j, b, v; + + for (j = 0; j < opcodes[i]->nbytes; j++) + lprintf (sim_log, "%s ", + prmb (opcodes[i]->b[j].decodable_mask, + opcodes[i]->b[j].decodable_bits)); + lprintf (sim_log, " %s\n", opcodes[i]->comment); + + for (j = 0; j < opcodes[i]->nbytes; j++) + { + for (b = 0; b < 8; b++) + if (isalpha (opcodes[i]->id[j * 8 + b])) + for (v = 0; v < n_varies; v++) + if (fieldcmp (opcodes[i], j * 8 + b, vary[v]->name)) + { + int nv = opcodes[i]->nvaries++; + if (nv) + opcodes[i]->vary = + (VaryRef *) realloc (opcodes[i]->vary, + (nv + 1) * sizeof (VaryRef)); + else + opcodes[i]->vary = + (VaryRef *) malloc ((nv + 1) * sizeof (VaryRef)); + + opcodes[i]->vary[nv].varyno = v; + opcodes[i]->vary[nv].byte = j; + opcodes[i]->vary[nv].shift = 8 - b - vary[v]->nlen; + lprintf (sim_log, "[vary %s shift %d]\n", + vary[v]->name, opcodes[i]->vary[nv].shift); + } + + } + } + + for (i = 0; i < n_opcodes; i++) + { + int i2; + int bytes = opcodes[i]->dbytes; + + lprintf (sim_log, "\nmask:"); + for (i2 = 0; i2 < opcodes[i]->nbytes; i2++) + lprintf (sim_log, " %02x", opcodes[i]->b[i2].decodable_mask); + lprintf (sim_log, "%*s%s\n", 13 - 3 * opcodes[i]->nbytes, "", + opcodes[i]->comment); + + lprintf (sim_log, "bits:"); + for (i2 = 0; i2 < opcodes[i]->nbytes; i2++) + lprintf (sim_log, " %02x", opcodes[i]->b[i2].decodable_bits); + lprintf (sim_log, "%*s(%s) %d byte%s\n", 13 - 3 * opcodes[i]->nbytes, + "", opcodes[i]->id, bytes, bytes == 1 ? "" : "s"); + + store_opcode_bits (opcodes[i], 0, indirect); + } + + dump_lines (&prefix_text, 0, 0); + + emit_indirect (indirect, 0); + + dump_lines (&suffix_text, 0, 0); + + if (sim_log) + log_indirect (indirect, 0); + + return errors; +}
opc2c.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: ChangeLog =================================================================== --- ChangeLog (nonexistent) +++ ChangeLog (revision 33) @@ -0,0 +1,69 @@ +2006-06-26 DJ Delorie + + * r8c.opc (decode_r8c): Don't bother reading the destination + before moving a constant into it. Fix borrow comparison for SUB. + +2006-06-13 Richard Earnshaw + + * configure: Regenerated. + +2006-06-05 Daniel Jacobowitz + + * configure: Regenerated. + +2006-05-31 Daniel Jacobowitz + + * configure: Regenerated. + +2006-03-13 DJ Delorie + + * mem.c (mem_put_byte): Hook simulated UART to stdout. + (mem_put_hi): Hook in simulated trace port. + (mem_get_byte): Hook in simulated uart control port. + * opc2c: Be more picky about matching special comments. + * r8c.opc (shift_op): Limit shift counts to -16..16. + (BMcnd): Map conditional codes. + * reg.c (condition_true): Mask condition code to 4 bits. + * syscalls.c: Include local syscall.h. + * syscall.h: New, copied from libgloss. + +2005-10-06 Jim Blandy + + Simulator for Renesas M32C and M16C, by DJ Delorie , + with further work from Jim Blandy and + Kevin Buettner . + + * ChangeLog: New. + * Makefile.in: New. + * blinky.S: New. + * config.in: New. + * configure: New. + * configure.in: New. + * cpu.h: New. + * gdb-if.c: New. + * gloss.S: New. + * int.c: New. + * int.h: New. + * load.c: New. + * load.h: New. + * m32c.opc: New. + * main.c: New. + * mem.c: New. + * mem.h: New. + * misc.c: New. + * misc.h: New. + * opc2c.c: New. + * r8c.opc: New. + * reg.c: New. + * safe-fgets.c: New. + * safe-fgets.h: New. + * sample.S: New. + * sample.ld: New. + * sample2.c: New. + * srcdest.c: New. + * syscalls.c: New. + * syscalls.h: New. + * trace.c: New. + * trace.h: New. + +
ChangeLog Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: srcdest.c =================================================================== --- srcdest.c (nonexistent) +++ srcdest.c (revision 33) @@ -0,0 +1,778 @@ +/* srcdest.c --- decoding M32C addressing modes. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include + +#include "cpu.h" +#include "mem.h" + +static int src_indirect = 0; +static int dest_indirect = 0; +static int src_addend = 0; +static int dest_addend = 0; + +static int +disp8 () +{ + int rv; + int tsave = trace; + + if (trace == 1) + trace = 0; + rv = mem_get_qi (get_reg (pc)); + regs.r_pc++; + trace = tsave; + return rv; +} + +static int +disp16 () +{ + int rv; + int tsave = trace; + + if (trace == 1) + trace = 0; + rv = mem_get_hi (get_reg (pc)); + regs.r_pc += 2; + trace = tsave; + return rv; +} + +static int +disp24 () +{ + int rv; + int tsave = trace; + + if (trace == 1) + trace = 0; + rv = mem_get_psi (get_reg (pc)); + regs.r_pc += 3; + trace = tsave; + return rv; +} + +static int +disp20 () +{ + return disp24 () & 0x000fffff; +} + +const char * +bits (int v, int b) +{ + static char buf[17]; + char *bp = buf + 16; + *bp = 0; + while (b) + { + *--bp = (v & 1) ? '1' : '0'; + v >>= 1; + b--; + } + return bp; +} + +static const char *the_bits = 0; + +void +decode_indirect (int si, int di) +{ + src_indirect = si; + dest_indirect = di; + if (trace && (si || di)) + printf ("indirect: s:%d d:%d\n", si, di); +} + +void +decode_index (int sa, int da) +{ + src_addend = sa; + dest_addend = da; + if (trace && (sa || da)) + printf ("index: s:%d d:%d\n", sa, da); +} + +srcdest +decode_srcdest4 (int destcode, int bw) +{ + srcdest sd; + sd.bytes = bw ? 2 : 1; + sd.mem = (destcode >= 6) ? 1 : 0; + static const char *dc_wnames[16] = { "r0", "r1", "r2", "r3", + "a0", "a1", "[a0]", "[a1]", + "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]", + "disp16[a0]", "disp16[a1]", "disp16[sb]", "disp16" + }; + static const char *dc_bnames[4] = { "r0l", "r0h", "r1l", "r1h" };; + + if (trace) + { + const char *n = dc_wnames[destcode]; + if (bw == 0 && destcode <= 3) + n = dc_bnames[destcode]; + if (!the_bits) + the_bits = bits (destcode, 4); + printf ("decode: %s (%d) : %s\n", the_bits, destcode, n); + the_bits = 0; + } + + switch (destcode) + { + case 0x0: + sd.u.reg = bw ? r0 : r0l; + break; + case 0x1: + sd.u.reg = bw ? r1 : r0h; + break; + case 0x2: + sd.u.reg = bw ? r2 : r1l; + break; + case 0x3: + sd.u.reg = bw ? r3 : r1h; + break; + case 0x4: + sd.u.reg = a0; + break; + case 0x5: + sd.u.reg = a1; + break; + case 0x6: + sd.u.addr = get_reg (a0); + break; + case 0x7: + sd.u.addr = get_reg (a1); + break; + case 0x8: + sd.u.addr = get_reg (a0) + disp8 (); + break; + case 0x9: + sd.u.addr = get_reg (a1) + disp8 (); + break; + case 0xa: + sd.u.addr = get_reg (sb) + disp8 (); + break; + case 0xb: + sd.u.addr = get_reg (fb) + sign_ext (disp8 (), 8); + break; + case 0xc: + sd.u.addr = get_reg (a0) + disp16 (); + break; + case 0xd: + sd.u.addr = get_reg (a1) + disp16 (); + break; + case 0xe: + sd.u.addr = get_reg (sb) + disp16 (); + break; + case 0xf: + sd.u.addr = disp16 (); + break; + default: + abort (); + } + if (sd.mem) + sd.u.addr &= addr_mask; + return sd; +} + +srcdest +decode_jumpdest (int destcode, int w) +{ + srcdest sd; + sd.bytes = w ? 2 : 3; + sd.mem = (destcode >= 6) ? 1 : 0; + static const char *dc_wnames[16] = { "r0", "r1", "r2", "r3", + "a0", "a1", "[a0]", "[a1]", + "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]", + "disp20[a0]", "disp20[a1]", "disp16[sb]", "abs16" + }; + static const char *dc_anames[4] = { "r0l", "r0h", "r1l", "r1h" }; + + if (trace) + { + const char *n = dc_wnames[destcode]; + if (w == 0 && destcode <= 3) + n = dc_anames[destcode]; + if (!the_bits) + the_bits = bits (destcode, 4); + printf ("decode: %s : %s\n", the_bits, n); + the_bits = 0; + } + + switch (destcode) + { + case 0x0: + sd.u.reg = w ? r0 : r2r0; + break; + case 0x1: + sd.u.reg = w ? r1 : r2r0; + break; + case 0x2: + sd.u.reg = w ? r2 : r3r1; + break; + case 0x3: + sd.u.reg = w ? r3 : r3r1; + break; + case 0x4: + sd.u.reg = w ? a0 : a1a0; + break; + case 0x5: + sd.u.reg = w ? a1 : a1a0; + break; + case 0x6: + sd.u.addr = get_reg (a0); + break; + case 0x7: + sd.u.addr = get_reg (a1); + break; + case 0x8: + sd.u.addr = get_reg (a0) + disp8 (); + break; + case 0x9: + sd.u.addr = get_reg (a1) + disp8 (); + break; + case 0xa: + sd.u.addr = get_reg (sb) + disp8 (); + break; + case 0xb: + sd.u.addr = get_reg (fb) + sign_ext (disp8 (), 8); + break; + case 0xc: + sd.u.addr = get_reg (a0) + disp20 (); + break; + case 0xd: + sd.u.addr = get_reg (a1) + disp20 (); + break; + case 0xe: + sd.u.addr = get_reg (sb) + disp16 (); + break; + case 0xf: + sd.u.addr = disp16 (); + break; + default: + abort (); + } + if (sd.mem) + sd.u.addr &= addr_mask; + return sd; +} + +srcdest +decode_dest3 (int destcode, int bw) +{ + static char map[8] = { -1, -1, -1, 1, 0, 10, 11, 15 }; + + the_bits = bits (destcode, 3); + return decode_srcdest4 (map[destcode], bw); +} + +srcdest +decode_src2 (int srccode, int bw, int d) +{ + static char map[4] = { 0, 10, 11, 15 }; + + the_bits = bits (srccode, 2); + return decode_srcdest4 (srccode ? map[srccode] : 1 - d, bw); +} + +static struct +{ + reg_id b_regno; + reg_id w_regno; + int is_memory; + int disp_bytes; + char *name; +} modes23[] = +{ + { + a0, a0, 1, 0, "[A0]"}, /* 0 0 0 0 0 */ + { + a1, a1, 1, 0, "[A1]"}, /* 0 0 0 0 1 */ + { + a0, a0, 0, 0, "A0"}, /* 0 0 0 1 0 */ + { + a1, a1, 0, 0, "A1"}, /* 0 0 0 1 1 */ + { + a0, a0, 1, 1, "dsp:8[A0]"}, /* 0 0 1 0 0 */ + { + a1, a1, 1, 1, "dsp:8[A1]"}, /* 0 0 1 0 1 */ + { + sb, sb, 1, 1, "dsp:8[SB]"}, /* 0 0 1 1 0 */ + { + fb, fb, 1, -1, "dsp:8[FB]"}, /* 0 0 1 1 1 */ + { + a0, a0, 1, 2, "dsp:16[A0]"}, /* 0 1 0 0 0 */ + { + a1, a1, 1, 2, "dsp:16[A1]"}, /* 0 1 0 0 1 */ + { + sb, sb, 1, 2, "dsp:16[SB]"}, /* 0 1 0 1 0 */ + { + fb, fb, 1, -2, "dsp:16[FB]"}, /* 0 1 0 1 1 */ + { + a0, a0, 1, 3, "dsp:24[A0]"}, /* 0 1 1 0 0 */ + { + a1, a1, 1, 3, "dsp:24[A1]"}, /* 0 1 1 0 1 */ + { + mem, mem, 1, 3, "abs24"}, /* 0 1 1 1 0 */ + { + mem, mem, 1, 2, "abs16"}, /* 0 1 1 1 1 */ + { + r0h, r2, 0, 0, "R0H/R2"}, /* 1 0 0 0 0 */ + { + r1h, r3, 0, 0, "R1H/R3"}, /* 1 0 0 0 1 */ + { + r0l, r0, 0, 0, "R0L/R0"}, /* 1 0 0 1 0 */ + { + r1l, r1, 0, 0, "R1L/R1"}, /* 1 0 0 1 1 */ +}; + +static srcdest +decode_sd23 (int bbb, int bb, int bytes, int ind, int add) +{ + srcdest sd; + int code = (bbb << 2) | bb; + + if (code >= sizeof (modes23) / sizeof (modes23[0])) + abort (); + + if (trace) + { + char *b1 = ""; + char *b2 = ""; + char ad[30]; + if (ind) + { + b1 = "["; + b2 = "]"; + } + if (add) + sprintf (ad, "%+d", add); + else + ad[0] = 0; + if (!the_bits) + the_bits = bits (code, 4); + printf ("decode: %s (%d) : %s%s%s%s\n", the_bits, code, b1, + modes23[code].name, ad, b2); + the_bits = 0; + } + + sd.bytes = bytes; + sd.mem = modes23[code].is_memory; + if (sd.mem) + { + if (modes23[code].w_regno == mem) + sd.u.addr = 0; + else + sd.u.addr = get_reg (modes23[code].w_regno); + switch (modes23[code].disp_bytes) + { + case 1: + sd.u.addr += disp8 (); + break; + case 2: + sd.u.addr += disp16 (); + break; + case -1: + sd.u.addr += sign_ext (disp8 (), 8); + break; + case -2: + sd.u.addr += sign_ext (disp16 (), 16); + break; + case 3: + sd.u.addr += disp24 (); + break; + default: + break; + } + if (add) + sd.u.addr += add; + if (ind) + sd.u.addr = mem_get_si (sd.u.addr & membus_mask); + sd.u.addr &= membus_mask; + } + else + { + sd.u.reg = (bytes > 1) ? modes23[code].w_regno : modes23[code].b_regno; + if (bytes == 3 || bytes == 4) + { + switch (sd.u.reg) + { + case r0: + sd.u.reg = r2r0; + break; + case r1: + sd.u.reg = r3r1; + break; + case r2: + abort (); + case r3: + abort (); + default:; + } + } + + } + return sd; +} + +srcdest +decode_dest23 (int ddd, int dd, int bytes) +{ + return decode_sd23 (ddd, dd, bytes, dest_indirect, dest_addend); +} + +srcdest +decode_src23 (int sss, int ss, int bytes) +{ + return decode_sd23 (sss, ss, bytes, src_indirect, src_addend); +} + +srcdest +decode_dest2 (int dd, int bytes) +{ + /* r0l/r0, abs16, dsp:8[SB], dsp:8[FB] */ + static char map[4] = { 0x12, 0x0f, 0x06, 0x07 }; + + the_bits = bits (dd, 2); + return decode_sd23 (map[dd] >> 2, map[dd] & 3, bytes, dest_indirect, + dest_addend); +} + +srcdest +decode_src3 (int sss, int bytes) +{ + /* r0, r1, a0, a1, r2, r3, N/A, N/A */ + static char map[8] = { 0x12, 0x13, 0x02, 0x03, 0x10, 0x11, 0, 0 }; + + the_bits = bits (sss, 3); + return decode_sd23 (map[sss] >> 2, map[sss] & 3, bytes, src_indirect, + src_addend); +} + +srcdest +decode_dest1 (int destcode, int bw) +{ + the_bits = bits (destcode, 1); + return decode_srcdest4 (destcode, bw); +} + +srcdest +decode_cr (int crcode) +{ + static int regcode[] = { 0, intbl, intbh, flags, isp, sp, sb, fb }; + srcdest sd; + sd.mem = 0; + sd.bytes = 2; + sd.u.reg = regcode[crcode & 7]; + return sd; +} + +srcdest +decode_cr_b (int crcode, int bank) +{ + /* FIXME: intbl, intbh, isp */ + static int regcode[3][8] = { + {0, 0, flags, 0, 0, 0, 0, 0}, + {intb, sp, sb, fb, 0, 0, 0, isp}, + {0, 0, 0, 0, 0, 0, 0, 0} + }; + srcdest sd; + sd.mem = 0; + sd.bytes = bank ? 3 : 2; + sd.u.reg = regcode[bank][crcode & 7]; + return sd; +} + +srcdest +widen_sd (srcdest sd) +{ + sd.bytes *= 2; + if (!sd.mem) + switch (sd.u.reg) + { + case r0l: + sd.u.reg = r0; + break; + case r0: + sd.u.reg = r2r0; + break; + case r1l: + sd.u.reg = r1; + break; + case r1: + sd.u.reg = r3r1; + break; + case a0: + if (A16) + sd.u.reg = a1a0; + break; + default: + break; + } + return sd; +} + +srcdest +reg_sd (reg_id reg) +{ + srcdest rv; + rv.bytes = reg_bytes[reg]; + rv.mem = 0; + rv.u.reg = reg; + return rv; +} + +int +get_src (srcdest sd) +{ + int v; + if (sd.mem) + { + switch (sd.bytes) + { + case 1: + v = mem_get_qi (sd.u.addr); + break; + case 2: + v = mem_get_hi (sd.u.addr); + break; + case 3: + v = mem_get_psi (sd.u.addr); + break; + case 4: + v = mem_get_si (sd.u.addr); + break; + default: + abort (); + } + } + else + { + v = get_reg (sd.u.reg); + switch (sd.bytes) + { + case 1: + v &= 0xff; + break; + case 2: + v &= 0xffff; + break; + case 3: + v &= 0xffffff; + break; + } + } + return v; +} + +void +put_dest (srcdest sd, int v) +{ + if (sd.mem) + { + switch (sd.bytes) + { + case 1: + mem_put_qi (sd.u.addr, v); + break; + case 2: + mem_put_hi (sd.u.addr, v); + break; + case 3: + mem_put_psi (sd.u.addr, v); + break; + case 4: + mem_put_si (sd.u.addr, v); + break; + } + } + else + { + switch (sd.bytes) + { + case 1: + v &= 0xff; + break; + case 2: + v &= 0xffff; + break; + case 3: + v &= 0xffffff; + break; + } + put_reg (sd.u.reg, v); + } +} + +srcdest +decode_bit (int destcode) +{ + srcdest sd; + int addr = 0; + static const char *dc_names[] = { "r0", "r1", "r2", "r3", + "a0", "a1", "[a0]", "[a1]", + "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]", + "disp16[a0]", "disp16[a1]", "disp16[sb]", "abs16" + }; + + if (trace) + { + const char *the_bits = bits (destcode, 4); + printf ("decode: %s : %s\n", the_bits, dc_names[destcode]); + } + + switch (destcode) + { + case 0: + sd.u.reg = r0; + break; + case 1: + sd.u.reg = r1; + break; + case 2: + sd.u.reg = r2; + break; + case 3: + sd.u.reg = r3; + break; + case 4: + sd.u.reg = a0; + break; + case 5: + sd.u.reg = a1; + break; + case 6: + addr = get_reg (a0); + break; + case 7: + addr = get_reg (a1); + break; + case 8: + addr = get_reg (a0) + disp8 (); + break; + case 9: + addr = get_reg (a1) + disp8 (); + break; + case 10: + addr = get_reg (sb) * 8 + disp8 (); + break; + case 11: + addr = get_reg (fb) * 8 + sign_ext (disp8 (), 8); + break; + case 12: + addr = get_reg (a0) + disp16 (); + break; + case 13: + addr = get_reg (a1) + disp16 (); + break; + case 14: + addr = get_reg (sb) + disp16 (); + break; + case 15: + addr = disp16 (); + break; + } + + if (destcode < 6) + { + int d = disp8 (); + sd.mem = 0; + sd.mask = 1 << (d & 0x0f); + } + else + { + addr &= addr_mask; + sd.mem = 1; + sd.mask = 1 << (addr & 7); + sd.u.addr = addr >> 3; + } + return sd; +} + +srcdest +decode_bit11 (int op0) +{ + srcdest sd; + sd.mask = 1 << (op0 & 7); + sd.mem = 1; + sd.u.addr = get_reg (sb) + disp8 (); + return sd; +} + +int +get_bit (srcdest sd) +{ + int b; + if (sd.mem) + b = mem_get_qi (sd.u.addr) & sd.mask; + else + b = get_reg (sd.u.reg) & sd.mask; + return b ? 1 : 0; +} + +void +put_bit (srcdest sd, int val) +{ + int b; + if (sd.mem) + b = mem_get_qi (sd.u.addr); + else + b = get_reg (sd.u.reg); + if (val) + b |= sd.mask; + else + b &= ~sd.mask; + if (sd.mem) + mem_put_qi (sd.u.addr, b); + else + put_reg (sd.u.reg, b); +} + +int +get_bit2 (srcdest sd, int bit) +{ + int b; + if (sd.mem) + b = mem_get_qi (sd.u.addr + (bit >> 3)) & (1 << (bit & 7)); + else + b = get_reg (sd.u.reg) & (1 << bit); + return b ? 1 : 0; +} + +void +put_bit2 (srcdest sd, int bit, int val) +{ + int b; + if (sd.mem) + b = mem_get_qi (sd.u.addr + (bit >> 3)); + else + b = get_reg (sd.u.reg); + if (val) + b |= (1 << (bit & 7)); + else + b &= ~(1 << (bit & 7)); + if (sd.mem) + mem_put_qi (sd.u.addr + (bit >> 3), b); + else + put_reg (sd.u.reg, b); +}
srcdest.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: gloss.S =================================================================== --- gloss.S (nonexistent) +++ gloss.S (revision 33) @@ -0,0 +1,32 @@ +;;; gloss.S --- system calls for sample2.x +;;; +;;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +;;; Contributed by Red Hat, Inc. +;;; +;;; This file is part of the GNU simulators. +;;; +;;; This program 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 3 of the License, or +;;; (at your option) any later version. +;;; +;;; This program 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 this program. If not, see . + +;;; See the 'sample2.x' target in Makefile.in. + .global _exit +_exit: + mov.b #1,r0l + ste.b r0l,0xe0000 + rts + + .global _foo +_foo: + mov.b #2,r0l + ste.b r0l,0xe0000 + rts
gloss.S Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: blinky.S =================================================================== --- blinky.S (nonexistent) +++ blinky.S (revision 33) @@ -0,0 +1,34 @@ +;;; blinky.S --- sample program to blink LED's on M32C simulator +;;; +;;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +;;; Contributed by Red Hat, Inc. +;;; +;;; This file is part of the GNU simulators. +;;; +;;; This program 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 3 of the License, or +;;; (at your option) any later version. +;;; +;;; This program 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 this program. If not, see . + + .text + + .global _start +_start: + mov.w #0xe1,a0 +top: + sub.w #1,r0 + mov.b r0h,[a0] + + mov.w #1000,r1 +loop: + adjnz.w #-1,r1,loop + + jmp.w top
blinky.S Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: reg.c =================================================================== --- reg.c (nonexistent) +++ reg.c (revision 33) @@ -0,0 +1,622 @@ +/* reg.c --- register set model for M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include + +#include "cpu.h" + +int verbose = 0; +int trace = 0; +int enable_counting = 0; + +regs_type regs; +int addr_mask = 0xffff; +int membus_mask = 0xfffff; +int m32c_cpu = 0; +int step_result; +unsigned int heapbottom = 0; +unsigned int heaptop = 0; + +char *reg_names[] = { + "mem", + "r0", "r0h", "r0l", + "r1", "r1h", "r1l", + "r2", "r2r0", + "r3", "r3r1", + "r3r1r2r0", + "r3r2r1r0", + "a0", + "a1", "a1a0", + "sb", "fb", + "intb", "intbl", "intbh", + "sp", "usp", "isp", "pc", "flags" +}; + +int reg_bytes[] = { + 0, + 2, 1, 1, + 2, 1, 1, + 2, 4, + 2, 4, + 8, + 8, + 2, + 2, 4, + 2, 2, + 2, 1, 3, + 2, 2, 2, 3, 2 +}; + + +unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; +unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) }; +int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff }; +int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 }; + +static regs_type oldregs; + +void +init_regs (void) +{ + memset (®s, 0, sizeof (regs)); + memset (&oldregs, 0, sizeof (oldregs)); +} + +void +set_pointer_width (int bytes) +{ + if (bytes == 2) + { + addr_mask = 0xffff; + membus_mask = 0x000fffff; + reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] = + reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2; + } + else + { + addr_mask = 0xffffff; + membus_mask = 0x00ffffff; + reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] = + reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3; + } +} + +void +m32c_set_cpu (int cpu) +{ + switch (cpu) + { + case CPU_R8C: + case CPU_M16C: + set_pointer_width (2); + decode_opcode = decode_r8c; + break; + case CPU_M32CM: + case CPU_M32C: + set_pointer_width (3); + decode_opcode = decode_m32c; + break; + default: + abort (); + } + m32c_cpu = cpu; +} + +static unsigned int +get_reg_i (reg_id id) +{ + reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); + + switch (id) + { + case r0: + return b->r_r0; + case r0h: + return b->r_r0 >> 8; + case r0l: + return b->r_r0 & 0xff; + case r1: + return b->r_r1; + case r1h: + return b->r_r1 >> 8; + case r1l: + return b->r_r1 & 0xff; + case r2: + return b->r_r2; + case r2r0: + return b->r_r2 * 65536 + b->r_r0; + case r3: + return b->r_r3; + case r3r1: + return b->r_r3 * 65536 + b->r_r1; + + case a0: + return b->r_a0 & addr_mask; + case a1: + return b->r_a1 & addr_mask; + case a1a0: + return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff); + + case sb: + return b->r_sb & addr_mask; + case fb: + return b->r_fb & addr_mask; + + case intb: + return regs.r_intbh * 65536 + regs.r_intbl; + case intbl: + return regs.r_intbl; + case intbh: + return regs.r_intbh; + + case sp: + return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs. + r_isp) & addr_mask; + case usp: + return regs.r_usp & addr_mask; + case isp: + return regs.r_isp & addr_mask; + + case pc: + return regs.r_pc & membus_mask; + case flags: + return regs.r_flags; + default: + abort (); + } +} + +unsigned int +get_reg (reg_id id) +{ + unsigned int rv = get_reg_i (id); + if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1)) + printf ("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, rv); + return rv; +} + +DI +get_reg_ll (reg_id id) +{ + reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); + + switch (id) + { + case r3r1r2r0: + return ((DI) b->r_r3 << 48 + | (DI) b->r_r1 << 32 | (DI) b->r_r2 << 16 | (DI) b->r_r0); + case r3r2r1r0: + return ((DI) b->r_r3 << 48 + | (DI) b->r_r2 << 32 | (DI) b->r_r1 << 16 | (DI) b->r_r0); + default: + return get_reg (id); + } +} + +static int highest_sp = 0, lowest_sp = 0xffffff; + +void +stack_heap_stats () +{ + printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop, + heaptop - heapbottom); + printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp, + highest_sp - lowest_sp); +} + +void +put_reg (reg_id id, unsigned int v) +{ + if (trace > ((id != pc) ? 0 : 1)) + printf ("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, v); + + reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); + switch (id) + { + case r0: + b->r_r0 = v; + break; + case r0h: + b->r_r0 = (b->r_r0 & 0xff) | (v << 8); + break; + case r0l: + b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff); + break; + case r1: + b->r_r1 = v; + break; + case r1h: + b->r_r1 = (b->r_r1 & 0xff) | (v << 8); + break; + case r1l: + b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff); + break; + case r2: + b->r_r2 = v; + break; + case r2r0: + b->r_r0 = v & 0xffff; + b->r_r2 = v >> 16; + break; + case r3: + b->r_r3 = v; + break; + case r3r1: + b->r_r1 = v & 0xffff; + b->r_r3 = v >> 16; + break; + + case a0: + b->r_a0 = v & addr_mask; + break; + case a1: + b->r_a1 = v & addr_mask; + break; + case a1a0: + b->r_a0 = v & 0xffff; + b->r_a1 = v >> 16; + break; + + case sb: + b->r_sb = v & addr_mask; + break; + case fb: + b->r_fb = v & addr_mask; + break; + + case intb: + regs.r_intbl = v & 0xffff; + regs.r_intbh = v >> 16; + break; + case intbl: + regs.r_intbl = v & 0xffff; + break; + case intbh: + regs.r_intbh = v & 0xff; + break; + + case sp: + { + SI *spp; + if (regs.r_flags & FLAGBIT_U) + spp = ®s.r_usp; + else + spp = ®s.r_isp; + *spp = v & addr_mask; + if (*spp < heaptop) + { + printf ("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc, + heaptop, *spp); + exit (1); + } + if (*spp < lowest_sp) + lowest_sp = *spp; + if (*spp > highest_sp) + highest_sp = *spp; + break; + } + case usp: + regs.r_usp = v & addr_mask; + break; + case isp: + regs.r_isp = v & addr_mask; + break; + + case pc: + regs.r_pc = v & membus_mask; + break; + case flags: + regs.r_flags = v; + break; + default: + abort (); + } +} + +int +condition_true (int cond_id) +{ + int f; + if (A16) + { + static const char *cond_name[] = { + "C", "C&!Z", "Z", "S", + "!C", "!(C&!Z)", "!Z", "!S", + "(S^O)|Z", "O", "!(S^O)", "unk", + "!((S^O)|Z)", "!O", "S^O", "unk" + }; + switch (cond_id & 15) + { + case 0: + f = FLAG_C; + break; /* GEU/C */ + case 1: + f = FLAG_C & !FLAG_Z; + break; /* GTU */ + case 2: + f = FLAG_Z; + break; /* EQ/Z */ + case 3: + f = FLAG_S; + break; /* N */ + case 4: + f = !FLAG_C; + break; /* LTU/NC */ + case 5: + f = !(FLAG_C & !FLAG_Z); + break; /* LEU */ + case 6: + f = !FLAG_Z; + break; /* NE/NZ */ + case 7: + f = !FLAG_S; + break; /* PZ */ + + case 8: + f = (FLAG_S ^ FLAG_O) | FLAG_Z; + break; /* LE */ + case 9: + f = FLAG_O; + break; /* O */ + case 10: + f = !(FLAG_S ^ FLAG_O); + break; /* GE */ + case 12: + f = !((FLAG_S ^ FLAG_O) | FLAG_Z); + break; /* GT */ + case 13: + f = !FLAG_O; + break; /* NO */ + case 14: + f = FLAG_S ^ FLAG_O; + break; /* LT */ + + default: + f = 0; + break; + } + if (trace) + printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15], + f ? "true" : "false"); + } + else + { + static const char *cond_name[] = { + "!C", "LEU", "!Z", "PZ", + "!O", "GT", "GE", "?", + "C", "GTU", "Z", "N", + "O", "LE", "LT", "!?" + }; + switch (cond_id & 15) + { + case 0: + f = !FLAG_C; + break; /* LTU/NC */ + case 1: + f = !(FLAG_C & !FLAG_Z); + break; /* LEU */ + case 2: + f = !FLAG_Z; + break; /* NE/NZ */ + case 3: + f = !FLAG_S; + break; /* PZ */ + + case 4: + f = !FLAG_O; + break; /* NO */ + case 5: + f = !((FLAG_S ^ FLAG_O) | FLAG_Z); + break; /* GT */ + case 6: + f = !(FLAG_S ^ FLAG_O); + break; /* GE */ + + case 8: + f = FLAG_C; + break; /* GEU/C */ + case 9: + f = FLAG_C & !FLAG_Z; + break; /* GTU */ + case 10: + f = FLAG_Z; + break; /* EQ/Z */ + case 11: + f = FLAG_S; + break; /* N */ + + case 12: + f = FLAG_O; + break; /* O */ + case 13: + f = (FLAG_S ^ FLAG_O) | FLAG_Z; + break; /* LE */ + case 14: + f = FLAG_S ^ FLAG_O; + break; /* LT */ + + default: + f = 0; + break; + } + if (trace) + printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15], + f ? "true" : "false"); + } + return f; +} + +void +set_flags (int mask, int newbits) +{ + int i; + regs.r_flags &= ~mask; + regs.r_flags |= newbits & mask; + if (trace) + { + printf ("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12)) & 7); + for (i = 7; i >= 0; i--) + if (regs.r_flags & (1 << i)) + putchar ("CDZSBOIU"[i]); + else + putchar ('-'); + printf ("\033[0m\n"); + } +} + +void +set_oszc (int value, int b, int c) +{ + int mask = b2mask[b]; + int f = 0; + + if (c) + f |= FLAGBIT_C; + if ((value & mask) == 0) + f |= FLAGBIT_Z; + if (value & b2signbit[b]) + f |= FLAGBIT_S; + if ((value > b2maxsigned[b]) || (value < b2minsigned[b])) + f |= FLAGBIT_O; + set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f); +} + +void +set_szc (int value, int b, int c) +{ + int mask = b2mask[b]; + int f = 0; + + if (c) + f |= FLAGBIT_C; + if ((value & mask) == 0) + f |= FLAGBIT_Z; + if (value & b2signbit[b]) + f |= FLAGBIT_S; + set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f); +} + +void +set_osz (int value, int b) +{ + int mask = b2mask[b]; + int f = 0; + + if ((value & mask) == 0) + f |= FLAGBIT_Z; + if (value & b2signbit[b]) + f |= FLAGBIT_S; + if (value & ~mask && (value & ~mask) != ~mask) + f |= FLAGBIT_O; + set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f); +} + +void +set_sz (int value, int b) +{ + int mask = b2mask[b]; + int f = 0; + + if ((value & mask) == 0) + f |= FLAGBIT_Z; + if (value & b2signbit[b]) + f |= FLAGBIT_S; + set_flags (FLAGBIT_Z | FLAGBIT_S, f); +} + +void +set_zc (int z, int c) +{ + set_flags (FLAGBIT_C | FLAGBIT_Z, + (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0)); +} + +void +set_c (int c) +{ + set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0); +} + +void +put_reg_ll (reg_id id, DI v) +{ + reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); + + switch (id) + { + case r3r1r2r0: + b->r_r3 = v >> 48; + b->r_r1 = v >> 32; + b->r_r2 = v >> 16; + b->r_r0 = v; + break; + case r3r2r1r0: + b->r_r3 = v >> 48; + b->r_r2 = v >> 32; + b->r_r1 = v >> 16; + b->r_r0 = v; + break; + default: + put_reg (id, v); + } +} + +#define TRC(f,n, id) \ + if (oldregs.f != regs.f) \ + { \ + printf(" %s %0*x:%0*x", n, \ + reg_bytes[id]*2, (unsigned int)oldregs.f, \ + reg_bytes[id]*2, (unsigned int)regs.f); \ + oldregs.f = regs.f; \ + } + +void +trace_register_changes () +{ + if (!trace) + return; + printf ("\033[36mREGS:"); + TRC (r[0].r_r0, "r0", r0); + TRC (r[0].r_r1, "r1", r1); + TRC (r[0].r_r2, "r2", r2); + TRC (r[0].r_r3, "r3", r3); + TRC (r[0].r_a0, "a0", a0); + TRC (r[0].r_a1, "a1", a1); + TRC (r[0].r_sb, "sb", sb); + TRC (r[0].r_fb, "fb", fb); + TRC (r[1].r_r0, "r0'", r0); + TRC (r[1].r_r1, "r1'", r1); + TRC (r[1].r_r2, "r2'", r2); + TRC (r[1].r_r3, "r3'", r3); + TRC (r[1].r_a0, "a0'", a0); + TRC (r[1].r_a1, "a1'", a1); + TRC (r[1].r_sb, "sb'", sb); + TRC (r[1].r_fb, "fb'", fb); + TRC (r_intbh, "intbh", intbh); + TRC (r_intbl, "intbl", intbl); + TRC (r_usp, "usp", usp); + TRC (r_isp, "isp", isp); + TRC (r_pc, "pc", pc); + TRC (r_flags, "flags", flags); + printf ("\033[0m\n"); +}
reg.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: mem.c =================================================================== --- mem.c (nonexistent) +++ mem.c (revision 33) @@ -0,0 +1,397 @@ +/* mem.c --- memory for M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include + +#include "mem.h" +#include "cpu.h" +#include "syscalls.h" +#include "misc.h" + +#define L1_BITS (10) +#define L2_BITS (10) +#define OFF_BITS (12) + +#define L1_LEN (1 << L1_BITS) +#define L2_LEN (1 << L2_BITS) +#define OFF_LEN (1 << OFF_BITS) + +static unsigned char **pt[L1_LEN]; + +/* [ get=0/put=1 ][ byte size ] */ +static unsigned int mem_counters[2][4]; + +#define COUNT(isput,bytes) \ + if (verbose && enable_counting) mem_counters[isput][bytes]++ + +void +init_mem (void) +{ + int i, j; + + for (i = 0; i < L1_LEN; i++) + if (pt[i]) + { + for (j = 0; j < L2_LEN; j++) + if (pt[i][j]) + free (pt[i][j]); + free (pt[i]); + } + memset (pt, 0, sizeof (pt)); + memset (mem_counters, 0, sizeof (mem_counters)); +} + +static unsigned char * +mem_ptr (address) +{ + int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1); + int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1); + int pto = address & ((1 << OFF_BITS) - 1); + + if (address == 0) + { + printf ("NULL pointer dereference\n"); + exit (1); + } + + if (pt[pt1] == 0) + pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **)); + if (pt[pt1][pt2] == 0) + { + pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN); + memset (pt[pt1][pt2], 0, OFF_LEN); + } + + return pt[pt1][pt2] + pto; +} + +static void +used (int rstart, int i, int j) +{ + int rend = i << (L2_BITS + OFF_BITS); + rend += j << OFF_BITS; + if (rstart == 0xe0000 && rend == 0xe1000) + return; + printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1, + (rend - rstart) / 1024); +} + +static char * +mcs (int isput, int bytes) +{ + return comma (mem_counters[isput][bytes]); +} + +void +mem_usage_stats () +{ + int i, j; + int rstart = 0; + int pending = 0; + + for (i = 0; i < L1_LEN; i++) + if (pt[i]) + { + for (j = 0; j < L2_LEN; j++) + if (pt[i][j]) + { + if (!pending) + { + pending = 1; + rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS); + } + } + else if (pending) + { + pending = 0; + used (rstart, i, j); + } + } + else + { + if (pending) + { + pending = 0; + used (rstart, i, 0); + } + } + /* mem foo: 123456789012 123456789012 123456789012 123456789012 + 123456789012 */ + printf (" byte short pointer long" + " fetch\n"); + printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2), + mcs (0, 3), mcs (0, 4), mcs (0, 0)); + printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2), + mcs (1, 3), mcs (1, 4)); +} + +static int tpr = 0; +static void +s (int address, char *dir) +{ + if (tpr == 0) + printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir); + tpr++; +} + +#define S(d) if (trace) s(address, d) +static void +e () +{ + if (!trace) + return; + tpr--; + if (tpr == 0) + printf ("\n"); +} + +#define E() if (trace) e() + +void +mem_put_byte (int address, unsigned char value) +{ + unsigned char *m; + address &= membus_mask; + m = mem_ptr (address); + if (trace) + printf (" %02x", value); + *m = value; + switch (address) + { + case 0x00e1: + { + static int old_led = -1; + static char *led_on[] = + { "\033[31m O ", "\033[32m O ", "\033[34m O " }; + static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " }; + int i; + if (old_led != value) + { + fputs (" ", stdout); + for (i = 0; i < 3; i++) + if (value & (1 << i)) + fputs (led_off[i], stdout); + else + fputs (led_on[i], stdout); + fputs ("\033[0m\r", stdout); + fflush (stdout); + old_led = value; + } + } + break; + + case 0x3aa: /* uart1tx */ + { + static int pending_exit = 0; + if (value == 0) + { + if (pending_exit) + { + step_result = M32C_MAKE_EXITED(value); + return; + } + pending_exit = 1; + } + else + putchar(value); + } + break; + + case 0x400: + m32c_syscall (value); + break; + + case 0x401: + putchar (value); + break; + + case 0x402: + printf ("SimTrace: %06lx %02x\n", regs.r_pc, value); + break; + + case 0x403: + printf ("SimTrap: %06lx %02x\n", regs.r_pc, value); + abort (); + } +} + +void +mem_put_qi (int address, unsigned char value) +{ + S ("<="); + mem_put_byte (address, value & 0xff); + E (); + COUNT (1, 1); +} + +void +mem_put_hi (int address, unsigned short value) +{ + if (address == 0x402) + { + printf ("SimTrace: %06lx %04x\n", regs.r_pc, value); + return; + } + S ("<="); + mem_put_byte (address, value & 0xff); + mem_put_byte (address + 1, value >> 8); + E (); + COUNT (1, 2); +} + +void +mem_put_psi (int address, unsigned long value) +{ + S ("<="); + mem_put_byte (address, value & 0xff); + mem_put_byte (address + 1, (value >> 8) & 0xff); + mem_put_byte (address + 2, value >> 16); + E (); + COUNT (1, 3); +} + +void +mem_put_si (int address, unsigned long value) +{ + S ("<="); + mem_put_byte (address, value & 0xff); + mem_put_byte (address + 1, (value >> 8) & 0xff); + mem_put_byte (address + 2, (value >> 16) & 0xff); + mem_put_byte (address + 3, (value >> 24) & 0xff); + E (); + COUNT (1, 4); +} + +void +mem_put_blk (int address, void *bufptr, int nbytes) +{ + S ("<="); + if (enable_counting) + mem_counters[1][1] += nbytes; + while (nbytes--) + mem_put_byte (address++, *(unsigned char *) bufptr++); + E (); +} + +unsigned char +mem_get_pc () +{ + unsigned char *m = mem_ptr (regs.r_pc & membus_mask); + COUNT (0, 0); + return *m; +} + +static unsigned char +mem_get_byte (int address) +{ + unsigned char *m; + address &= membus_mask; + S ("=>"); + m = mem_ptr (address); + switch (address) + { + case 0x3ad: /* uart1c1 */ + E(); + return 2; /* transmitter empty */ + break; + default: + if (trace) + printf (" %02x", *m); + break; + } + E (); + return *m; +} + +unsigned char +mem_get_qi (int address) +{ + unsigned char rv; + S ("=>"); + rv = mem_get_byte (address); + COUNT (0, 1); + E (); + return rv; +} + +unsigned short +mem_get_hi (int address) +{ + unsigned short rv; + S ("=>"); + rv = mem_get_byte (address); + rv |= mem_get_byte (address + 1) * 256; + COUNT (0, 2); + E (); + return rv; +} + +unsigned long +mem_get_psi (int address) +{ + unsigned long rv; + S ("=>"); + rv = mem_get_byte (address); + rv |= mem_get_byte (address + 1) * 256; + rv |= mem_get_byte (address + 2) * 65536; + COUNT (0, 3); + E (); + return rv; +} + +unsigned long +mem_get_si (int address) +{ + unsigned long rv; + S ("=>"); + rv = mem_get_byte (address); + rv |= mem_get_byte (address + 1) << 8; + rv |= mem_get_byte (address + 2) << 16; + rv |= mem_get_byte (address + 3) << 24; + COUNT (0, 4); + E (); + return rv; +} + +void +mem_get_blk (int address, void *bufptr, int nbytes) +{ + S ("=>"); + if (enable_counting) + mem_counters[0][1] += nbytes; + while (nbytes--) + *(char *) bufptr++ = mem_get_byte (address++); + E (); +} + +int +sign_ext (int v, int bits) +{ + if (bits < 32) + { + v &= (1 << bits) - 1; + if (v & (1 << (bits - 1))) + v -= (1 << bits); + } + return v; +}
mem.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: load.c =================================================================== --- load.c (nonexistent) +++ load.c (revision 33) @@ -0,0 +1,129 @@ +/* load.c --- loading object files into the M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include + +#include "bfd.h" + +#include "cpu.h" +#include "mem.h" + +int (*decode_opcode) () = 0; +int default_machine = 0; + +void +m32c_set_mach (unsigned long mach) +{ + switch (mach) + { + case bfd_mach_m16c: + m32c_set_cpu (CPU_M16C); + if (verbose) + fprintf (stderr, "[cpu: r8c/m16c]\n"); + break; + case bfd_mach_m32c: + m32c_set_cpu (CPU_M32C); + if (verbose) + fprintf (stderr, "[cpu: m32cm/m32c]\n"); + break; + default: + fprintf (stderr, "unknown m32c machine type 0x%lx\n", mach); + decode_opcode = 0; + break; + } +} + +void +m32c_load (bfd *prog) +{ + asection *s; + unsigned long mach = bfd_get_mach (prog); + unsigned long highest_addr_loaded = 0; + + if (mach == 0 && default_machine != 0) + mach = default_machine; + + m32c_set_mach (mach); + + for (s = prog->sections; s; s = s->next) + { +#if 0 + /* This was a good idea until we started storing the RAM data in + ROM, at which point everything was all messed up. The code + remains as a reminder. */ + if ((s->flags & SEC_ALLOC) && !(s->flags & SEC_READONLY)) + { + if (strcmp (bfd_get_section_name (prog, s), ".stack")) + { + int secend = + bfd_get_section_size (s) + bfd_section_lma (prog, s); + if (heaptop < secend && bfd_section_lma (prog, s) < 0x10000) + { + heaptop = heapbottom = secend; + } + } + } +#endif + if (s->flags & SEC_LOAD) + { + char *buf; + bfd_size_type size; + + size = bfd_get_section_size (s); + if (size <= 0) + continue; + + bfd_vma base = bfd_section_lma (prog, s); + if (verbose) + fprintf (stderr, "[load a=%08x s=%08x %s]\n", + (int) base, (int) size, bfd_get_section_name (prog, s)); + buf = (char *) malloc (size); + bfd_get_section_contents (prog, s, buf, 0, size); + mem_put_blk (base, buf, size); + free (buf); + if (highest_addr_loaded < base + size - 1 && size >= 4) + highest_addr_loaded = base + size - 1; + } + } + + if (strcmp (bfd_get_target (prog), "srec") == 0) + { + heaptop = heapbottom = 0; + switch (mach) + { + case bfd_mach_m16c: + if (highest_addr_loaded > 0x10000) + regs.r_pc = mem_get_si (0x000ffffc) & membus_mask; + else + regs.r_pc = mem_get_si (0x000fffc) & membus_mask; + break; + case bfd_mach_m32c: + regs.r_pc = mem_get_si (0x00fffffc) & membus_mask; + break; + } + } + else + regs.r_pc = prog->start_address; + if (verbose) + fprintf (stderr, "[start pc=%08x]\n", (unsigned int) regs.r_pc); +}
load.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: syscall.h =================================================================== --- syscall.h (nonexistent) +++ syscall.h (revision 33) @@ -0,0 +1,50 @@ +/* Copied from libgloss */ +/* General use syscall.h file. + The more ports that use this file, the simpler sim/common/nltvals.def + remains. */ + +#ifndef LIBGLOSS_SYSCALL_H +#define LIBGLOSS_SYSCALL_H + +/* Note: This file may be included by assembler source. */ + +/* These should be as small as possible to allow a port to use a trap type + instruction, which the system call # as the trap (the d10v for instance + supports traps 0..31). An alternative would be to define one trap for doing + system calls, and put the system call number in a register that is not used + for the normal calling sequence (so that you don't have to shift down the + arguments to add the system call number). Obviously, if these system call + numbers are ever changed, all of the simulators and potentially user code + will need to be updated. */ + +/* There is no current need for the following: SYS_execv, SYS_creat, SYS_wait, + etc. etc. Don't add them. */ + +/* These are required by the ANSI C part of newlib (excluding system() of + course). */ +#define SYS_exit 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_read 4 +#define SYS_write 5 +#define SYS_lseek 6 +#define SYS_unlink 7 +#define SYS_getpid 8 +#define SYS_kill 9 +#define SYS_fstat 10 +/*#define SYS_sbrk 11 - not currently a system call, but reserved. */ + +/* ARGV support. */ +#define SYS_argvlen 12 +#define SYS_argv 13 + +/* These are extras added for one reason or another. */ +#define SYS_chdir 14 +#define SYS_stat 15 +#define SYS_chmod 16 +#define SYS_utime 17 +#define SYS_time 18 +#define SYS_gettimeofday 19 +#define SYS_times 20 +#define SYS_link 21 +#endif
syscall.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: mem.h =================================================================== --- mem.h (nonexistent) +++ mem.h (revision 33) @@ -0,0 +1,41 @@ +/* mem.h --- interface to memory for M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +void init_mem (void); +void mem_usage_stats (void); + +void mem_put_qi (int address, unsigned char value); +void mem_put_hi (int address, unsigned short value); +void mem_put_psi (int address, unsigned long value); +void mem_put_si (int address, unsigned long value); + +void mem_put_blk (int address, void *bufptr, int nbytes); + +unsigned char mem_get_pc (); + +unsigned char mem_get_qi (int address); +unsigned short mem_get_hi (int address); +unsigned long mem_get_psi (int address); +unsigned long mem_get_si (int address); + +void mem_get_blk (int address, void *bufptr, int nbytes); + +int sign_ext (int v, int bits);
mem.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: main.c =================================================================== --- main.c (nonexistent) +++ main.c (revision 33) @@ -0,0 +1,136 @@ +/* main.c --- main function for stand-alone M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "bfd.h" + +#include "cpu.h" +#include "mem.h" +#include "misc.h" +#include "load.h" +#include "trace.h" + +static int disassemble = 0; +static unsigned int cycles = 0; + +static void +done (int exit_code) +{ + if (verbose) + { + stack_heap_stats (); + mem_usage_stats (); + printf ("insns: %14s\n", comma (cycles)); + } + exit (exit_code); +} + +int +main (int argc, char **argv) +{ + int o; + int save_trace; + bfd *prog; + + while ((o = getopt (argc, argv, "tvdm:")) != -1) + switch (o) + { + case 't': + trace++; + break; + case 'v': + verbose++; + break; + case 'd': + disassemble++; + break; + case 'm': + if (strcmp (optarg, "r8c") == 0 || strcmp (optarg, "m16c") == 0) + default_machine = bfd_mach_m16c; + else if (strcmp (optarg, "m32cm") == 0 + || strcmp (optarg, "m32c") == 0) + default_machine = bfd_mach_m32c; + else + { + fprintf (stderr, "Invalid machine: %s\n", optarg); + exit (1); + } + break; + case '?': + fprintf (stderr, + "usage: run [-v] [-t] [-d] [-m r8c|m16c|m32cm|m32c]" + " program\n"); + exit (1); + } + + prog = bfd_openr (argv[optind], 0); + if (!prog) + { + fprintf (stderr, "Can't read %s\n", argv[optind]); + exit (1); + } + + if (!bfd_check_format (prog, bfd_object)) + { + fprintf (stderr, "%s not a m32c program\n", argv[optind]); + exit (1); + } + + save_trace = trace; + trace = 0; + m32c_load (prog); + trace = save_trace; + + if (disassemble) + sim_disasm_init (prog); + + while (1) + { + int rc; + + if (trace) + printf ("\n"); + + if (disassemble) + sim_disasm_one (); + + enable_counting = verbose; + cycles++; + rc = decode_opcode (); + enable_counting = 0; + + if (M32C_HIT_BREAK (rc)) + done (1); + else if (M32C_EXITED (rc)) + done (M32C_EXIT_STATUS (rc)); + else + assert (M32C_STEPPED (rc)); + + trace_register_changes (); + } +}
main.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: load.h =================================================================== --- load.h (nonexistent) +++ load.h (revision 33) @@ -0,0 +1,27 @@ +/* load.h --- interface to loading object files into the M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include "bfd.h" + +extern int default_machine; + +void m32c_set_mach (int mach); +void m32c_load (bfd *);
load.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: safe-fgets.c =================================================================== --- safe-fgets.c (nonexistent) +++ safe-fgets.c (revision 33) @@ -0,0 +1,69 @@ +/* safe-fgets.c --- like fgets, but allocates its own static buffer. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include + +#include "safe-fgets.h" + +static char *line_buf = 0; +static int line_buf_size = 0; + +#define LBUFINCR 100 + +char * +safe_fgets (FILE *f) +{ + char *line_ptr; + + if (line_buf == 0) + { + line_buf = (char *) malloc (LBUFINCR); + line_buf_size = LBUFINCR; + } + + /* points to last byte */ + line_ptr = line_buf + line_buf_size - 1; + + /* so we can see if fgets put a 0 there */ + *line_ptr = 1; + if (fgets (line_buf, line_buf_size, f) == 0) + return 0; + + /* we filled the buffer? */ + while (line_ptr[0] == 0 && line_ptr[-1] != '\n') + { + /* Make the buffer bigger and read more of the line */ + line_buf_size += LBUFINCR; + line_buf = (char *) realloc (line_buf, line_buf_size); + + /* points to last byte again */ + line_ptr = line_buf + line_buf_size - 1; + /* so we can see if fgets put a 0 there */ + *line_ptr = 1; + + if (fgets (line_buf + line_buf_size - LBUFINCR - 1, LBUFINCR + 1, f) == + 0) + return 0; + } + + return line_buf; +}
safe-fgets.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: gdb-if.c =================================================================== --- gdb-if.c (nonexistent) +++ gdb-if.c (revision 33) @@ -0,0 +1,708 @@ +/* gdb.c --- sim interface to GDB. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include +#include +#include + +#include "ansidecl.h" +#include "gdb/callback.h" +#include "gdb/remote-sim.h" +#include "gdb/signals.h" +#include "gdb/sim-m32c.h" + +#include "cpu.h" +#include "mem.h" +#include "load.h" +#include "syscalls.h" + +/* I don't want to wrap up all the minisim's data structures in an + object and pass that around. That'd be a big change, and neither + GDB nor run needs that ability. + + So we just have one instance, that lives in global variables, and + each time we open it, we re-initialize it. */ +struct sim_state +{ + const char *message; +}; + +static struct sim_state the_minisim = { + "This is the sole m32c minisim instance. See libsim.a's global variables." +}; + +static int open; + +SIM_DESC +sim_open (SIM_OPEN_KIND kind, + struct host_callback_struct *callback, + struct bfd *abfd, char **argv) +{ + if (open) + fprintf (stderr, "m32c minisim: re-opened sim\n"); + + /* The 'run' interface doesn't use this function, so we don't care + about KIND; it's always SIM_OPEN_DEBUG. */ + if (kind != SIM_OPEN_DEBUG) + fprintf (stderr, "m32c minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n", + kind); + + if (abfd) + m32c_set_mach (bfd_get_mach (abfd)); + + /* We can use ABFD, if non-NULL to select the appropriate + architecture. But we only support the r8c right now. */ + + set_callbacks (callback); + + /* We don't expect any command-line arguments. */ + + init_mem (); + init_regs (); + + open = 1; + return &the_minisim; +} + +static void +check_desc (SIM_DESC sd) +{ + if (sd != &the_minisim) + fprintf (stderr, "m32c minisim: desc != &the_minisim\n"); +} + +void +sim_close (SIM_DESC sd, int quitting) +{ + check_desc (sd); + + /* Not much to do. At least free up our memory. */ + init_mem (); + + open = 0; +} + +static bfd * +open_objfile (const char *filename) +{ + bfd *prog = bfd_openr (filename, 0); + + if (!prog) + { + fprintf (stderr, "Can't read %s\n", filename); + return 0; + } + + if (!bfd_check_format (prog, bfd_object)) + { + fprintf (stderr, "%s not a m32c program\n", filename); + return 0; + } + + return prog; +} + + +SIM_RC +sim_load (SIM_DESC sd, char *prog, struct bfd *abfd, int from_tty) +{ + check_desc (sd); + + if (!abfd) + abfd = open_objfile (prog); + if (!abfd) + return SIM_RC_FAIL; + + m32c_load (abfd); + + return SIM_RC_OK; +} + +SIM_RC +sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env) +{ + check_desc (sd); + + if (abfd) + m32c_load (abfd); + + return SIM_RC_OK; +} + +int +sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) +{ + check_desc (sd); + + if (mem == 0) + return 0; + + mem_get_blk ((int) mem, buf, length); + + return length; +} + +int +sim_write (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) +{ + check_desc (sd); + + mem_put_blk ((int) mem, buf, length); + + return length; +} + + +/* Read the LENGTH bytes at BUF as an little-endian value. */ +static DI +get_le (unsigned char *buf, int length) +{ + DI acc = 0; + while (--length >= 0) + acc = (acc << 8) + buf[length]; + + return acc; +} + +/* Store VAL as a little-endian value in the LENGTH bytes at BUF. */ +static void +put_le (unsigned char *buf, int length, DI val) +{ + int i; + + for (i = 0; i < length; i++) + { + buf[i] = val & 0xff; + val >>= 8; + } +} + +static int +check_regno (enum m32c_sim_reg regno) +{ + return 0 <= regno && regno < m32c_sim_reg_num_regs; +} + +static size_t +mask_size (int addr_mask) +{ + switch (addr_mask) + { + case 0xffff: + return 2; + case 0xfffff: + case 0xffffff: + return 3; + default: + fprintf (stderr, + "m32c minisim: addr_mask_size: unexpected mask 0x%x\n", + addr_mask); + return sizeof (addr_mask); + } +} + +static size_t +reg_size (enum m32c_sim_reg regno) +{ + switch (regno) + { + case m32c_sim_reg_r0_bank0: + case m32c_sim_reg_r1_bank0: + case m32c_sim_reg_r2_bank0: + case m32c_sim_reg_r3_bank0: + case m32c_sim_reg_r0_bank1: + case m32c_sim_reg_r1_bank1: + case m32c_sim_reg_r2_bank1: + case m32c_sim_reg_r3_bank1: + case m32c_sim_reg_flg: + case m32c_sim_reg_svf: + return 2; + + case m32c_sim_reg_a0_bank0: + case m32c_sim_reg_a1_bank0: + case m32c_sim_reg_fb_bank0: + case m32c_sim_reg_sb_bank0: + case m32c_sim_reg_a0_bank1: + case m32c_sim_reg_a1_bank1: + case m32c_sim_reg_fb_bank1: + case m32c_sim_reg_sb_bank1: + case m32c_sim_reg_usp: + case m32c_sim_reg_isp: + return mask_size (addr_mask); + + case m32c_sim_reg_pc: + case m32c_sim_reg_intb: + case m32c_sim_reg_svp: + case m32c_sim_reg_vct: + return mask_size (membus_mask); + + case m32c_sim_reg_dmd0: + case m32c_sim_reg_dmd1: + return 1; + + case m32c_sim_reg_dct0: + case m32c_sim_reg_dct1: + case m32c_sim_reg_drc0: + case m32c_sim_reg_drc1: + return 2; + + case m32c_sim_reg_dma0: + case m32c_sim_reg_dma1: + case m32c_sim_reg_dsa0: + case m32c_sim_reg_dsa1: + case m32c_sim_reg_dra0: + case m32c_sim_reg_dra1: + return 3; + + default: + fprintf (stderr, "m32c minisim: unrecognized register number: %d\n", + regno); + return -1; + } +} + +int +sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) +{ + size_t size; + + check_desc (sd); + + if (!check_regno (regno)) + return 0; + + size = reg_size (regno); + if (length == size) + { + DI val; + + switch (regno) + { + case m32c_sim_reg_r0_bank0: + val = regs.r[0].r_r0; + break; + case m32c_sim_reg_r1_bank0: + val = regs.r[0].r_r1; + break; + case m32c_sim_reg_r2_bank0: + val = regs.r[0].r_r2; + break; + case m32c_sim_reg_r3_bank0: + val = regs.r[0].r_r3; + break; + case m32c_sim_reg_a0_bank0: + val = regs.r[0].r_a0; + break; + case m32c_sim_reg_a1_bank0: + val = regs.r[0].r_a1; + break; + case m32c_sim_reg_fb_bank0: + val = regs.r[0].r_fb; + break; + case m32c_sim_reg_sb_bank0: + val = regs.r[0].r_sb; + break; + case m32c_sim_reg_r0_bank1: + val = regs.r[1].r_r0; + break; + case m32c_sim_reg_r1_bank1: + val = regs.r[1].r_r1; + break; + case m32c_sim_reg_r2_bank1: + val = regs.r[1].r_r2; + break; + case m32c_sim_reg_r3_bank1: + val = regs.r[1].r_r3; + break; + case m32c_sim_reg_a0_bank1: + val = regs.r[1].r_a0; + break; + case m32c_sim_reg_a1_bank1: + val = regs.r[1].r_a1; + break; + case m32c_sim_reg_fb_bank1: + val = regs.r[1].r_fb; + break; + case m32c_sim_reg_sb_bank1: + val = regs.r[1].r_sb; + break; + + case m32c_sim_reg_usp: + val = regs.r_usp; + break; + case m32c_sim_reg_isp: + val = regs.r_isp; + break; + case m32c_sim_reg_pc: + val = regs.r_pc; + break; + case m32c_sim_reg_intb: + val = regs.r_intbl * 65536 + regs.r_intbl; + break; + case m32c_sim_reg_flg: + val = regs.r_flags; + break; + + /* These registers aren't implemented by the minisim. */ + case m32c_sim_reg_svf: + case m32c_sim_reg_svp: + case m32c_sim_reg_vct: + case m32c_sim_reg_dmd0: + case m32c_sim_reg_dmd1: + case m32c_sim_reg_dct0: + case m32c_sim_reg_dct1: + case m32c_sim_reg_drc0: + case m32c_sim_reg_drc1: + case m32c_sim_reg_dma0: + case m32c_sim_reg_dma1: + case m32c_sim_reg_dsa0: + case m32c_sim_reg_dsa1: + case m32c_sim_reg_dra0: + case m32c_sim_reg_dra1: + return 0; + + default: + fprintf (stderr, "m32c minisim: unrecognized register number: %d\n", + regno); + return -1; + } + + put_le (buf, length, val); + } + + return size; +} + +int +sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length) +{ + size_t size; + + check_desc (sd); + + if (!check_regno (regno)) + return 0; + + size = reg_size (regno); + + if (length == size) + { + DI val = get_le (buf, length); + + switch (regno) + { + case m32c_sim_reg_r0_bank0: + regs.r[0].r_r0 = val & 0xffff; + break; + case m32c_sim_reg_r1_bank0: + regs.r[0].r_r1 = val & 0xffff; + break; + case m32c_sim_reg_r2_bank0: + regs.r[0].r_r2 = val & 0xffff; + break; + case m32c_sim_reg_r3_bank0: + regs.r[0].r_r3 = val & 0xffff; + break; + case m32c_sim_reg_a0_bank0: + regs.r[0].r_a0 = val & addr_mask; + break; + case m32c_sim_reg_a1_bank0: + regs.r[0].r_a1 = val & addr_mask; + break; + case m32c_sim_reg_fb_bank0: + regs.r[0].r_fb = val & addr_mask; + break; + case m32c_sim_reg_sb_bank0: + regs.r[0].r_sb = val & addr_mask; + break; + case m32c_sim_reg_r0_bank1: + regs.r[1].r_r0 = val & 0xffff; + break; + case m32c_sim_reg_r1_bank1: + regs.r[1].r_r1 = val & 0xffff; + break; + case m32c_sim_reg_r2_bank1: + regs.r[1].r_r2 = val & 0xffff; + break; + case m32c_sim_reg_r3_bank1: + regs.r[1].r_r3 = val & 0xffff; + break; + case m32c_sim_reg_a0_bank1: + regs.r[1].r_a0 = val & addr_mask; + break; + case m32c_sim_reg_a1_bank1: + regs.r[1].r_a1 = val & addr_mask; + break; + case m32c_sim_reg_fb_bank1: + regs.r[1].r_fb = val & addr_mask; + break; + case m32c_sim_reg_sb_bank1: + regs.r[1].r_sb = val & addr_mask; + break; + + case m32c_sim_reg_usp: + regs.r_usp = val & addr_mask; + break; + case m32c_sim_reg_isp: + regs.r_isp = val & addr_mask; + break; + case m32c_sim_reg_pc: + regs.r_pc = val & membus_mask; + break; + case m32c_sim_reg_intb: + regs.r_intbl = (val & membus_mask) & 0xffff; + regs.r_intbh = (val & membus_mask) >> 16; + break; + case m32c_sim_reg_flg: + regs.r_flags = val & 0xffff; + break; + + /* These registers aren't implemented by the minisim. */ + case m32c_sim_reg_svf: + case m32c_sim_reg_svp: + case m32c_sim_reg_vct: + case m32c_sim_reg_dmd0: + case m32c_sim_reg_dmd1: + case m32c_sim_reg_dct0: + case m32c_sim_reg_dct1: + case m32c_sim_reg_drc0: + case m32c_sim_reg_drc1: + case m32c_sim_reg_dma0: + case m32c_sim_reg_dma1: + case m32c_sim_reg_dsa0: + case m32c_sim_reg_dsa1: + case m32c_sim_reg_dra0: + case m32c_sim_reg_dra1: + return 0; + + default: + fprintf (stderr, "m32c minisim: unrecognized register number: %d\n", + regno); + return -1; + } + } + + return size; +} + +void +sim_info (SIM_DESC sd, int verbose) +{ + check_desc (sd); + + printf ("The m32c minisim doesn't collect any statistics.\n"); +} + +static volatile int stop; +static enum sim_stop reason; +int siggnal; + + +/* Given a signal number used by the M32C bsp (that is, newlib), + return a host signal number. (Oddly, the gdb/sim interface uses + host signal numbers...) */ +int +m32c_signal_to_host (int m32c) +{ + switch (m32c) + { + case 4: +#ifdef SIGILL + return SIGILL; +#else + return SIGSEGV; +#endif + + case 5: + return SIGTRAP; + + case 10: +#ifdef SIGBUS + return SIGBUS; +#else + return SIGSEGV; +#endif + + case 11: + return SIGSEGV; + + case 24: +#ifdef SIGXCPU + return SIGXCPU; +#else + break; +#endif + + case 2: + return SIGINT; + + case 8: +#ifdef SIGFPE + return SIGFPE; +#else + break; +#endif + + case 6: + return SIGABRT; + } + + return 0; +} + + +/* Take a step return code RC and set up the variables consulted by + sim_stop_reason appropriately. */ +void +handle_step (int rc) +{ + if (M32C_STEPPED (rc) || M32C_HIT_BREAK (rc)) + { + reason = sim_stopped; + siggnal = TARGET_SIGNAL_TRAP; + } + else if (M32C_STOPPED (rc)) + { + reason = sim_stopped; + siggnal = m32c_signal_to_host (M32C_STOP_SIG (rc)); + } + else + { + assert (M32C_EXITED (rc)); + reason = sim_exited; + siggnal = M32C_EXIT_STATUS (rc); + } +} + + +void +sim_resume (SIM_DESC sd, int step, int sig_to_deliver) +{ + check_desc (sd); + + if (sig_to_deliver != 0) + { + fprintf (stderr, + "Warning: the m32c minisim does not implement " + "signal delivery yet.\n" "Resuming with no signal.\n"); + } + + if (step) + handle_step (decode_opcode ()); + else + { + /* We don't clear 'stop' here, because then we would miss + interrupts that arrived on the way here. Instead, we clear + the flag in sim_stop_reason, after GDB has disabled the + interrupt signal handler. */ + for (;;) + { + if (stop) + { + stop = 0; + reason = sim_stopped; + siggnal = TARGET_SIGNAL_INT; + break; + } + + int rc = decode_opcode (); + + if (!M32C_STEPPED (rc)) + { + handle_step (rc); + break; + } + } + } +} + +int +sim_stop (SIM_DESC sd) +{ + stop = 1; + + return 1; +} + +void +sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p) +{ + check_desc (sd); + + *reason_p = reason; + *sigrc_p = siggnal; +} + +void +sim_do_command (SIM_DESC sd, char *cmd) +{ + check_desc (sd); + + char *p = cmd; + + /* Skip leading whitespace. */ + while (isspace (*p)) + p++; + + /* Find the extent of the command word. */ + for (p = cmd; *p; p++) + if (isspace (*p)) + break; + + /* Null-terminate the command word, and record the start of any + further arguments. */ + char *args; + if (*p) + { + *p = '\0'; + args = p + 1; + while (isspace (*args)) + args++; + } + else + args = p; + + if (strcmp (cmd, "trace") == 0) + { + if (strcmp (args, "on") == 0) + trace = 1; + else if (strcmp (args, "off") == 0) + trace = 0; + else + printf ("The 'sim trace' command expects 'on' or 'off' " + "as an argument.\n"); + } + else if (strcmp (cmd, "verbose") == 0) + { + if (strcmp (args, "on") == 0) + verbose = 1; + else if (strcmp (args, "off") == 0) + verbose = 0; + else + printf ("The 'sim verbose' command expects 'on' or 'off'" + " as an argument.\n"); + } + else + printf ("The 'sim' command expects either 'trace' or 'verbose'" + " as a subcommand.\n"); +}
gdb-if.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: config.in =================================================================== Index: safe-fgets.h =================================================================== --- safe-fgets.h (nonexistent) +++ safe-fgets.h (revision 33) @@ -0,0 +1,27 @@ +/* safe-fgets.h --- interface to safe version of fgets. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#ifndef _safe_gets_h_ +#define _safe_gets_h_ + +char *safe_fgets (FILE *f); + +#endif
safe-fgets.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: int.c =================================================================== --- int.c (nonexistent) +++ int.c (revision 33) @@ -0,0 +1,59 @@ +/* int.c --- M32C interrupt handling. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include "int.h" +#include "cpu.h" +#include "mem.h" + +void +trigger_fixed_interrupt (int addr) +{ + int s = get_reg (sp); + int f = get_reg (flags); + int p = get_reg (pc); + + if (A16) + { + s -= 4; + put_reg (sp, s); + mem_put_hi (s, p); + mem_put_qi (s + 2, f); + mem_put_qi (s + 3, ((f >> 4) & 0x0f) | (p >> 16)); + } + else + { + s -= 6; + put_reg (sp, s); + mem_put_si (s, p); + mem_put_hi (s + 4, f); + } + put_reg (pc, mem_get_psi (addr)); + set_flags (FLAGBIT_U | FLAGBIT_I | FLAGBIT_D, 0); +} + +void +trigger_based_interrupt (int vector) +{ + int addr = get_reg (intb) + vector * 4; + if (vector <= 31) + set_flags (FLAGBIT_U, 0); + trigger_fixed_interrupt (addr); +}
int.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: misc.c =================================================================== --- misc.c (nonexistent) +++ misc.c (revision 33) @@ -0,0 +1,77 @@ +/* misc.c --- miscellaneous utility functions for M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include + +#include "cpu.h" +#include "misc.h" + +int +bcd2int (int bcd, int w) +{ + int v = 0, m = 1, i; + for (i = 0; i < (w ? 4 : 2); i++) + { + v += (bcd % 16) * m; + m *= 10; + bcd /= 16; + } + return v; +} + +int +int2bcd (int v, int w) +{ + int bcd = 0, m = 1, i; + for (i = 0; i < (w ? 4 : 2); i++) + { + bcd += (v % 10) * m; + m *= 16; + v /= 10; + } + return bcd; +} + +char * +comma (unsigned int u) +{ + static char buf[5][20]; + static int bi = 0; + int comma = 0; + char *bp; + + bi = (bi + 1) % 5; + bp = buf[bi] + 19; + *--bp = 0; + do + { + if (comma == 3) + { + *--bp = ','; + comma = 0; + } + comma++; + *--bp = '0' + (u % 10); + u /= 10; + } + while (u); + return bp; +}
misc.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: r8c.opc =================================================================== --- r8c.opc (nonexistent) +++ r8c.opc (revision 33) @@ -0,0 +1,1593 @@ +/* r8c.opc --- semantics for r8c opcodes. -*- mode: c -*- + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include + +#include "cpu.h" +#include "mem.h" +#include "misc.h" +#include "int.h" + +#define AU __attribute__((unused)) + +#define tprintf if (trace) printf + +static unsigned char +getbyte () +{ + int tsave = trace; + unsigned char b; + + if (trace == 1) + trace = 0; + b = mem_get_pc (); + regs.r_pc ++; + trace = tsave; + return b; +} + +#define M16C_ONLY() /* FIXME: add something here */ + +#define GETBYTE() (op[opi++] = getbyte()) + +#define UNSUPPORTED() unsupported("unsupported", orig_pc) +#define NOTYET() unsupported("unimplemented", orig_pc) + +static void +unsupported (char *tag, int orig_pc) +{ + int i; + printf("%s opcode at %08x\n", tag, orig_pc); + regs.r_pc = orig_pc; + for (i=0; i<2; i++) + { + int b = mem_get_pc(); + printf(" %s", bits(b>>4, 4)); + printf(" %s", bits(b, 4)); + regs.r_pc ++; + } + printf("\n"); + regs.r_pc = orig_pc; + for (i=0; i<6; i++) + { + printf(" %02x", mem_get_pc ()); + regs.r_pc ++; + } + printf("\n"); + exit(1); +} + +static int +IMM(bw) +{ + int rv = getbyte (); + if (bw) + rv = rv + 256 * getbyte(); + if (bw == 2) + rv = rv + 65536 * getbyte(); + return rv; +} + +#define IMM4() (immm >= 8 ? 7 - immm : immm + 1) + +#define UNARY_SOP \ + dc = decode_srcdest4 (dest, w); \ + v = sign_ext (get_src (dc), w?16:8); + +#define UNARY_UOP \ + dc = decode_srcdest4 (dest, w); \ + v = get_src (dc); + +#define BINARY_SOP \ + sc = decode_srcdest4 (srcx, w); \ + dc = decode_srcdest4 (dest, w); \ + a = sign_ext (get_src (sc), w?16:8); \ + b = sign_ext (get_src (dc), w?16:8); + +#define BINARY_UOP \ + sc = decode_srcdest4 (srcx, w); \ + dc = decode_srcdest4 (dest, w); \ + a = get_src (sc); \ + b = get_src (dc); + +#define carry (FLAG_C ? 1 : 0) + +static void +cmp (int d, int s, int w) +{ + int a, b, f=0; + int mask = w ? 0xffff : 0xff; + a = d - s; + b = sign_ext (d, w?16:8) - sign_ext (s, w?16:8); + tprintf ("cmp: %x - %x = %08x, %x - %x = %d\n", + d, s, a, + sign_ext(d,w?16:8), sign_ext(s,w?16:8), b); + + if (b == 0) + f |= FLAGBIT_Z; + if (b & (w ? 0x8000 : 0x80)) + f |= FLAGBIT_S; + if ((d & mask) >= (s & mask)) + f |= FLAGBIT_C; + if (b < (w ? -32768 : -128) || b > (w ? 32767 : 127)) + f |= FLAGBIT_O; + + set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f); +} + +static void +div_op (int s, int u, int x, int w) +{ + srcdest sc; + int v, a, b; + + if (s == -1) + s = IMM(w); + else + { + sc = decode_srcdest4 (s, w); + s = get_src (sc); + } + + v = get_reg (w ? r2r0 : r0); + + if (!u) + { + s = sign_ext (s, w ? 16 : 8); + v = sign_ext (v, w ? 16 : 8); + } + + if (s == 0) + { + set_flags (FLAGBIT_O, FLAGBIT_O); + return; + } + + if (u) + { + a = (unsigned int)v / (unsigned int)s; + b = (unsigned int)v % (unsigned int)s; + } + else + { + a = v / s; + b = v % s; + } + if (x) + { + if ((s > 0 && b < 0) + || (s < 0 && b > 0)) + { + a --; + b += s; + } + } + tprintf ("%d / %d = %d rem %d\n", v, s, a, b); + if ((!u && (a > (w ? 32767 : 127) + || a < (w ? -32768 : -129))) + || (u && (a > (w ? 65536 : 255)))) + set_flags (FLAGBIT_O, FLAGBIT_O); + else + set_flags (FLAGBIT_O, 0); + + put_reg (w ? r0 : r0l, a); + put_reg (w ? r2 : r0h, b); +} + +static void +rot_op (srcdest sd, int rotc, int count) +{ + int mask = (sd.bytes == 2) ? 0xffff : 0xff; + int msb = (sd.bytes == 2) ? 0x8000 : 0x80; + int v = get_src (sd); + int c = carry, ct; + + tprintf("%s %x by %d\n", rotc ? "rotc" : "rot", v, count); + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + while (count > 0) + { + ct = (v & msb) ? 1 : 0; + v <<= 1; + v |= rotc ? c : ct; + v &= mask; + c = ct; + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count --; + } + while (count < 0) + { + ct = v & 1; + v >>= 1; + v |= (rotc ? c : ct) * msb; + c = ct; + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count ++; + } + put_dest (sd, v); + set_szc (v, sd.bytes, c); +} + +static void +shift_op (srcdest sd, int arith, int count) +{ + int mask = (sd.bytes == 2) ? 0xffff : 0xff; + int msb = (sd.bytes == 2) ? 0x8000 : 0x80; + int v = get_src (sd); + int c = 0; + + if (sd.bytes == 4) + { + mask = 0xffffffffU; + msb = 0x80000000U; + if (count > 16 || count < -16) + { + fprintf(stderr, "Error: SI shift of %d undefined\n", count); + exit(1); + } + if (count > 16) + count = (count - 1) % 16 + 1; + if (count < -16) + count = -((-count - 1) % 16 + 1); + } + + tprintf("%s %x by %d\n", arith ? "sha" : "shl", v, count); + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + while (count > 0) + { + c = (v & msb) ? 1 : 0; + v <<= 1; + v &= mask; + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count --; + } + while (count < 0) + { + c = v & 1; + if (arith) + v = (v & msb) | (v >> 1); + else + v = (v >> 1) & (msb - 1); + tprintf (": %s %d\n", bits(v, 8*sd.bytes), c); + count ++; + } + put_dest (sd, v); + set_szc (v, sd.bytes, c); +} + +#define MATH_OP(dc,s,c,op,carryrel) \ + a = get_src(dc); \ + b = s & b2mask[dc.bytes]; \ + v2 = a op b op c; \ + tprintf("0x%x " #op " 0x%x " #op " 0x%x = 0x%x\n", a, b, c, v2); \ + a = sign_ext (a, dc.bytes * 8); \ + b = sign_ext (s, dc.bytes * 8); \ + v = a op b op c; \ + tprintf("%d " #op " %d " #op " %d = %d\n", a, b, c, v); \ + set_oszc (v, dc.bytes, v2 carryrel); \ + put_dest (dc, v2); + +#define BIT_OP(field,expr) \ + dc = decode_bit (field); \ + b = get_bit (dc); \ + v = expr; \ + tprintf ("b=%d, carry=%d, %s = %d\n", b, carry, #expr, v); \ + put_bit (dc, v); + +#define BIT_OPC(field,expr) \ + dc = decode_bit (field); \ + b = get_bit (dc); \ + v = expr; \ + tprintf ("b=%d, carry=%d, %s = %d\n", b, carry, #expr, v); \ + set_c (v); + +/* The "BMcnd dest" opcode uses a different encoding for the */ +/* condition than other opcodes. */ +static int bmcnd_cond_map[] = { + 0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15 +}; + +int +decode_r8c() +{ + unsigned char op[40]; + int opi = 0; + int v, v2, a, b; + int orig_pc = get_reg (pc); + srcdest sc, dc; + int imm; + + step_result = M32C_MAKE_STEPPED (); + + tprintf("trace: decode pc = %05x\n", orig_pc); + + /** VARY dst 011 100 101 110 111 */ + + /** 0111 011w 1111 dest ABS.size dest */ + + UNARY_SOP; + a = v<0 ? -v : v; + tprintf("abs(%d) = %d\n", v, a); + set_osz(a, w+1); + put_dest (dc, a); + + /** 0111 011w 0110 dest ADC.size #IMM,dest */ + + dc = decode_srcdest4(dest, w); + imm = IMM(w); + MATH_OP (dc, imm, carry, +, > (w?0xffff:0xff)); + + /** 1011 000w srcx dest ADC.size src,dest */ + + sc = decode_srcdest4(srcx, w); + dc = decode_srcdest4(dest, w); + b = get_src (sc); + MATH_OP (dc, b, carry, +, > (w?0xffff:0xff)); + + /** 0111 011w 1110 dest ADCF.size dest */ + + dc = decode_srcdest4(dest, w); + MATH_OP (dc, 0, carry, +, > (w?0xffff:0xff)); + + /** 0111 011w 0100 dest ADD.size:G #imm,dest */ + + dc = decode_srcdest4(dest, w); + imm = IMM(w); + MATH_OP (dc, imm, 0, +, > (w?0xffff:0xff)); + + /** 1100 100w immm dest ADD.size:Q #IMM,dest */ + + dc = decode_srcdest4(dest, w); + imm = sign_ext (immm, 4); + MATH_OP (dc, imm, 0, +, > (w?0xffff:0xff)); + + /** 1000 0dst ADD.B:S #IMM8,dst */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + MATH_OP (dc, imm, 0, +, > 0xff); + + /** 1010 000w srcx dest ADD.size:G src,dest */ + + sc = decode_srcdest4(srcx, w); + dc = decode_srcdest4(dest, w); + b = get_src (sc); + MATH_OP (dc, b, 0, +, > (w?0xffff:0xff)); + + /** 0010 0d sr ADD.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + dc = decode_dest1 (d, 0); + b = get_src (sc); + MATH_OP (dc, b, 0, +, > 0xff); + + /** 0111 110w 1110 1011 ADD.size:G #IMM,sp */ + + dc = reg_sd (sp); + imm = sign_ext (IMM(w), w?16:8); + MATH_OP (dc, imm, 0, +, > 0xffff); + + /** 0111 1101 1011 immm ADD.size:Q #IMM,sp */ + + dc = reg_sd (sp); + imm = sign_ext (immm, 4); + MATH_OP (dc, imm, 0, +, > 0xffff); + + /** 1111 100w immm dest ADJNZ.size #IMM,dest,label */ + + UNARY_UOP; + imm = sign_ext(immm, 4); + tprintf("%x + %d = %x\n", v, imm, v+imm); + v += imm; + put_dest (dc, v); + a = sign_ext (IMM(0), 8); + if ((v & (w ? 0xffff : 0xff)) != 0) + { + tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a); + put_reg (pc, orig_pc + 2 + a); + tprintf("%x\n", get_reg (pc)); + } + + /** 0111 011w 0010 dest AND.size:G #IMM,dest */ + + UNARY_UOP; + imm = IMM(w); + tprintf ("%x & %x = %x\n", v, imm, v & imm); + v &= imm; + set_sz (v, w+1); + put_dest (dc, v); + + /** 1001 0dst AND.B:S #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + v = get_src (dc); + tprintf("%x & %x = %x\n", v, imm, v & imm); + v &= imm; + set_sz (v, 1); + put_dest (dc, v); + + /** 1001 000w srcx dest AND.size:G src.dest */ + + BINARY_UOP; + tprintf ("%x & %x = %x\n", a, b, a & b); + v = a & b; + set_sz (v, w+1); + put_dest (dc, v); + + /** 0001 0d sr AND.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + dc = decode_dest1 (d, 0); + a = get_src (sc); + b = get_src (dc); + v = a & b; + tprintf("%x & %x = %x\n", a, b, v); + set_sz (v, 1); + put_dest (dc, v); + + /** 0111 1110 0100 srcx BAND src */ + + BIT_OPC (srcx, b & carry); + + /** 0111 1110 1000 dest BCLR:G dest */ + + dc = decode_bit (dest); + put_bit (dc, 0); + + /** 0100 0bit BCLR:S bit,base:11[SB] */ + + dc = decode_bit11 (bit); + put_bit (dc, 0); + + /** 0111 1110 0010 dest BMcnd dest */ + + dc = decode_bit (dest); + if (condition_true (bmcnd_cond_map [IMM (0) & 15])) + put_bit (dc, 1); + else + put_bit (dc, 0); + + /** 0111 1101 1101 cond BMcnd C */ + + if (condition_true (cond)) + set_c (1); + else + set_c (0); + + /** 0111 1110 0101 srcx BNAND src */ + + BIT_OPC (srcx, !b & carry); + + /** 0111 1110 0111 srcx BNOR src */ + + BIT_OPC (srcx, !b | carry); + + /** 0111 1110 1010 dest BNOT:G dest */ + + BIT_OP (dest, !b); + + /** 0101 0bit BNOT:S bit,base:11[SB] */ + + dc = decode_bit11 (bit); + put_bit (dc, !get_bit (dc)); + + /** 0111 1110 0011 srcx BNTST src */ + + dc = decode_bit (srcx); + b = get_bit (dc); + set_zc (!b, !b); + + /** 0111 1110 1101 srcx BNXOR src */ + + BIT_OPC (srcx, !b ^ carry); + + /** 0111 1110 0110 srcx BOR src */ + + BIT_OPC (srcx, b | carry); + + /** 0000 0000 BRK */ + + /* We report the break to our caller with the PC still pointing at the + breakpoint instruction. */ + put_reg (pc, orig_pc); + if (verbose) + printf("[break]\n"); + return M32C_MAKE_HIT_BREAK (); + + /** 0111 1110 1001 dest BSET:G dest */ + + dc = decode_bit (dest); + put_bit (dc, 1); + + /** 0100 1bit BSET:S bit,base:11[SB] */ + + dc = decode_bit11 (bit); + put_bit (dc, 1); + + /** 0111 1110 1011 srcx BTST:G src */ + + dc = decode_bit (srcx); + b = get_bit (dc); + set_zc (!b, b); + + /** 0101 1bit BTST:S bit,base:11[SB] */ + + dc = decode_bit11 (bit); + b = get_bit (dc); + set_zc (!b, b); + + /** 0111 1110 0000 dest BTSTC dest */ + + dc = decode_bit (dest); + b = get_bit (dc); + set_zc (!b, b); + put_bit (dc, 0); + + /** 0111 1110 0001 dest BTSTS dest */ + + dc = decode_bit (dest); + b = get_bit (dc); + set_zc (!b, b); + put_bit (dc, 1); + + /** 0111 1110 1100 srcx BXOR src */ + + BIT_OPC (srcx, b ^ carry); + + /** 0111 011w 1000 dest CMP.size:G #IMM,dest */ + + UNARY_UOP; + imm = IMM(w); + cmp (v, imm, w); + + /** 1101 000w immm dest CMP.size:Q #IMM,dest */ + + UNARY_UOP; + immm = sign_ext (immm, 4); + cmp (v, immm, w); + + /** 1110 0dst CMP.B:S #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + v = get_src (dc); + cmp (v, imm, 0); + + /** 1100 000w srcx dest CMP.size:G src,dest */ + + BINARY_UOP; + cmp(b, a, w); + + /** 0011 1d sr CMP.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + dc = decode_dest1 (d, 0); + a = get_src (sc); + b = get_src (dc); + cmp (b, a, 0); + + /** 0111 110w 1110 i1c s DADC,DADD,DSBB,DSUB */ + + /* w = width, i = immediate, c = carry, s = subtract */ + + int src = i ? IMM(w) : get_reg (w ? r1 : r0h); + int dest = get_reg (w ? r0 : r0l); + int res; + + src = bcd2int(src, w); + dest = bcd2int(dest, w); + + tprintf("decimal: %d %s %d", dest, s?"-":"+", src); + if (c) + tprintf(" c=%d", carry); + + if (!s) + { + res = dest + src; + if (c) + res += carry; + c = res > (w ? 9999 : 99); + } + else + { + res = dest - src; + if (c) + res -= (1-carry); + c = res >= 0; + if (res < 0) + res += w ? 10000 : 100; + } + + res = int2bcd (res, w); + tprintf(" = %x\n", res); + + set_szc (res, w+1, c); + + put_reg (w ? r0 : r0l, res); + + /** 1010 1dst DEC.B dest */ + + dc = decode_dest3 (dst, 0); + v = get_src (dc); + tprintf("%x -- = %x\n", v, v-1); + v --; + set_sz (v, 1); + put_dest (dc, v); + + /** 1111 d010 DEC.W dest */ + + v = get_reg (d ? a1 : a0); + tprintf("%x -- = %x\n", v, v-1); + v --; + set_sz (v, 2); + put_reg (d ? a1 : a0, v); + + /** 0111 110w 1110 0001 DIV.size #IMM */ + + div_op (-1, 0, 0, w); + + /** 0111 011w 1101 srcx DIV.size src */ + + div_op (srcx, 0, 0, w); + + /** 0111 110w 1110 0000 DIVU.size #IMM */ + + div_op (-1, 1, 0, w); + + /** 0111 011w 1100 srcx DIVU.size src */ + + div_op (srcx, 1, 0, w); + + /** 0111 110w 1110 0011 DIVX.size #IMM */ + + div_op (-1, 0, 1, w); + + /** 0111 011w 1001 srcx DIVX.size src */ + + div_op (srcx, 0, 1, w); + + /** 0111 1100 1111 0010 ENTER #IMM8 */ + + imm = IMM(0); + put_reg (sp, get_reg (sp) - 2); + mem_put_hi (get_reg (sp), get_reg (fb)); + put_reg (fb, get_reg (sp)); + put_reg (sp, get_reg (sp) - imm); + + /** 0111 1101 1111 0010 EXITD */ + + put_reg (sp, get_reg (fb)); + put_reg (fb, mem_get_hi (get_reg (sp))); + put_reg (sp, get_reg (sp) + 2); + put_reg (pc, mem_get_psi (get_reg (sp))); + put_reg (sp, get_reg (sp) + 3); + + /** 0111 1100 0110 dest EXTS.B dest */ + + dc = decode_srcdest4 (dest, 0); + v = sign_ext (get_src (dc), 8); + dc = widen_sd (dc); + put_dest (dc, v); + set_sz (v, 1); + + /** 0111 1100 1111 0011 EXTS.W R0 */ + + v = sign_ext (get_reg (r0), 16); + put_reg (r2r0, v); + set_sz (v, 2); + + /** 1110 1011 0flg 0101 FCLR dest */ + + set_flags (1 << flg, 0); + + /** 1110 1011 0flg 0100 FSET dest */ + + set_flags (1 << flg, 1 << flg); + + /** 1010 0dst INC.B dest */ + + dc = decode_dest3 (dst, 0); + v = get_src (dc); + tprintf("%x ++ = %x\n", v, v+1); + v ++; + set_sz (v, 1); + put_dest (dc, v); + + /** 1011 d010 INC.W dest */ + + v = get_reg (d ? a1 : a0); + tprintf("%x ++ = %x\n", v, v+1); + v ++; + set_sz (v, 2); + put_reg (d ? a1 : a0, v); + + /** 1110 1011 11vector INT #imm */ + + trigger_based_interrupt (vector); + + /** 1111 0110 INTO */ + + if (FLAG_O) + trigger_fixed_interrupt (0xffe0); + + /** 0110 1cnd Jcnd label */ + + v = sign_ext (IMM(0), 8); + if (condition_true (cnd)) + put_reg (pc, orig_pc + 1 + v); + + /** 0111 1101 1100 cond Jcnd label */ + + v = sign_ext (IMM(0), 8); + if (condition_true (cond)) + put_reg (pc, orig_pc + 2 + v); + + /** 0110 0dsp JMP.S label */ + + put_reg (pc, orig_pc + 2 + dsp); + + /** 1111 1110 JMP.B label */ + + imm = sign_ext (IMM(0), 8); + if (imm == -1) + { + if (verbose) + printf("[jmp-to-self detected as exit]\n"); + return M32C_MAKE_HIT_BREAK (); + } + put_reg (pc, orig_pc + 1 + imm); + + /** 1111 0100 JMP.W label */ + + imm = sign_ext (IMM(1), 16); + put_reg (pc, orig_pc + 1 + imm); + + /** 1111 1100 JMP.A label */ + + imm = IMM(2); + put_reg (pc, imm); + + /** 0111 1101 0010 srcx JMPI.W src */ + + sc = decode_jumpdest (srcx, 1); + a = get_src (sc); + a = sign_ext (a, 16); + put_reg (pc, orig_pc + a); + + /** 0111 1101 0000 srcx JMPI.A src */ + + sc = decode_jumpdest (srcx, 0); + a = get_src (sc); + put_reg (pc, a); + + /** 1110 1110 JMPS #IMM8 */ + + M16C_ONLY(); + + imm = IMM(0); + a = 0xf0000 + mem_get_hi (0xffffe - imm * 2); + put_reg (pc, a); + + /** 1111 0101 JSR.W label */ + + imm = sign_ext (IMM(1), 16); + put_reg (sp, get_reg (sp) - 3); + mem_put_psi (get_reg (sp), get_reg (pc)); + put_reg (pc, orig_pc + imm + 1); + + /** 1111 1101 JSR.A label */ + + imm = IMM(2); + put_reg (sp, get_reg (sp) - 3); + mem_put_psi (get_reg (sp), get_reg (pc)); + put_reg (pc, imm); + + /** 0111 1101 0011 srcx JSRI.W src */ + + sc = decode_jumpdest (srcx, 1); + a = get_src (sc); + a = sign_ext (a, 16); + + put_reg (sp, get_reg (sp) - 3); + mem_put_psi (get_reg (sp), get_reg (pc)); + put_reg (pc, orig_pc + a); + + /** 0111 1101 0001 srcx JSRI.A src */ + + sc = decode_jumpdest (srcx, 0); + a = get_src (sc); + + put_reg (sp, get_reg (sp) - 3); + mem_put_psi (get_reg (sp), get_reg (pc)); + put_reg (pc, a); + + /** 1110 1111 JSRS #IMM8 */ + + M16C_ONLY(); + + imm = IMM(0); + a = 0xf0000 + mem_get_hi (0xffffe - imm * 2); + + put_reg (sp, get_reg (sp) - 3); + mem_put_psi (get_reg (sp), get_reg (pc)); + put_reg (pc, a); + + /** 1110 1011 0reg 0000 LDC #IMM16,dest */ + + dc = decode_cr (reg); + imm = IMM(1); + put_dest (dc, imm); + + /** 0111 1010 1reg srcx LDC src,dest */ + + dc = decode_cr (reg); + sc = decode_srcdest4 (srcx,1); + put_dest (dc, get_src (sc)); + + /** 0111 1100 1111 0000 LDCTX abs16,abs20 */ + + NOTYET(); + + /** 0111 010w 1000 dest LDE.size abs20,dest */ + + dc = decode_srcdest4 (dest, w); + imm = IMM(2); + if (w) + v = mem_get_hi (imm); + else + v = mem_get_qi (imm); + put_dest (dc, v); + + /** 0111 010w 1001 dest LDE.size dsp:20[a0], dest */ + + dc = decode_srcdest4 (dest, w); + imm = IMM(2) + get_reg (a0); + if (w) + v = mem_get_hi (imm); + else + v = mem_get_qi (imm); + put_dest (dc, v); + + /** 0111 010w 1010 dest LDE.size [a1a0],dest */ + + dc = decode_srcdest4 (dest, w); + imm = get_reg (a1a0); + if (w) + v = mem_get_hi (imm); + else + v = mem_get_qi (imm); + put_dest (dc, v); + + /** 0111 1101 1010 0imm LDIPL #IMM */ + + set_flags (0x700, imm*0x100); + + /** 0111 010w 1100 dest MOV.size:G #IMM,dest */ + + dc = decode_srcdest4 (dest, w); + imm = IMM(w); + v = imm; + tprintf("%x = %x\n", v, v); + set_sz(v, w+1); + put_dest (dc, v); + + /** 1101 100w immm dest MOV.size:Q #IMM,dest */ + + dc = decode_srcdest4 (dest, w); + v = sign_ext (immm, 4); + tprintf ("%x = %x\n", v, v); + set_sz (v, w+1); + put_dest (dc, v); + + /** 1100 0dst MOV.B:S #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + v = imm; + tprintf("%x = %x\n", v, v); + set_sz (v, 1); + put_dest (dc, v); + + /** 1w10 d010 MOV.size:S #IMM,dest */ + + /* Note that for w, 0=W and 1=B unlike the usual meaning. */ + v = IMM(1-w); + tprintf("%x = %x\n", v, v); + set_sz (v, 2-w); + put_reg (d ? a1 : a0, v); + + /** 1011 0dst MOV.B:Z #0,dest */ + + dc = decode_dest3 (dst, 0); + v = 0; + set_sz (v, 1); + put_dest (dc, v); + + /** 0111 001w srcx dest MOV.size:G src,dest */ + + sc = decode_srcdest4 (srcx, w); + dc = decode_srcdest4 (dest, w); + v = get_src (sc); + set_sz (v, w+1); + put_dest (dc, v); + + /** 0011 0d sr MOV.B:S src,dest */ + + sc = decode_src2 (sr, 0, d); + v = get_src (sc); + set_sz (v, 1); + put_reg (d ? a1 : a0, v); + + /** 0000 0s ds MOV.B:S R0L/R0H,dest */ + + if (ds == 0) + UNSUPPORTED(); + dc = decode_src2 (ds, 0, s); + v = get_reg (s ? r0h : r0l); + set_sz (v, 1); + put_dest (dc, v); + + /** 0000 1d sr MOV.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + v = get_src (sc); + set_sz (v, 1); + put_reg (d ? r0h : r0l, v); + + /** 0111 010w 1011 dest MOV.size:G dsp:8[SP], dest */ + + dc = decode_srcdest4 (dest, w); + imm = IMM(0); + a = get_reg (sp) + sign_ext (imm, 8); + a &= addr_mask; + if (w) + v = mem_get_hi (a); + else + v = mem_get_qi (a); + set_sz (v, w+1); + put_dest (dc, v); + + /** 0111 010w 0011 srcx MOV.size:G src, disp8[SP] */ + + sc = decode_srcdest4 (srcx, w); + imm = IMM(0); + a = get_reg (sp) + sign_ext (imm, 8); + a &= addr_mask; + v = get_src (sc); + if (w) + mem_put_hi (a, v); + else + mem_put_qi (a, v); + set_sz (v, w+1); + + /** 1110 1011 0reg 1src MOVA src,dest */ + + static reg_id map[] = { r0, r1, r2, r3, a0, a1, 0, 0 }; + sc = decode_srcdest4 (8 + src, 0); + put_reg (map[reg], sc.u.addr); + + /** 0111 1100 10hl dest MOVdir R0L,dest */ + + if (dest == 0 || dest == 4 || dest == 5) + UNSUPPORTED(); + dc = decode_srcdest4 (dest, 0); + a = get_src (dc); + b = get_reg (r0l); + switch (hl) + { + case 0: a = (a & 0xf0) | (b & 0x0f); break; + case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break; + case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break; + case 3: a = (a & 0x0f) | (b & 0xf0); break; + } + put_dest (dc, a); + + /** 0111 1100 00hl srcx MOVdir src,R0L */ + + if (srcx == 0 || srcx == 4 || srcx == 5) + UNSUPPORTED(); + sc = decode_srcdest4 (srcx, 0); + a = get_reg (r0l); + b = get_src (sc); + switch (hl) + { + case 0: a = (a & 0xf0) | (b & 0x0f); break; + case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break; + case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break; + case 3: a = (a & 0x0f) | (b & 0xf0); break; + } + put_reg (r0l, a); + + /** 0111 110w 0101 dest MUL.size #IMM,dest */ + + UNARY_SOP; + imm = sign_ext (IMM(w), w?16:8); + tprintf("%d * %d = %d\n", v, imm, v*imm); + v *= imm; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0111 100w srcx dest MUL.size src,dest */ + + BINARY_SOP; + v = a * b; + tprintf("%d * %d = %d\n", a, b, v); + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0111 110w 0100 dest MULU.size #IMM,dest */ + + UNARY_UOP; + imm = IMM(w); + tprintf("%u * %u = %u\n", v, imm, v*imm); + v *= imm; + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0111 000w srcx dest MULU.size src,dest */ + + BINARY_UOP; + v = a * b; + tprintf("%u * %u = %u\n", a, b, v); + dc = widen_sd (dc); + put_dest (dc, v); + + /** 0111 010w 0101 dest NEG.size dest */ + + UNARY_SOP; + tprintf("%d * -1 = %d\n", v, -v); + v = -v; + set_oszc (v, w+1, v == 0); + put_dest (dc, v); + + /** 0000 0100 NOP */ + + tprintf("nop\n"); + + /** 0111 010w 0111 dest NOT.size:G */ + + UNARY_UOP; + tprintf("~ %x = %x\n", v, ~v); + v = ~v; + set_sz (v, w+1); + put_dest (dc, v); + + /** 1011 1dst NOT.B:S dest */ + + dc = decode_dest3 (dst, 0); + v = get_src (dc); + tprintf("~ %x = %x\n", v, ~v); + v = ~v; + set_sz (v, 1); + put_dest (dc, v); + + /** 0111 011w 0011 dest OR.size:G #IMM,dest */ + + UNARY_UOP; + imm = IMM(w); + tprintf ("%x | %x = %x\n", v, imm, v | imm); + v |= imm; + set_sz (v, w+1); + put_dest (dc, v); + + /** 1001 1dst OR.B:S #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + v = get_src (dc); + tprintf("%x | %x = %x\n", v, imm, v|imm); + v |= imm; + set_sz (v, 1); + put_dest (dc, v); + + /** 1001 100w srcx dest OR.size:G src,dest */ + + BINARY_UOP; + tprintf ("%x | %x = %x\n", a, b, a | b); + v = a | b; + set_sz (v, w+1); + put_dest (dc, v); + + /** 0001 1d sr OR.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + dc = decode_dest1 (d, 0); + a = get_src (sc); + b = get_src (dc); + v = a | b; + tprintf("%x | %x = %x\n", a, b, v); + set_sz (v, 1); + put_dest (dc, v); + + /** 0111 010w 1101 dest POP.size:G dest */ + + dc = decode_srcdest4 (dest, w); + if (w) + { + v = mem_get_hi (get_reg (sp)); + put_reg (sp, get_reg (sp) + 2); + tprintf("pophi: %x\n", v); + } + else + { + v = mem_get_qi (get_reg (sp)); + put_reg (sp, get_reg (sp) + 1); + tprintf("popqi: %x\n", v); + } + put_dest (dc, v); + + /** 1001 d010 POP.B:S dest */ + + v = mem_get_qi (get_reg (sp)); + put_reg (d ? r0h : r0l, v); + put_reg (sp, get_reg (sp) + 1); + tprintf("popqi: %x\n", v); + + /** 1101 d010 POP.W:S dest */ + + v = mem_get_hi (get_reg (sp)); + put_reg (d ? a1 : a0, v); + put_reg (sp, get_reg (sp) + 2); + tprintf("pophi: %x\n", v); + + /** 1110 1011 0reg 0011 POPC dest */ + + dc = decode_cr (reg); + v = mem_get_hi (get_reg (sp)); + put_dest (dc, v); + put_reg (sp, get_reg (sp) + 2); + tprintf("popc: %x\n", v); + + /** 1110 1101 POPM dest */ + + static int map[] = { r0, r1, r2, r3, a0, a1, sb, fb }; + imm = IMM(0); + tprintf("popm: %x\n", imm); + for (a=0; a<8; a++) + if (imm & (1<= 0); + + /** 1011 100w srcx dest SBB.size src,dest */ + + sc = decode_srcdest4(srcx, w); + dc = decode_srcdest4(dest, w); + b = get_src (sc); + MATH_OP (dc, b, !carry, -, >= 0); + + /** 1111 000w immm dest SHA.size #IMM, dest */ + + dc = decode_srcdest4(dest, w); + shift_op (dc, 1, IMM4()); + + /** 0111 010w 1111 dest SHA.size R1H,dest */ + + dc = decode_srcdest4(dest, w); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 1, a); + + /** 1110 1011 101d immm SHA.L #IMM, dest */ + + dc = reg_sd (d ? r3r1 : r2r0); + shift_op (dc, 1, IMM4()); + + /** 1110 1011 001d 0001 SHA.L R1H,dest */ + + dc = reg_sd (d ? r3r1 : r2r0); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 1, a); + + /** 1110 100w immm dest SHL.size #IMM, dest */ + + dc = decode_srcdest4(dest, w); + shift_op (dc, 0, IMM4()); + + /** 0111 010w 1110 dest SHL.size R1H,dest */ + + dc = decode_srcdest4(dest, w); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 0, a); + + /** 1110 1011 100d immm SHL.L #IMM,dest */ + + dc = reg_sd (d ? r3r1 : r2r0); + shift_op (dc, 0, IMM4()); + + /** 1110 1011 000d 0001 SHL.L R1H,dest */ + + dc = reg_sd (d ? r3r1 : r2r0); + a = sign_ext (get_reg (r1h), 8); + shift_op (dc, 0, a); + + /** 0111 110w 1110 100b SMOVB.size */ + + int count = get_reg (r3); + int s1 = get_reg (a0) + (get_reg (r1h) << 16); + int s2 = get_reg (a1); + int inc = (w ? 2 : 1) * (b ? -1 : 1); + + while (count) + { + if (w) + { + v = mem_get_hi (s1); + mem_put_hi (s2, v); + } + else + { + v = mem_get_qi (s1); + mem_put_qi (s2, v); + } + s1 += inc; + s2 += inc; + count --; + } + put_reg (r3, count); + put_reg (a0, s1 & 0xffff); + put_reg (a1, s2); + put_reg (r1h, s1 >> 16); + + /** 0111 110w 1110 1010 SSTR.size */ + + int count = get_reg (r3); + int s1 = get_reg (a1); + v = get_reg (w ? r0 : r0h); + + while (count) + { + if (w) + { + mem_put_hi (s1, v); + s1 += 2; + } + else + { + mem_put_qi (s1, v); + s1 += 1; + } + count --; + } + put_reg (r3, count); + put_reg (a1, s1); + + /** 0111 1011 1src dest STC src,dest */ + + dc = decode_srcdest4 (dest, 1); + sc = decode_cr (src); + put_dest (dc, get_src(sc)); + + /** 0111 1100 1100 dest STC PC,dest */ + + dc = decode_srcdest4 (dest, 1); + dc.bytes = 3; + put_dest (dc, orig_pc); + + /** 0111 1101 1111 0000 STCTX abs16,abs20 */ + + NOTYET(); + + /** 0111 010w 0000 srcx STE.size src,abs20 */ + + sc = decode_srcdest4 (srcx, w); + a = IMM(2); + v = get_src (sc); + if (w) + mem_put_hi (a, v); + else + mem_put_qi (a, v); + if (srcx == 4 || srcx == 5) + { + v = get_reg (sc.u.reg); + set_sz (v, 2); + } + else + set_sz (v, w+1); + + /** 0111 010w 0001 srcx STE.size src,disp20[a0] */ + + sc = decode_srcdest4 (srcx, w); + a = get_reg(a0) + IMM(2); + v = get_src (sc); + if (w) + mem_put_hi (a, v); + else + mem_put_qi (a, v); + if (srcx == 4 || srcx == 5) + { + v = get_reg (sc.u.reg); + set_sz (v, 2); + } + else + set_sz (v, w+1); + + /** 0111 010w 0010 srcx STE.size src,[a1a0] */ + + sc = decode_srcdest4 (srcx, w); + a = get_reg(a1a0); + v = get_src (sc); + if (w) + mem_put_hi (a, v); + else + mem_put_qi (a, v); + if (srcx == 4 || srcx == 5) + { + v = get_reg (sc.u.reg); + set_sz (v, 2); + } + else + set_sz (v, w+1); + + /** 1101 0dst STNZ #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3(dst, 0); + if (!FLAG_Z) + put_dest (dc, imm); + + /** 1100 1dst STZ #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3(dst, 0); + if (FLAG_Z) + put_dest (dc, imm); + + /** 1101 1dst STZX #IMM81,#IMM82,dest */ + + a = IMM(0); + dc = decode_dest3(dst, 0); + b = IMM(0); + if (FLAG_Z) + put_dest (dc, a); + else + put_dest (dc, b); + + /** 0111 011w 0101 dest SUB.size:G #IMM,dest */ + + dc = decode_srcdest4 (dest, w); + imm = IMM(w); + MATH_OP (dc, imm, 0, -, >= 0); + + /** 1000 1dst SUB.B:S #IMM8,dest */ + + imm = IMM(0); + dc = decode_dest3 (dst, 0); + MATH_OP (dc, imm, 0, -, >= 0); + + /** 1010 100w srcx dest SUB.size:G src,dest */ + + sc = decode_srcdest4(srcx, w); + dc = decode_srcdest4(dest, w); + b = get_src (sc); + MATH_OP (dc, b, 0, -, >= 0); + + /** 0010 1d sr SUB.B:S src,R0L/R0H */ + + sc = decode_src2 (sr, 0, d); + dc = decode_dest1 (d, 0); + b = get_src (sc); + MATH_OP (dc, b, 0, -, >= 0); + + /** 0111 011w 0000 dest TST.size #IMM, dest */ + + UNARY_UOP; + imm = IMM(w); + tprintf ("%x & %x = %x\n", v, imm, v & imm); + v &= imm; + set_sz (v, w+1); + + /** 1000 000w srcx dest TST.size src,dest */ + + BINARY_UOP; + tprintf ("%x & %x = %x\n", a, b, a & b); + v = a & b; + set_sz (v, w+1); + + /** 1111 1111 UND */ + + trigger_fixed_interrupt (0xffdc); + + /** 0111 1101 1111 0011 WAIT */ + + tprintf("waiting...\n"); + + /** 0111 101w 00sr dest XCHG.size src,dest */ + + sc = decode_srcdest4 (sr, w); + dc = decode_srcdest4 (dest, w); + a = get_src (sc); + b = get_src (dc); + put_dest (dc, a); + put_dest (sc, b); + + /** 0111 011w 0001 dest XOR.size #IMM,dest */ + + UNARY_UOP; + imm = IMM(w); + tprintf ("%x ^ %x = %x\n", v, imm, v ^ imm); + v ^= imm; + set_sz (v, w+1); + put_dest (dc, v); + + /** 1000 100w srcx dest XOR.size src,dest */ + + BINARY_UOP; + tprintf ("%x ^ %x = %x\n", a, b, a ^ b); + v = a ^ b; + set_sz (v, w+1); + put_dest (dc, v); + + /** OP */ +/** */ + + return step_result; +} Index: cpu.h =================================================================== --- cpu.h (nonexistent) +++ cpu.h (revision 33) @@ -0,0 +1,222 @@ +/* cpu.h --- declarations for the M32C core. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +extern int verbose; +extern int trace; +extern int enable_counting; + +typedef unsigned char QI; +typedef unsigned short HI; +typedef unsigned long SI; +typedef unsigned long long DI; + +#define CPU_R8C 0x11 +#define CPU_M16C 0x12 +#define CPU_M32CM 0x23 +#define CPU_M32C 0x24 +extern int m32c_cpu; +void m32c_set_cpu (int cpu); + +#define A16 (m32c_cpu & 0x10) +#define A24 (m32c_cpu & 0x20) + +typedef struct +{ + HI r_r0; + HI r_r2; + HI r_r1; + HI r_r3; + SI r_a0; + SI r_a1; + SI r_sb; + SI r_fb; +} reg_bank_type; + +typedef struct +{ + reg_bank_type r[2]; + QI r_intbh; + HI r_intbl; + SI r_usp; + SI r_isp; + SI r_pc; + HI r_flags; +} regs_type; + +extern regs_type regs; +extern int addr_mask; +extern int membus_mask; + +#define FLAGBIT_C 0x0001 +#define FLAGBIT_D 0x0002 +#define FLAGBIT_Z 0x0004 +#define FLAGBIT_S 0x0008 +#define FLAGBIT_B 0x0010 +#define FLAGBIT_O 0x0020 +#define FLAGBIT_I 0x0040 +#define FLAGBIT_U 0x0080 + +#define REG_BANK (regs.r_flags & FLAG_B ? 1 : 0) + +typedef enum +{ + mem, + r0, r0h, r0l, + r1, r1h, r1l, + r2, r2r0, + r3, r3r1, + r3r1r2r0, + r3r2r1r0, + a0, + a1, a1a0, + sb, fb, + intb, intbl, intbh, + sp, usp, isp, pc, flags, + num_regs +} reg_id; + +extern char *reg_names[]; +extern int reg_bytes[]; + +extern unsigned int b2mask[]; +extern unsigned int b2signbit[]; +extern int b2maxsigned[]; +extern int b2minsigned[]; + +void init_regs (void); +void stack_heap_stats (void); +void set_pointer_width (int bytes); +unsigned int get_reg (reg_id id); +DI get_reg_ll (reg_id id); +void put_reg (reg_id id, unsigned int value); +void put_reg_ll (reg_id id, DI value); + +void set_flags (int mask, int newbits); +void set_oszc (int value, int bytes, int c); +void set_szc (int value, int bytes, int c); +void set_osz (int value, int bytes); +void set_sz (int value, int bytes); +void set_zc (int z, int c); +void set_c (int c); + +const char *bits (int v, int b); + +typedef struct +{ + QI bytes; + QI mem; + HI mask; + union + { + unsigned int addr; + reg_id reg; + } u; +} srcdest; + +void decode_indirect (int src_indirect, int dest_indirect); +void decode_index (int src_addend, int dest_addend); + +/* r8c */ +srcdest decode_srcdest4 (int destcode, int bw); +srcdest decode_dest3 (int destcode, int bw); +srcdest decode_src2 (int srccode, int bw, int d); +srcdest decode_dest1 (int destcode, int bw); +srcdest decode_jumpdest (int destcode, int w); +srcdest decode_cr (int crcode); +srcdest decode_cr_b (int crcode, int bank); +#define CR_B_DCT0 0 +#define CR_B_INTB 1 +#define CR_B_DMA0 2 + +/* m32c */ +srcdest decode_dest23 (int ddd, int dd, int bytes); +srcdest decode_src23 (int sss, int ss, int bytes); +srcdest decode_src3 (int sss, int bytes); +srcdest decode_dest2 (int dd, int bytes); + +srcdest widen_sd (srcdest sd); +srcdest reg_sd (reg_id reg); + +/* Mask has the one appropriate bit set. */ +srcdest decode_bit (int destcode); +srcdest decode_bit11 (int op0); +int get_bit (srcdest sd); +void put_bit (srcdest sd, int val); +int get_bit2 (srcdest sd, int bit); +void put_bit2 (srcdest sd, int bit, int val); + +int get_src (srcdest sd); +void put_dest (srcdest sd, int value); + +int condition_true (int cond_id); + +#define FLAG(f) (regs.r_flags & f ? 1 : 0) +#define FLAG_C FLAG(FLAGBIT_C) +#define FLAG_D FLAG(FLAGBIT_D) +#define FLAG_Z FLAG(FLAGBIT_Z) +#define FLAG_S FLAG(FLAGBIT_S) +#define FLAG_B FLAG(FLAGBIT_B) +#define FLAG_O FLAG(FLAGBIT_O) +#define FLAG_I FLAG(FLAGBIT_I) +#define FLAG_U FLAG(FLAGBIT_U) + +/* Instruction step return codes. + Suppose one of the decode_* functions below returns a value R: + - If M32C_STEPPED (R), then the single-step completed normally. + - If M32C_HIT_BREAK (R), then the program hit a breakpoint. + - If M32C_EXITED (R), then the program has done an 'exit' system + call, and the exit code is M32C_EXIT_STATUS (R). + - If M32C_STOPPED (R), then a signal (number M32C_STOP_SIG (R)) was + generated. + + For building step return codes: + - M32C_MAKE_STEPPED is the return code for finishing a normal step. + - M32C_MAKE_HIT_BREAK is the return code for hitting a breakpoint. + - M32C_MAKE_EXITED (C) is the return code for exiting with status C. + - M32C_MAKE_STOPPED (S) is the return code for stopping on signal S. */ +#define M32C_MAKE_STEPPED() (0) +#define M32C_MAKE_HIT_BREAK() (1) +#define M32C_MAKE_EXITED(c) (((int) (c) << 8) + 2) +#define M32C_MAKE_STOPPED(s) (((int) (s) << 8) + 3) + +#define M32C_STEPPED(r) ((r) == M32C_MAKE_STEPPED ()) +#define M32C_HIT_BREAK(r) ((r) == M32C_MAKE_HIT_BREAK ()) +#define M32C_EXITED(r) (((r) & 0xff) == 2) +#define M32C_EXIT_STATUS(r) ((r) >> 8) +#define M32C_STOPPED(r) (((r) & 0xff) == 3) +#define M32C_STOP_SIG(r) ((r) >> 8) + +/* The step result for the current step. Global to allow + communication between the stepping function and the system + calls. */ +extern int step_result; + +/* Used to detect heap/stack collisions */ +extern unsigned int heaptop; +extern unsigned int heapbottom; + +/* Points to one of the below functions, set by m32c_load(). */ +extern int (*decode_opcode) (); + +extern int decode_r8c (); +extern int decode_m32c (); + +extern void trace_register_changes ();
cpu.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: syscalls.c =================================================================== --- syscalls.c (nonexistent) +++ syscalls.c (revision 33) @@ -0,0 +1,334 @@ +/* syscalls.c --- implement system calls for the M32C simulator. + +Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +This program 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 3 of the License, or +(at your option) any later version. + +This program 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 this program. If not, see . */ + + +#include +#include +#include +#include +#include + +#include "gdb/callback.h" + +#include "cpu.h" +#include "mem.h" +#include "syscalls.h" + +#include "syscall.h" + +/* The current syscall callbacks we're using. */ +static struct host_callback_struct *callbacks; + +void +set_callbacks (struct host_callback_struct *cb) +{ + callbacks = cb; +} + + +/* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack + arg2 in r2 (HI) or stack + arg3..N on stack + padding: none + + A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack + arg2..N on stack + padding: qi->hi + + return value in r0l (QI) r0 (HI) r2r0 (SI) + structs: pointer pushed on stack last + +*/ + +int argp, stackp; + +static int +arg (int bytes) +{ + int rv = 0; + argp++; + if (A16) + { + switch (argp) + { + case 1: + if (bytes == 1) + return get_reg (r1l); + if (bytes == 2) + return get_reg (r1); + break; + case 2: + if (bytes == 2) + return get_reg (r2); + break; + } + } + else + { + switch (argp) + { + case 1: + if (bytes == 1) + return get_reg (r0l); + if (bytes == 2) + return get_reg (r0); + break; + } + } + if (bytes == 0) + bytes = 2; + switch (bytes) + { + case 1: + rv = mem_get_qi (get_reg (sp) + stackp); + if (A24) + stackp++; + break; + case 2: + rv = mem_get_hi (get_reg (sp) + stackp); + break; + case 3: + rv = mem_get_psi (get_reg (sp) + stackp); + if (A24) + stackp++; + break; + case 4: + rv = mem_get_si (get_reg (sp) + stackp); + break; + } + stackp += bytes; + return rv; +} + +static void +read_target (char *buffer, int address, int count, int asciiz) +{ + char byte; + while (count > 0) + { + byte = mem_get_qi (address++); + *buffer++ = byte; + if (asciiz && (byte == 0)) + return; + count--; + } +} + +static void +write_target (char *buffer, int address, int count, int asciiz) +{ + char byte; + while (count > 0) + { + byte = *buffer++; + mem_put_qi (address++, byte); + if (asciiz && (byte == 0)) + return; + count--; + } +} + +#define PTRSZ (A16 ? 2 : 3) + +static char *callnames[] = { + "SYS_zero", + "SYS_exit", + "SYS_open", + "SYS_close", + "SYS_read", + "SYS_write", + "SYS_lseek", + "SYS_unlink", + "SYS_getpid", + "SYS_kill", + "SYS_fstat", + "SYS_sbrk", + "SYS_argvlen", + "SYS_argv", + "SYS_chdir", + "SYS_stat", + "SYS_chmod", + "SYS_utime", + "SYS_time", + "SYS_gettimeofday", + "SYS_times", + "SYS_link" +}; + +void +m32c_syscall (int id) +{ + static char buf[256]; + int rv; + + argp = 0; + stackp = A16 ? 3 : 4; + if (trace) + printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]); + switch (id) + { + case SYS_exit: + { + int ec = arg (2); + if (verbose) + printf ("[exit %d]\n", ec); + step_result = M32C_MAKE_EXITED (ec); + } + break; + + case SYS_open: + { + int path = arg (PTRSZ); + int oflags = arg (2); + int cflags = arg (2); + + read_target (buf, path, 256, 1); + if (trace) + printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags); + + if (callbacks) + /* The callback vector ignores CFLAGS. */ + rv = callbacks->open (callbacks, buf, oflags); + else + { + int h_oflags = 0; + + if (oflags & 0x0001) + h_oflags |= O_WRONLY; + if (oflags & 0x0002) + h_oflags |= O_RDWR; + if (oflags & 0x0200) + h_oflags |= O_CREAT; + if (oflags & 0x0008) + h_oflags |= O_APPEND; + if (oflags & 0x0400) + h_oflags |= O_TRUNC; + rv = open (buf, h_oflags, cflags); + } + if (trace) + printf ("%d\n", rv); + put_reg (r0, rv); + } + break; + + case SYS_close: + { + int fd = arg (2); + + if (callbacks) + rv = callbacks->close (callbacks, fd); + else if (fd > 2) + rv = close (fd); + else + rv = 0; + if (trace) + printf ("close(%d) = %d\n", fd, rv); + put_reg (r0, rv); + } + break; + + case SYS_read: + { + int fd = arg (2); + int addr = arg (PTRSZ); + int count = arg (2); + + if (count > sizeof (buf)) + count = sizeof (buf); + if (callbacks) + rv = callbacks->read (callbacks, fd, buf, count); + else + rv = read (fd, buf, count); + if (trace) + printf ("read(%d,%d) = %d\n", fd, count, rv); + if (rv > 0) + write_target (buf, addr, rv, 0); + put_reg (r0, rv); + } + break; + + case SYS_write: + { + int fd = arg (2); + int addr = arg (PTRSZ); + int count = arg (2); + + if (count > sizeof (buf)) + count = sizeof (buf); + if (trace) + printf ("write(%d,0x%x,%d)\n", fd, addr, count); + read_target (buf, addr, count, 0); + if (trace) + fflush (stdout); + if (callbacks) + rv = callbacks->write (callbacks, fd, buf, count); + else + rv = write (fd, buf, count); + if (trace) + printf ("write(%d,%d) = %d\n", fd, count, rv); + put_reg (r0, rv); + } + break; + + case SYS_getpid: + put_reg (r0, 42); + break; + + case SYS_gettimeofday: + { + int tvaddr = arg (PTRSZ); + struct timeval tv; + + rv = gettimeofday (&tv, 0); + if (trace) + printf ("gettimeofday: %ld sec %ld usec to 0x%x\n", tv.tv_sec, + tv.tv_usec, tvaddr); + mem_put_si (tvaddr, tv.tv_sec); + mem_put_si (tvaddr + 4, tv.tv_usec); + put_reg (r0, rv); + } + break; + + case SYS_kill: + { + int pid = arg (2); + int sig = arg (2); + if (pid == 42) + { + if (verbose) + printf ("[signal %d]\n", sig); + step_result = M32C_MAKE_STOPPED (sig); + } + } + break; + + case 11: + { + int heaptop_arg = arg (PTRSZ); + if (trace) + printf ("sbrk: heap top set to %x\n", heaptop_arg); + heaptop = heaptop_arg; + if (heapbottom == 0) + heapbottom = heaptop_arg; + } + break; + + } +}
syscalls.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.