/* m32c.opc --- semantics for m32c opcodes. -*- mode: c -*-
-Copyright (C) 2005 Free Software Foundation, Inc.
+Copyright (C) 2005-2016 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
-The GNU simulators are free software; you can redistribute them and/or
-modify them under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+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.
-The GNU simulators are distributed in the hope that they 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.
+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 the GNU simulators; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA */
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#define tprintf if (trace) printf
static unsigned char
-getbyte ()
+getbyte (void)
{
int tsave = trace;
unsigned char b;
#define GETBYTE() (op[opi++] = getbyte())
-#define UNSUPPORTED() unsupported("unsupported", orig_pc)
-#define NOTYET() unsupported("unimplemented", orig_pc)
+#define UNSUPPORTED() unsupported("unsupported", m32c_opcode_pc)
+#define NOTYET() unsupported("unimplemented", m32c_opcode_pc)
static void
unsupported (char *tag, int orig_pc)
/* Indicate which sorts of prefixes are allowed for the current
opcode. */
-void
-prefix (src_allowed, dest_allowed, index_bytewidth)
+static void
+prefix (int src_allowed, int dest_allowed, int index_bytewidth)
{
/* At the moment, we don't do anything with this information. We
just wanted to get the information entered in some
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)); \
+ set_oszc (v, dc.bytes, (1 op 1) ? (ll > b2mask[dc.bytes]) : (ll >= 0)); \
put_dest (dc, v); \
}
set_flags (FLAGBIT_O, o ? FLAGBIT_O : 0);
}
+static int pcs[16];
+static int ipcs = 0;
+
int
-decode_m32c()
+decode_m32c (void)
{
unsigned char op[40];
int opi;
- int orig_pc;
int v, a, b;
long long ll;
srcdest sc, dc;
next_opcode:
opi = 0;
- orig_pc = get_reg (pc);
+ m32c_opcode_pc = get_reg (pc);
- tprintf("trace: decode pc = %06x\n", orig_pc);
+ tprintf("trace: decode pc = %06x\n", m32c_opcode_pc);
+
+ if (m32c_opcode_pc == 0)
+ {
+ int i;
+ printf("Abort: PC is zero, here from:\n");
+ for (i=0; i<4; i++)
+ printf(" 0x%06x\n", pcs[(ipcs+15-i)%16]);
+ return M32C_MAKE_HIT_BREAK ();
+ }
+ pcs[ipcs++] = m32c_opcode_pc;
+ ipcs %= 16;
/** VARY sss 000 001 010 011 100 */
/** VARY ddd 000 001 010 011 100 */
if ((v & (w ? 0xffff : 0xff)) != 0)
{
tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a);
- put_reg (pc, orig_pc + 2 + a);
+ put_reg (pc, m32c_opcode_pc + 2 + a);
tprintf("%x\n", get_reg (pc));
}
prefix (0, 0, 0);
sc = decode_src23 (sss, ss, 1);
- BIT_OPC (sc, bit, !b & carry);
+ 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);
+ BIT_OPC (sc, bit, (!b) | carry);
/** 1101 ddd0 dd01 1bit BNOT dest */
/* We report the break to our caller with the PC still pointing at the
breakpoint instruction. */
- put_reg (pc, orig_pc);
+ put_reg (pc, m32c_opcode_pc);
if (verbose)
printf("[break]\n");
+ if (in_gdb || (regs.r_intbl == 0 && regs.r_intbh == 0))
+ return M32C_MAKE_HIT_BREAK ();
+ if (mem_get_qi (0xFFFFE7) == 0xff)
+ trigger_based_interrupt (0);
+ else
+ trigger_fixed_interrupt (0xFFFFE4);
+
+ /** 1111 1110 GBRK */
+
+ /* This alternate break, which is not part of the chip's opcode set,
+ is here in case you need to debug a program that itself uses the
+ chip's BRK opcode. You'll need to modify your copy of GDB to use
+ this opcode instead of the real BRK. */
+
+ /* GDB Break. */
+ /* We report the break to our caller with the PC still pointing at the
+ breakpoint instruction. */
+ put_reg (pc, m32c_opcode_pc);
+ if (verbose)
+ printf("[gdb break]\n");
return M32C_MAKE_HIT_BREAK ();
- /** 0000 1000 BRK */
+ /** 0000 1000 BRK2 */
if (verbose)
printf("[break2]\n");
- return M32C_MAKE_HIT_BREAK ();
+ if (in_gdb)
+ return M32C_MAKE_HIT_BREAK ();
+ if (mem_get_qi (0xFFFFE7) == 0xff)
+ trigger_based_interrupt (0);
+ else
+ trigger_fixed_interrupt (0xFFFFE4);
/** 1101 ddd0 dd11 1bit BSET dest */
prefix (0, 0, 0);
v = sign_ext (IMM(1), 8);
if (condition_true (ccc*2+c))
- put_reg (pc, orig_pc + 1 + v);
+ put_reg (pc, m32c_opcode_pc + 1 + v);
/** 01dd 101d JMP.S label */
prefix (0, 0, 0);
- put_reg (pc, orig_pc + (dd*2+d) + 2);
+ put_reg (pc, m32c_opcode_pc + (dd*2+d) + 2);
/** 1011 1011 JMP.B label */
printf("[jmp-to-self detected as exit]\n");
return M32C_MAKE_HIT_BREAK ();
}
- put_reg (pc, orig_pc + 1 + imm);
+ put_reg (pc, m32c_opcode_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);
+ put_reg (pc, m32c_opcode_pc + 1 + imm);
/** 1100 1100 JMP.A label */
sc = decode_src23 (sss, ss, 2);
a = get_src (sc);
a = sign_ext (a, 16);
- put_reg (pc, orig_pc + a);
+ put_reg (pc, m32c_opcode_pc + a);
/** 1000 sss0 ss00 0001 JMPI.A src */
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);
+ put_reg (pc, m32c_opcode_pc + imm + 1);
/** 1100 1101 JSR.A label */
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);
+ put_reg (pc, m32c_opcode_pc + a);
/** 1001 sss0 ss00 0001 JSRI.A src */
a = get_reg (a1);
b = get_reg (r3);
+ v = get_reg (w ? r0 : r0l);
for (;b;)
{
if (w)
- mem_put_hi(a, r0);
+ mem_put_hi(a, v);
else
- mem_put_qi(a, r0 & 0xff);
+ mem_put_qi(a, v);
a += w ? 2 : 1;
b --;
}