OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [m32c/] [m32c.opc] - Rev 227

Compare with Previous | Blame | View Log

/* m32c.opc --- semantics for m32c opcodes.                     -*- mode: c -*-

Copyright (C) 2005, 2007, 2008, 2009, 2010 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 <stdlib.h>

#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", m32c_opcode_pc)
#define NOTYET() unsupported("unimplemented", m32c_opcode_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, (1 op 1) ? (ll > b2mask[dc.bytes]) : (ll >= 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);
}

static int pcs[16];
static int ipcs = 0;

int
decode_m32c()
{
  unsigned char op[40];
  int opi;
  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;
  m32c_opcode_pc = get_reg (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 */

  /** 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, m32c_opcode_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, 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                         BRK2 */

  if (verbose)
    printf("[break2]\n");
  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 */

  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, m32c_opcode_pc + 1 + v);

  /** 01dd 101d                         JMP.S label */

  prefix (0, 0, 0);
  put_reg (pc, m32c_opcode_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, m32c_opcode_pc + 1 + imm);

  /** 1100 1110                         JMP.W label */

  prefix (0, 0, 0);
  imm = sign_ext (IMM(2), 16);
  put_reg (pc, m32c_opcode_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, m32c_opcode_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, m32c_opcode_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, m32c_opcode_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<<a))
      {
        v = mem_get_hi (get_reg (sp));
        put_reg (map[a], v);
        put_reg (sp, get_reg (sp) + 2);
      }
  for (; a<8; a++)
    if (imm & (1<<a))
      {
        v = mem_get_si (get_reg (sp));
        put_reg (map[a], v);
        put_reg (sp, get_reg (sp) + 4);
      }

  /** 1010 111w                         PUSH.size #IMM */

  prefix (0, 0, 0);
  imm = IMM(w+1);
  tprintf("push%s: %x\n", w ? "hi" : "qi", imm);
  int a = get_reg (sp) - 2;
  if (w)
    mem_put_hi (a, imm);
  else
    mem_put_qi (a, imm);
  put_reg (sp, a);

  /** 1100 sss w ss00 1110              PUSH.size src */

  prefix (0, 1, 0);
  sc = decode_dest23 (sss, ss, w+1);
  a = get_src (sc);
  put_reg (sp, get_reg (sp) - 2);
  if (w)
    mem_put_hi (get_reg (sp), a);
  else
    mem_put_qi (get_reg (sp), a);
  tprintf("push%s: %x\n", w ? "hi" : "qi", a);

  /** 1011 0110 0101 0011               PUSH.L #IMM32 */

  imm = IMM(4);
  put_reg (sp, get_reg (sp) - 4);
  mem_put_si (get_reg (sp), imm);

  /** 1010 sss0 ss00 0001               PUSH.L src */

  prefix (0, 1, 0);
  sc = decode_dest23 (sss, ss, 4);
  a = get_src (sc);
  put_reg (sp, get_reg (sp) - 4);
  mem_put_si (get_reg (sp), a);

  /** 1011 0sa0 ss00 0001               PUSHA src */

  prefix (0, 0, 0);
  sc = decode_dest23 (sa, ss, 1);
  put_reg (sp, get_reg (sp) - 4);
  mem_put_hi (get_reg (sp), sc.u.addr);
  tprintf("pushsi: %x\n", sc.u.addr);

  /** 1101 0001 1010 1src               PUSHC src */

  prefix (0, 0, 0);
  sc = decode_cr_b (src, CR_B_DCT0);
  a = get_src (sc);
  put_reg (sp, get_reg (sp) - 2);
  mem_put_hi (get_reg (sp), a);
  tprintf("pushhi: %x\n", a);

  /** 1101 0001 0010 1src               PUSHC src */

  prefix (0, 0, 0);
  sc = decode_cr_b (src, CR_B_INTB);
  a = get_src (sc);
  put_reg (sp, get_reg (sp) - 4);
  mem_put_si (get_reg (sp), a);
  tprintf("pushsi: %x\n", a);

  /** 1000 1111                         PUSHM src */

  static int map[] = { fb, sb, a1, a0, r3, r2, r1, r0 };
  imm = IMM(1);
  tprintf("pushm: %x\n", imm);
  for (a=0; a<4; a++)
    if (imm & (1<<a))
      {
        put_reg (sp, get_reg (sp) - 4);
        v = get_reg (map[a]);
        mem_put_si (get_reg (sp), v);
      }
  for (; a<8; a++)
    if (imm & (1<<a))
      {
        put_reg (sp, get_reg (sp) - 2);
        v = get_reg (map[a]);
        mem_put_hi (get_reg (sp), v);
      }

  /** 1001 1110                         REIT */

  a = get_reg (sp);
  put_reg (pc, mem_get_si (a));
  a += 4;
  put_reg (flags, mem_get_hi (a));
  a += 2;
  put_reg (sp, a);

  /** 1011 1000 010w 0011               RMPA.size */

  int count = get_reg (r3);
  int list1 = get_reg (a0);
  int list2 = get_reg (a1);
  long long sum = get_reg_ll (r3r1r2r0) & 0xffffff;

  while (count)
    {
      if (w)
        {
          a = sign_ext (mem_get_hi (list1), 16);
          b = sign_ext (mem_get_hi (list2), 16);
        }
      else
        {
          a = sign_ext (mem_get_qi (list1), 8);
          b = sign_ext (mem_get_qi (list2), 8);
        }
      tprintf("%lld + %d * %d = ", sum, a, b);
      sum += a * b;
      tprintf("%lld\n", sum);
      list1 += w ? 2 : 1;
      list2 += w ? 2 : 1;
      count --;
    }
  put_reg (r3, count);
  put_reg (a0, list1);
  put_reg (a1, list2);
  put_reg (r2r0, (int)(sum & 0xffffffffU));
  put_reg (r1, (int)(sum >> 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);
  v = get_reg (w ? r0 : r0l);
  for (;b;)
    {
      if (w)
        mem_put_hi(a, v);
      else
        mem_put_qi(a, v);
      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;
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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