1396 lines
25 KiB
C
1396 lines
25 KiB
C
/* BFD library support routines for the Hitachi H8/300 architecture.
|
|
Copyright (C) 1990-1991 Free Software Foundation, Inc.
|
|
Hacked by Steve Chamberlain of Cygnus Support.
|
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
#include"bfd.h"
|
|
#include"sysdep.h"
|
|
|
|
#define DEFINE_TABLE
|
|
#define INSIM
|
|
#include"opcode/h8300.h"
|
|
|
|
#define MAXSAME 14
|
|
|
|
#define PTWO 256
|
|
static struct h8_opcode *h8_opcodes_sorted[PTWO][MAXSAME];
|
|
|
|
/* Run through the opcodes and sort them into order to make them easy
|
|
to disassemble
|
|
*/
|
|
|
|
char *cs = "/*";
|
|
char *ce = "*/";
|
|
|
|
char *nibs[] =
|
|
{
|
|
"foo",
|
|
"(b0&0xf)",
|
|
"((b1>>4)&0xf)",
|
|
"((b1)&0xf)",
|
|
"((pc[2]>>4)&0xf)",
|
|
"((pc[2])&0xf)",
|
|
"((pc[3]>>4)&0xf)",
|
|
"((pc[3])&0xf)",
|
|
0, 0};
|
|
|
|
char *abs8[] =
|
|
{
|
|
"foo",
|
|
"foo",
|
|
"b1",
|
|
"foo",
|
|
};
|
|
|
|
#define sorted_key noperands
|
|
char *abs16[] =
|
|
{
|
|
"foo",
|
|
"foo",
|
|
"foo",
|
|
"foo",
|
|
|
|
"(pc[2]<<8)|pc[3]",
|
|
"foo",
|
|
"foo",
|
|
"foo",
|
|
};
|
|
char *empty="fake";
|
|
init ()
|
|
{
|
|
unsigned int i;
|
|
struct h8_opcode *p;
|
|
|
|
for (p = h8_opcodes; p->name; p++)
|
|
{
|
|
int n1 = 0;
|
|
int n2 = 0;
|
|
int j;
|
|
for (j = 0; p->data.nib[j] != E; j++)
|
|
{
|
|
if ((int)p->data.nib[j] == ABS16ORREL8SRC)
|
|
p->data.nib[j] = ABS16SRC;
|
|
if ((int)p->data.nib[j ] == ABS16OR8SRC)
|
|
p->data.nib[j] = ABS16SRC;
|
|
if ((int)p->data.nib[j] == ABS16OR8DST)
|
|
p->data.nib[j] = ABS16DST;
|
|
}
|
|
/* Kill push and pop, they're duplicates */
|
|
if (strcmp(p->name,"push")==0) {
|
|
p->name = empty;
|
|
}
|
|
if (strcmp(p->name,"pop")==0) {
|
|
p->name = empty;
|
|
}
|
|
|
|
|
|
if ((int) p->data.nib[0] < 16)
|
|
{
|
|
n1 = (int) p->data.nib[0];
|
|
}
|
|
else
|
|
n1 = 0;
|
|
if ((int) p->data.nib[1] < 16)
|
|
{
|
|
n2 = (int) p->data.nib[1];
|
|
}
|
|
else
|
|
n2 = 0;
|
|
#if 0
|
|
if ((int) p->data.nib[2] < 16)
|
|
{
|
|
n3 = (int) p->data.nib[2];
|
|
}
|
|
else if ((int) p->data.nib[2] & B30)
|
|
{
|
|
n3 = 0;
|
|
}
|
|
else if ((int) p->data.nib[2] & B31)
|
|
{
|
|
n3 = 0x8;
|
|
}
|
|
|
|
|
|
if ((int) p->data.nib[3] < 16)
|
|
{
|
|
n4 = (int) p->data.nib[3];
|
|
}
|
|
else if ((int) p->data.nib[3] & B30)
|
|
{
|
|
n4 = 0;
|
|
}
|
|
else if ((int) p->data.nib[3] & B31)
|
|
{
|
|
n4 = 0x8;
|
|
}
|
|
#endif
|
|
for (i = 0; i < MAXSAME; i++)
|
|
{
|
|
int j = /* ((n3 >> 3) * 512) + ((n4 >> 3) * 256) + */ n1 * 16 + n2;
|
|
|
|
if (h8_opcodes_sorted[j][i] == (struct h8_opcode *) NULL)
|
|
{
|
|
h8_opcodes_sorted[j][i] = p;
|
|
p->sorted_key = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == MAXSAME)
|
|
abort ();
|
|
|
|
/* Just make sure there are an even number of nibbles in it, and
|
|
that the count is the same s the length */
|
|
for (i = 0; p->data.nib[i] != E; i++)
|
|
/*EMPTY*/ ;
|
|
if (i & 1)
|
|
abort ();
|
|
p->length = i / 2;
|
|
}
|
|
for (i = 0; i < PTWO; i++)
|
|
{
|
|
if (h8_opcodes_sorted[i][0])
|
|
p = h8_opcodes_sorted[i][0];
|
|
else
|
|
h8_opcodes_sorted[i][0] = p;
|
|
}
|
|
}
|
|
|
|
unsigned int
|
|
DEFUN (bfd_h8_disassemble, (addr, data, stream),
|
|
bfd_vma addr AND
|
|
CONST bfd_byte * data AND
|
|
FILE * stream)
|
|
{
|
|
/* Find the first entry in the table for this opcode */
|
|
CONST static char *regnames[] =
|
|
{
|
|
"r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
|
|
"r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"};
|
|
|
|
int rs = 0;
|
|
int rd = 0;
|
|
int rdisp = 0;
|
|
int abs = 0;
|
|
struct h8_opcode **p = h8_opcodes_sorted[(unsigned) (data[0])];
|
|
struct h8_opcode *q;
|
|
|
|
/* Find the exact opcode/arg combo */
|
|
while (*p)
|
|
{
|
|
op_type *nib;
|
|
unsigned int len = 0;
|
|
|
|
q = *p++;
|
|
nib = q->data.nib;
|
|
while (*nib != E)
|
|
{
|
|
op_type looking_for = *nib;
|
|
int thisnib = data[len >> 1];
|
|
|
|
thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib >> 4) & 0xf);
|
|
if ((int) looking_for & (int) B31)
|
|
{
|
|
if (((int) thisnib & 0x8) == 0)
|
|
goto fail;
|
|
looking_for = (op_type) ((int) looking_for & ~(int) B31);
|
|
}
|
|
if ((int) looking_for & (int) B30)
|
|
{
|
|
if (((int) thisnib & 0x8) != 0)
|
|
goto fail;
|
|
looking_for = (op_type) ((int) looking_for & ~(int) B30);
|
|
}
|
|
switch (looking_for)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
if ((int) looking_for != thisnib)
|
|
goto fail;
|
|
break;
|
|
case ABS16SRC:
|
|
case ABS16OR8SRC:
|
|
case ABS16ORREL8SRC:
|
|
case ABS16DST:
|
|
case ABS16OR8DST:
|
|
case DISPSRC:
|
|
case DISPDST:
|
|
case IMM16:
|
|
abs = (data[len >> 1]) * 256 + data[(len + 2) >> 1];
|
|
len += 3;
|
|
nib += 3;
|
|
break;
|
|
case DISPREG:
|
|
rdisp = thisnib;
|
|
break;
|
|
case KBIT:
|
|
abs = thisnib == 0x8 ? 2 : 1;
|
|
break;
|
|
case IMM8:
|
|
case ABS8SRC:
|
|
case ABS8DST:
|
|
case MEMIND:
|
|
case DISP8:
|
|
abs = data[len >> 1];
|
|
len++;
|
|
nib++;
|
|
break;
|
|
case IMM3:
|
|
abs = thisnib;
|
|
break;
|
|
case RS8:
|
|
case RS16:
|
|
case RSINC:
|
|
case RSIND:
|
|
rs = thisnib;
|
|
break;
|
|
case RD16:
|
|
case RDDEC:
|
|
case RD8:
|
|
case RDIND:
|
|
rd = thisnib;
|
|
break;
|
|
default:
|
|
fprintf (stream, "Dont understand \n");
|
|
goto found;
|
|
}
|
|
len++;
|
|
nib++;
|
|
}
|
|
goto found;
|
|
fail:
|
|
;
|
|
|
|
}
|
|
fprintf (stream, "%02x %02x .word\tH'%x,H'%x",
|
|
data[0], data[1],
|
|
data[0], data[1]);
|
|
return 2;
|
|
found:;
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < q->length; i++)
|
|
{
|
|
fprintf (stream, "%02x", data[i]);
|
|
}
|
|
for (; i < 6; i++)
|
|
{
|
|
fprintf (stream, " ");
|
|
}
|
|
}
|
|
fprintf (stream, "%s\t", q->name);
|
|
/* Now print out the args */
|
|
{
|
|
op_type *args = q->args.nib;
|
|
int hadone = 0;
|
|
|
|
while (*args != E)
|
|
{
|
|
if (hadone)
|
|
fprintf (stream, ",");
|
|
switch ((int) (*args) & ~((int) B30 | (int) B31))
|
|
{
|
|
case IMM16:
|
|
case IMM8:
|
|
case IMM3:
|
|
fprintf (stream, "#0x%x", (unsigned) abs);
|
|
break;
|
|
case RD8:
|
|
fprintf (stream, "%s", regnames[rd]);
|
|
break;
|
|
case RS8:
|
|
fprintf (stream, "%s", regnames[rs]);
|
|
break;
|
|
case RD16:
|
|
fprintf (stream, "r%d", rd & 0x7);
|
|
break;
|
|
case RS16:
|
|
fprintf (stream, "r%d", rs & 0x7);
|
|
break;
|
|
case RSINC:
|
|
fprintf (stream, "@r%d+", rs & 0x7);
|
|
break;
|
|
case RDDEC:
|
|
fprintf (stream, "@-r%d", rd & 0x7);
|
|
break;
|
|
case RDIND:
|
|
fprintf (stream, "@r%d", rd & 0x7);
|
|
break;
|
|
case RSIND:
|
|
fprintf (stream, "@r%d", rs & 0x7);
|
|
break;
|
|
case ABS8SRC:
|
|
case ABS16SRC:
|
|
case ABS16OR8SRC:
|
|
case ABS16ORREL8SRC:
|
|
case ABS16OR8DST:
|
|
case ABS16DST:
|
|
case ABS8DST:
|
|
fprintf (stream, "@0x%x", (unsigned) abs);
|
|
break;
|
|
case MEMIND:
|
|
fprintf (stream, "@@%d (%x)", abs, abs);
|
|
break;
|
|
case DISP8:
|
|
fprintf (stream, ".%s%d (%x)", (char) abs > 0 ? "+" : "", (char) abs,
|
|
addr + (char) abs + 2);
|
|
break;
|
|
case DISPSRC:
|
|
case DISPDST:
|
|
fprintf (stream, "@(0x%x,r%d)", abs, rdisp & 0x7);
|
|
break;
|
|
case CCR:
|
|
fprintf (stream, "ccr");
|
|
break;
|
|
case KBIT:
|
|
fprintf (stream, "#%d", abs);
|
|
break;
|
|
default:
|
|
abort ();
|
|
}
|
|
hadone = 1;
|
|
args++;
|
|
}
|
|
}
|
|
return q->length;
|
|
}
|
|
|
|
void
|
|
decode (p, fetch, size)
|
|
struct h8_opcode *p;
|
|
int fetch;
|
|
int size;
|
|
{
|
|
int i;
|
|
char *ss = size == 8 ? "BYTE" : "WORD";
|
|
|
|
for (i = 0; p->data.nib[i] != E; i++)
|
|
{
|
|
switch (p->data.nib[i])
|
|
{
|
|
case RS8:
|
|
if (fetch)
|
|
printf ("srca = BYTE_REG(%s);\n", nibs[i]);
|
|
break;
|
|
case RS16 | B30:
|
|
case RS16 | B31:
|
|
case RS16:
|
|
if (fetch)
|
|
printf ("srca = WORD_REG(%s);\n", nibs[i]);
|
|
break;
|
|
case RD8:
|
|
if (fetch)
|
|
printf ("srcb = BYTE_REG(%s);\n", nibs[i]);
|
|
else
|
|
printf ("SET_BYTE_REG(%s,dst);\n", nibs[i]);
|
|
break;
|
|
case RD16 | B30:
|
|
case RD16 | B31:
|
|
case RD16:
|
|
if (fetch)
|
|
printf ("srcb = WORD_REG(%s);\n", nibs[i]);
|
|
else
|
|
printf ("SET_WORD_REG(%s,dst);\n", nibs[i]);
|
|
break;
|
|
case IMM8:
|
|
if (fetch)
|
|
printf ("srca = b1;\n", i);
|
|
break;
|
|
case RSINC:
|
|
case RSINC | B30:
|
|
case RSINC | B31:
|
|
|
|
if (fetch)
|
|
{
|
|
printf("rn = %s &0x7;\n", nibs[i]);
|
|
printf ("srca = %s_MEM(reg[rn]);\n", size == 8 ? "BYTE"
|
|
: "WORD") ;
|
|
printf("reg[rn]+=%d;\n", size/8);
|
|
}
|
|
break;
|
|
case RSIND:
|
|
case RSIND | B30:
|
|
case RSIND | B31:
|
|
if (fetch) {
|
|
printf("lval = WORD_REG(%s);\n", nibs[i]);
|
|
printf("srca = %s_MEM(lval);\n", ss);
|
|
}
|
|
break;
|
|
|
|
case RDIND:
|
|
case RDIND | B30:
|
|
case RDIND | B31:
|
|
if (fetch) {
|
|
printf("rn = %s & 0x7;\n", nibs[i] );
|
|
printf("lval = reg[rn];\n");
|
|
printf("srcb = %s_MEM(lval);\n", size==8 ? "BYTE" : "WORD");
|
|
}
|
|
else
|
|
{
|
|
printf("SET_%s_MEM(lval,dst);\n",ss);
|
|
}
|
|
break;
|
|
|
|
case MEMIND:
|
|
if (fetch)
|
|
{
|
|
printf("lval = WORD_MEM(b1);\n");
|
|
}
|
|
break;
|
|
case RDDEC:
|
|
case RDDEC | B30:
|
|
case RDDEC | B31:
|
|
if (!fetch)
|
|
{
|
|
printf("rn = %s & 0x7;\n", nibs[i]);
|
|
printf("reg[rn]-=%d;\n", size/8);
|
|
printf ("SET_%s_MEM(reg[rn], dst);\n",
|
|
size == 8 ? "BYTE" : "WORD");
|
|
}
|
|
break;
|
|
|
|
case IMM16:
|
|
if (fetch)
|
|
printf ("srca =WORD_IMM;\n", i);
|
|
break;
|
|
case ABS8SRC:
|
|
if (fetch) {
|
|
|
|
printf("lval = (0xff00) + b1;\n");
|
|
printf ("srca = BYTE_MEM(lval);\n");
|
|
}
|
|
|
|
break;
|
|
case ABS8DST:
|
|
if (fetch)
|
|
{
|
|
printf("lval = (0xff00) + b1;\n");
|
|
printf ("srcb = BYTE_MEM(lval);\n");
|
|
}
|
|
else
|
|
{
|
|
printf ("SET_BYTE_MEM(lval,dst);\n");
|
|
}
|
|
break;
|
|
case KBIT:
|
|
if (fetch)
|
|
printf ("srca = KBIT(%d);\n", i);
|
|
break;
|
|
case ABS16ORREL8SRC:
|
|
case ABS16SRC:
|
|
if (fetch)
|
|
{
|
|
printf("lval = ((pc[2] << 8) + pc[3]);\n");
|
|
printf("srca = %s_MEM(lval);\n", size==8 ? "BYTE" : "WORD");
|
|
}
|
|
break;
|
|
case DISPREG|B30:
|
|
case DISPREG|B31:
|
|
case DISPREG:
|
|
printf("rn = %s & 0x7;\n", nibs[i]);
|
|
break;
|
|
case DISPSRC:
|
|
if (fetch)
|
|
{
|
|
printf("lval = 0xffff&((pc[2] << 8) + pc[3] +reg[rn]);\n");
|
|
printf("srca = %s_MEM(lval);\n", size == 8 ? "BYTE" : "WORD");
|
|
}
|
|
break;
|
|
case DISPDST:
|
|
if (fetch)
|
|
{
|
|
printf("lval = 0xffff&((pc[2] << 8) + pc[3] +reg[rn]);\n");
|
|
printf("srcb = %s_MEM(lval);\n", size == 8 ? "BYTE" : "WORD");
|
|
}
|
|
else {
|
|
printf("SET_%s_MEM(lval,dst);\n",ss);
|
|
}
|
|
break;
|
|
case ABS16DST:
|
|
if (fetch)
|
|
{
|
|
printf("lval = ((pc[2] << 8) + pc[3]);\n");
|
|
printf("srcb = WORD_MEM(lval);\n");
|
|
}
|
|
else
|
|
{
|
|
printf ("SET_WORD_MEM(lval,dst);\n", i);
|
|
}
|
|
break;
|
|
case IGNORE:
|
|
break;
|
|
case DISP8:
|
|
printf(" /* DISP8 handled in opcode */\n");
|
|
break;
|
|
default:
|
|
if (p->data.nib[i] > HexF)
|
|
{
|
|
printf("exception = SIGILL;\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define NNIBS 8
|
|
|
|
typedef int keytype[NNIBS];
|
|
struct key
|
|
{
|
|
keytype k;
|
|
int nmatch;
|
|
/* struct h8_opcode *match[200];*/
|
|
};
|
|
|
|
struct key keys[50];
|
|
int nkeys;
|
|
|
|
calckey (p, key)
|
|
struct h8_opcode *p;
|
|
keytype key;
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; (p->data.nib[j] != E); j++)
|
|
{
|
|
if (p->data.nib[j] == RS8 || p->data.nib[j] == RD8)
|
|
p->size = 8;
|
|
if (p->size != 8)
|
|
p->size=16;
|
|
if (p->data.nib[j] > HexF)
|
|
key[j] = p->data.nib[j];
|
|
else
|
|
key[j] = 0;
|
|
}
|
|
for (; j < NNIBS; j++)
|
|
key[j] = 0;
|
|
}
|
|
|
|
lookup (key)
|
|
keytype key;
|
|
{
|
|
int n;
|
|
|
|
/* See if this key matches one already found */
|
|
for (n = 0; n < nkeys; n++)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NNIBS; i++)
|
|
{
|
|
if ((keys[n].k[i]&0x3f) != (key[i]&0x3f))
|
|
break;
|
|
}
|
|
if (i == NNIBS)
|
|
break;
|
|
}
|
|
return n;
|
|
}
|
|
BADNEWS(x) {
|
|
if (x == 0x7c) return 0;
|
|
if (x == 0x7d) return 0;
|
|
if (x == 0x7e) return 0;
|
|
if (x == 0x7f) return 0;
|
|
return 1;
|
|
}
|
|
|
|
sortmodes ()
|
|
{
|
|
/* look through all the addressing modes, work out which ones are unique*/
|
|
struct h8_opcode **p;
|
|
keytype key;
|
|
|
|
int n;
|
|
int i;
|
|
|
|
memset (keys, 0, sizeof (keys));
|
|
|
|
|
|
for (i = 0; i < PTWO; i++)
|
|
{
|
|
p = h8_opcodes_sorted[i];
|
|
while (*p)
|
|
{
|
|
int j;
|
|
int a = 0;
|
|
|
|
if (BADNEWS((*p)->sorted_key)) {
|
|
calckey (*p, key);
|
|
n = lookup (key);
|
|
if (n == nkeys)
|
|
{
|
|
/* No hit, insert */
|
|
memcpy (keys[n].k, key, sizeof (keys[n].k));
|
|
nkeys++;
|
|
}
|
|
/* Link in the p */
|
|
#if 0
|
|
/*e*/ keys[n].match[keys[n].nmatch++] = *p;
|
|
#endif
|
|
}
|
|
(*p)->idx = n;
|
|
p++;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
for (n = 0; n < nkeys; n++)
|
|
{
|
|
printf ("%d %d %d %d %d %d %d %d\n", keys[n][0], keys[n][1], keys[n][2], keys[n][3],
|
|
keys[n][4], keys[n][5], keys[n][6], keys[n][7]);
|
|
|
|
}
|
|
#endif
|
|
|
|
}
|
|
void
|
|
enop ()
|
|
{
|
|
printf ("%s Nop does nothing %s", cs, ce);
|
|
}
|
|
|
|
void
|
|
esleep ()
|
|
{
|
|
printf ("exception = SIGSTOP;\n");
|
|
}
|
|
|
|
rv (x)
|
|
{
|
|
printf ("v= 0;\n");
|
|
}
|
|
|
|
void
|
|
mov (p, s, sz)
|
|
struct h8_opcode *p;
|
|
char *s;
|
|
int sz;
|
|
{
|
|
printf("dst = srca;\n");
|
|
}
|
|
|
|
tn (s)
|
|
{
|
|
/* printf ("n = dst & 0x%x;\n", s == 8 ? 0x80 : 0x8000);*/
|
|
}
|
|
|
|
tz (s)
|
|
{
|
|
/* printf ("z = ~(dst & 0x%x);\n", s == 8 ? 0xff : 0xffff);*/
|
|
}
|
|
|
|
tv (s)
|
|
{
|
|
/* printf ("v = (( (~(srca ^ srcb) & (srca ^ dst))) & (1<<%d));\n", s);*/
|
|
}
|
|
|
|
tc (s)
|
|
{
|
|
printf ("c = dst & 0x%x;\n", 1 << s);
|
|
}
|
|
|
|
log_flags (s)
|
|
{
|
|
tn (s);
|
|
tz (s);
|
|
rv (s);
|
|
}
|
|
|
|
alu_flags (s)
|
|
{
|
|
tn (s);
|
|
tz (s);
|
|
tv (s);
|
|
tc (s);
|
|
}
|
|
|
|
void
|
|
bclr (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("dst = srca & ~(1<<srcb);\n");
|
|
}
|
|
|
|
void
|
|
biand (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("c =(C && ! ((srca >> srcb)&1));\n");
|
|
}
|
|
|
|
void
|
|
bild (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("c = ( ! ((srca >> srcb)&1));\n");
|
|
}
|
|
|
|
|
|
void
|
|
andc (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("SET_CCR(GET_CCR() & srca);\n");
|
|
}
|
|
|
|
void
|
|
addx (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("dst = srca + srcb+ (c != 0);\n");
|
|
}
|
|
|
|
void
|
|
subx (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
printf ("dst = srcb - srca - (c != 0);\n");
|
|
}
|
|
|
|
void
|
|
add (p, s, sz)
|
|
struct h8_opcode *p;
|
|
char *s;
|
|
int sz;
|
|
{
|
|
printf ("%s;\n", s);
|
|
alu_flags (sz);
|
|
|
|
}
|
|
|
|
void
|
|
adds (p, s)
|
|
struct h8_opcode *p;
|
|
char *s;
|
|
{
|
|
printf ("%s;\n", s);
|
|
}
|
|
|
|
void
|
|
bra (p, a)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
{
|
|
printf ("if (%s) npc += (((char *)pc)[1]);\n", a);
|
|
}
|
|
|
|
|
|
void
|
|
bsr (p, a)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
{
|
|
printf("reg[7]-=2;\n");
|
|
printf("tmp = reg[7];\n");
|
|
printf ("SET_WORD_MEM(tmp, npc-mem);\n");
|
|
printf ("npc += (((char *)pc)[1]);\n");
|
|
}
|
|
|
|
void
|
|
cmp (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
decode(p, 1, s);
|
|
printf("srca = -srca;\n");
|
|
printf ("dst = srca + srcb;\n");
|
|
}
|
|
|
|
void
|
|
jsr (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf("if (b1 == 0xc4) {\n");
|
|
printf("printf(\"%%c\", reg[2]);\n");
|
|
printf("}\n");
|
|
printf("else {\n");
|
|
printf("reg[7]-=2;\n");
|
|
printf("tmp = reg[7];\n");
|
|
printf ("SET_WORD_MEM(tmp, npc-mem);\n");
|
|
printf ("npc = lval + mem;\n");
|
|
printf("}");
|
|
}
|
|
|
|
void
|
|
jmp (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("npc = lval + mem;\n");
|
|
}
|
|
|
|
void
|
|
rts (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("tmp = reg[7];\n");
|
|
printf ("reg[7]+=2;\n");
|
|
printf ("npc = mem + WORD_MEM(tmp);\n");
|
|
}
|
|
|
|
void
|
|
setf (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("tmp = GET_CCR();\n");
|
|
printf ("tmp %s= srca;\n",a);
|
|
}
|
|
|
|
void
|
|
bpt (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("exception = SIGTRAP;\n");
|
|
printf( "npc = pc;\n");
|
|
}
|
|
|
|
void
|
|
log (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("dst = srcb %s srca;\n", a);
|
|
}
|
|
|
|
void
|
|
ulog (p, a, s)
|
|
struct h8_opcode *p;
|
|
char *a;
|
|
int s;
|
|
{
|
|
printf ("dst = %s srcb ;\n", a);
|
|
}
|
|
|
|
void
|
|
nop()
|
|
{
|
|
}
|
|
|
|
void
|
|
rotl()
|
|
{
|
|
printf("c = srcb & 0x80;\n");
|
|
printf("dst = srcb << 1;\n");
|
|
printf("if (c) dst|=1;\n");
|
|
}
|
|
void
|
|
rotr()
|
|
{
|
|
printf("c = srcb & 1;\n");
|
|
printf("dst = srcb >> 1;\n");
|
|
printf("if (c) dst|=0x80;\n");
|
|
}
|
|
|
|
void
|
|
rotxl()
|
|
{
|
|
printf("tmp = srcb & 0x80;\n");
|
|
printf("dst = srcb << 1;\n");
|
|
printf("if (c) dst|=1;\n");
|
|
printf("c = tmp;\n");
|
|
}
|
|
void
|
|
rotxr()
|
|
{
|
|
printf("tmp = srcb & 1;\n");
|
|
printf("dst = srcb >> 1;\n");
|
|
printf("if (c) dst|=0x80;\n");
|
|
printf("c = tmp;\n");
|
|
}
|
|
|
|
|
|
void
|
|
shal()
|
|
{
|
|
printf("c = srcb&0x80;\n");
|
|
printf("dst = srcb << 1;\n");
|
|
}
|
|
|
|
void
|
|
shar()
|
|
{
|
|
printf("c = srcb&0x1;\n");
|
|
printf("if (srcb&0x80) dst = (srcb>>1) | 0x80;\n");
|
|
printf("else dst = (srcb>>1) &~ 0x80;\n");
|
|
}
|
|
|
|
void
|
|
shll()
|
|
{
|
|
printf("c = srcb&0x80;\n");
|
|
printf("dst = srcb << 1;\n");
|
|
}
|
|
|
|
void
|
|
shlr()
|
|
{
|
|
printf("c = srcb&0x1;\n");
|
|
printf("dst = (srcb>>1) &~ 0x80;\n");
|
|
}
|
|
|
|
void
|
|
divxu()
|
|
{
|
|
printf("srca = BYTE_REG(pc[1]>>4);\n");
|
|
printf("srcb = WORD_REG(pc[1]&0x7);\n");
|
|
printf("n = srca & 0x80\;\n");
|
|
printf("z = !srca;\n");
|
|
printf("if (srca) dst = srcb / srca;tmp = srcb %% srca;\n");
|
|
printf("reg[pc[1]&0x7] = (dst & 0xff) | (tmp << 8);\n");
|
|
}
|
|
void
|
|
mulxu()
|
|
{
|
|
printf("srca = BYTE_REG(pc[1]>>4);\n");
|
|
printf("srcb = WORD_REG(pc[1]&0x7);\n");
|
|
printf("dst = (srcb&0xff) * srca;\n");
|
|
printf("reg[pc[1]&0x7] = dst;\n");
|
|
}
|
|
char saf[]="goto setflags;";
|
|
char sf[] = "goto shiftflags;";
|
|
char af8[] = "goto aluflags8;";
|
|
char af16[] = "goto aluflags16;";
|
|
char lf[] = "goto logflags;";
|
|
char mf8[]= "goto movflags8;";
|
|
char mf16[]= "goto movflags16;";
|
|
char nx[] = "goto next;";
|
|
struct
|
|
{
|
|
char *ftype;
|
|
int decode;
|
|
char *name;
|
|
void (*func) ();
|
|
char *arg;
|
|
int size;
|
|
|
|
}
|
|
|
|
|
|
table [] =
|
|
{
|
|
saf,1,"orc",setf,"|",0,
|
|
saf,1,"xorc",setf,"^",0,
|
|
saf,1,"andc",setf,"&",0,
|
|
0,1, "bild", bild, 0, 0,
|
|
0,1, "nop", nop, 0, 0,
|
|
0,1, "bclr", bclr, 0, 0,
|
|
0,1, "biand", biand, 0, 0,
|
|
0,1, "bra", bra, "1", 0,
|
|
0,1, "brn", bra, "0", 0,
|
|
0,1, "bf", bra, "0", 0,
|
|
0,1, "bhi", bra, "(C||Z)==0", 0,
|
|
0,1, "bls", bra, "(C||Z)==1", 0,
|
|
0,1, "bcs", bra, "C==1", 0,
|
|
0,1, "bcc", bra, "C==0", 0,
|
|
0,1, "bpl", bra, "N==0", 0,
|
|
0,1, "bmi", bra, "N==1", 0,
|
|
0,1, "bvs", bra, "V==1", 0,
|
|
0,1, "bvc", bra, "V==0", 0,
|
|
0,1, "bge", bra, "(N^V)==0", 0,
|
|
0,1, "bgt", bra, "(Z|(N^V))==0", 0,
|
|
0,1, "blt", bra, "(N^V)==1", 0,
|
|
0,1, "ble", bra, "(Z|(N^V))==1", 0,
|
|
0,1, "beq", bra, "Z==1", 0,
|
|
0,1, "bne", bra, "Z==0", 0,
|
|
0,1, "bsr", bsr, "", 0,
|
|
0,1, "jsr", jsr, 0, 0,
|
|
0,1, "jmp", jmp, 0, 0,
|
|
0,0, "rts", rts, 0, 0,
|
|
0,1, "andc", andc, 0, 0,
|
|
0,1, "nop", enop, 0, 0,
|
|
sf,1, "shal",shal,0,0,
|
|
sf,1, "shar",shar,0,0,
|
|
sf,1, "shll",shll,0,0,
|
|
sf,1, "shlr",shlr,0,0,
|
|
sf,1, "rotxl",rotxl,0,0,
|
|
sf,1, "rotxr",rotxr,0,0,
|
|
sf,1, "rotl",rotl,0,0,
|
|
sf,1, "rotr",rotr,0,0,
|
|
lf,1, "xor", log, "^",0,
|
|
lf,1, "and", log, "&",0,
|
|
lf,1, "or", log, "|",0,
|
|
lf,1,"not", ulog," ~",0,
|
|
lf,1,"neg", ulog," - ",0,
|
|
0,1, "adds", adds, "dst = srca + srcb", 0,
|
|
0,1, "subs", adds, "srca = -srca; dst = srcb + srca", 0,
|
|
af8,1, "add.b", add, "dst = srca + srcb", 8,
|
|
af16,1, "add.w", add, "dst = srca + srcb", 16,
|
|
af16,1, "sub.w", add, "srca = -srca; dst = srcb + srca", 16,
|
|
af8,1, "sub.b", add, "srca = -srca; dst = srcb + srca", 8,
|
|
af8,1, "addx", addx, 0, 8,
|
|
af8,1, "subx", subx, 0, 8,
|
|
af8,0, "cmp.b", cmp, 0, 8,
|
|
af16,0, "cmp.w", cmp, 0, 16,
|
|
0,1, "sleep", esleep, 0, 0,
|
|
0,0, "bpt", bpt, 0, 8,
|
|
nx,0, "divxu", divxu,0,0,
|
|
nx,0, "mulxu", mulxu,0,0,
|
|
mf8,1, "mov.b", mov, 0, 8,
|
|
mf16,1, "mov.w", mov, 0, 16,
|
|
0, 0
|
|
};
|
|
|
|
edo (p)
|
|
struct h8_opcode *p;
|
|
{
|
|
int i;
|
|
|
|
printf ("%s %s %s\n", cs, p->name, ce);
|
|
|
|
for (i = 0; table[i].name; i++)
|
|
{
|
|
if (strcmp (table[i].name, p->name) == 0)
|
|
{
|
|
printf ("{\n");
|
|
if (table[i].decode) decode(p, 1,p->size);
|
|
printf ("cycles += %d;\n", p->time);
|
|
printf ("npc = pc + %d;\n", p->length);
|
|
table[i].func (p, table[i].arg, table[i].size);
|
|
if (table[i].decode) decode(p, 0,p->size);
|
|
if (table[i].ftype) printf(table[i].ftype);
|
|
else printf ("goto next;\n");
|
|
printf ("}\n");
|
|
return;
|
|
}
|
|
}
|
|
printf ("%s not found %s\n", cs, ce);
|
|
printf("exception = SIGILL;\n");
|
|
printf ("break;\n");
|
|
}
|
|
|
|
int
|
|
owrite (i)
|
|
{
|
|
/* write if statements to select the right opcode */
|
|
struct h8_opcode **p;
|
|
int needand = 1;
|
|
|
|
p = h8_opcodes_sorted[i];
|
|
printf ("case 0x%03x:\n", i);
|
|
|
|
if (p[1] == 0)
|
|
{
|
|
/* See if the next few also match */
|
|
while (h8_opcodes_sorted[i + 1][0] == *p)
|
|
{
|
|
i++;
|
|
printf ("case 0x%03x:\n", i);
|
|
}
|
|
|
|
/* Dont need any if's this is the only one */
|
|
edo (*p);
|
|
}
|
|
else
|
|
{
|
|
while (*p)
|
|
{
|
|
/* start two nibbles in since we know we match in the first byte */
|
|
int c;
|
|
int nib = 2;
|
|
int byte = 1;
|
|
int mask1[5];
|
|
int mask0[5];
|
|
int nibshift = 4;
|
|
int any = 0;
|
|
|
|
for (c = 0; c < 5; c++)
|
|
{
|
|
mask1[c] = 0;
|
|
mask0[c] = 0;
|
|
}
|
|
printf ("%s %x%x", cs, (*p)->data.nib[0], (*p)->data.nib[1]);
|
|
while ((c = (*p)->data.nib[nib]) != E)
|
|
{
|
|
if (c & B30)
|
|
{
|
|
/* bit 3 must be zero */
|
|
mask0[byte] |= 0x8 << nibshift;
|
|
printf ("0");
|
|
any = 1;
|
|
}
|
|
else if (c & B31)
|
|
{
|
|
/* bit 3 must be one */
|
|
mask1[byte] |= 0x8 << nibshift;
|
|
printf ("8");
|
|
any = 1;
|
|
}
|
|
else if (c <= HexF)
|
|
{
|
|
mask0[byte] |= ((~c) & 0xf) << nibshift;
|
|
mask1[byte] |= (c & 0xf) << nibshift;
|
|
printf ("%x", c);
|
|
any = 1;
|
|
}
|
|
else
|
|
{
|
|
printf ("x");
|
|
}
|
|
nib++;
|
|
if (nibshift == 4)
|
|
{
|
|
nibshift = 0;
|
|
}
|
|
else
|
|
{
|
|
byte++;
|
|
nibshift = 4;
|
|
}
|
|
}
|
|
printf ("*/\n");
|
|
if (any)
|
|
{
|
|
printf ("if (");
|
|
needand = 0;
|
|
for (c = 1; c < byte; c++)
|
|
{
|
|
if (mask0[c] | mask1[c])
|
|
{
|
|
if (needand)
|
|
printf ("\n&&");
|
|
printf ("((pc[%d]&0x%02x)==0x%x)",
|
|
c, mask0[c] | mask1[c], mask1[c]);
|
|
needand = 1;
|
|
}
|
|
}
|
|
printf (")\n");
|
|
}
|
|
edo (*p);
|
|
p++;
|
|
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
print_key (i)
|
|
{
|
|
int j;
|
|
|
|
printf ("%s", cs);
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
/* printf ("(0x%02x ", keys[i].k[j]);*/
|
|
if (keys[i].k[j] & B30)
|
|
printf ("B30");
|
|
else if (keys[i].k[j] & B31)
|
|
printf ("B31");
|
|
switch (keys[i].k[j])
|
|
{
|
|
case KBIT:
|
|
printf ("KBIT");
|
|
break;
|
|
case IMM3:
|
|
printf ("IMM3");
|
|
break;
|
|
case RD8:
|
|
printf ("RD8");
|
|
break;
|
|
case RD16:
|
|
printf ("RD16");
|
|
break;
|
|
case RS8:
|
|
printf ("RS8");
|
|
break;
|
|
case RS16:
|
|
printf ("RS16");
|
|
break;
|
|
case IMM8:
|
|
printf ("IMM8");
|
|
break;
|
|
case IMM16:
|
|
printf ("IMM16");
|
|
break;
|
|
case CCR:
|
|
printf ("CCR");
|
|
break;
|
|
case ABS8SRC:
|
|
printf ("ABS8SRC");
|
|
break;
|
|
case ABS8DST:
|
|
printf ("ABS8SDST");
|
|
break;
|
|
case DISP8:
|
|
printf ("DISP8");
|
|
break;
|
|
case ABS16SRC:
|
|
printf ("ABS16SRC");
|
|
break;
|
|
case ABS16OR8SRC:
|
|
printf ("ABS16OR8SRC");
|
|
break;
|
|
case ABS16DST:
|
|
printf ("ABS16SDST");
|
|
break;
|
|
case ABS16OR8DST:
|
|
printf ("ABS16OR8SDST");
|
|
break;
|
|
case DISPSRC:
|
|
printf ("DISPSRC");
|
|
break;
|
|
case DISPDST:
|
|
printf ("DISPSDST");
|
|
break;
|
|
case DISPREG:
|
|
printf ("DISPREG");
|
|
break;
|
|
case RDDEC:
|
|
printf ("RDDEC");
|
|
break;
|
|
case RSINC:
|
|
printf ("RSINC");
|
|
break;
|
|
case RDIND:
|
|
printf ("RDIND");
|
|
break;
|
|
case RSIND:
|
|
printf ("RSIND");
|
|
break;
|
|
case MEMIND:
|
|
printf ("MEMIND");
|
|
break;
|
|
case ABS16ORREL8SRC:
|
|
printf ("ABS16ORREL8SRC");
|
|
break;
|
|
case IGNORE:
|
|
printf ("IGNORE");
|
|
break;
|
|
default:
|
|
printf ("**");
|
|
break;
|
|
}
|
|
printf (" ");
|
|
}
|
|
printf ("%s\n", ce);
|
|
}
|
|
|
|
dofetch (fetch)
|
|
int fetch;
|
|
{
|
|
int i;
|
|
int done_for[PTWO];
|
|
memset (done_for, 0, sizeof (done_for));
|
|
printf ("switch (b0) {\n");
|
|
for (i = 0; i < nkeys; i++)
|
|
{
|
|
struct h8_opcode *p;
|
|
struct h8_opcode *l = 0;
|
|
int k;
|
|
|
|
printf ("%s KEY %d %s\n", cs,i,ce);
|
|
print_key (i);
|
|
|
|
{
|
|
int j;
|
|
|
|
l = 0;
|
|
for (p = h8_opcodes; p->name; p++)
|
|
{
|
|
int key[8];
|
|
|
|
if (p->idx == i && p->name != empty)
|
|
{
|
|
l = p;
|
|
if (done_for[p->sorted_key] != i + 1000)
|
|
{
|
|
done_for[p->sorted_key] = i + 1000;
|
|
printf ("case 0x%03x:\n", p->sorted_key);
|
|
printf("%s %s %s\n", cs, p->name, ce);
|
|
}
|
|
}
|
|
}
|
|
if (l)
|
|
{
|
|
|
|
decode (l, fetch, l->size);
|
|
printf ("break;\n");
|
|
}
|
|
else
|
|
printf (" /* NO */\n");
|
|
}
|
|
}
|
|
printf ("}\n");
|
|
}
|
|
|
|
remove_dups()
|
|
{
|
|
struct h8_opcode *s;
|
|
struct h8_opcode *d;
|
|
for (d = s = h8_opcodes; s->name; s++)
|
|
{
|
|
int doit = 1;
|
|
if (strcmp(s->name,"push") ==0) doit = 0;
|
|
if (strcmp(s->name,"pop") ==0) doit = 0;
|
|
if (doit)
|
|
{
|
|
*d++ = *s;
|
|
}
|
|
}
|
|
*d++ = *s++;
|
|
}
|
|
main ()
|
|
{
|
|
int i;
|
|
remove_dups();
|
|
init ();
|
|
|
|
sortmodes ();
|
|
|
|
#if 0
|
|
printf("%s fetch the args %s\n", cs,ce);
|
|
dofetch (1);
|
|
#endif
|
|
printf("%s do the operation %s\n", cs,ce);
|
|
printf ("switch (b0) \n{\n");
|
|
for (i = 0; i < PTWO; i++)
|
|
{
|
|
i = owrite (i);
|
|
}
|
|
printf ("}\n");
|
|
#if 0
|
|
printf("%s store the result %s\n", cs,ce);
|
|
dofetch (0);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|