mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
1d506c26d9
This commit is the result of the following actions: - Running gdb/copyright.py to update all of the copyright headers to include 2024, - Manually updating a few files the copyright.py script told me to update, these files had copyright headers embedded within the file, - Regenerating gdbsupport/Makefile.in to refresh it's copyright date, - Using grep to find other files that still mentioned 2023. If these files were updated last year from 2022 to 2023 then I've updated them this year to 2024. I'm sure I've probably missed some dates. Feel free to fix them up as you spot them.
2151 lines
46 KiB
C
2151 lines
46 KiB
C
/* m32c.opc --- semantics for m32c opcodes. -*- mode: c -*-
|
|
|
|
Copyright (C) 2005-2024 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/>. */
|
|
|
|
/* This must come before any other includes. */
|
|
#include "defs.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ansidecl.h"
|
|
#include "cpu.h"
|
|
#include "mem.h"
|
|
#include "misc.h"
|
|
#include "int.h"
|
|
|
|
#define tprintf if (trace) printf
|
|
|
|
static unsigned char
|
|
getbyte (void)
|
|
{
|
|
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. */
|
|
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
|
|
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 (void)
|
|
{
|
|
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 101bit BTST:S src */
|
|
|
|
sc = decode_src23 (3, 3, 1); /* bit,base:19 */
|
|
bit = get_bit2 (sc, bb*2 + bit);
|
|
set_zc (!bit, bit);
|
|
|
|
/** 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 1flg LDIPL #IMM */
|
|
|
|
set_flags (0x7000, flg*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);
|
|
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;
|
|
}
|