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