binutils-gdb/sim/h8300/writecode.c

1151 lines
19 KiB
C

/* code generator for the Hitachi H8/300 architecture simulator.
Copyright (C) 1993 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. */
/* This program reads the H8/300 opcode table and writes out
a large switch statement to understand the opcodes (with ifs if
there is more than one opcode per case) and code to do the stuff */
#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];
char *cs = "/*";
char *ce = "*/";
/* How to get at nibble n from the instruction */
char *nibs[] =
{
"foo",
"(b0&0xf)",
"((b1>>4)&0xf)",
"((b1)&0xf)",
"((pc[1]>>12)&0xf)",
"((pc[1]>>8)&0xf)",
"((pc[1]>>4)&0xf)",
"((pc[1])&0xf)",
0, 0};
/* how to get at the 3 bit immediate in the instruction */
char *imm3[] =
{"foo",
"foo",
"((b1>>4)&0x7)",
"foo",
"foo",
"foo",
"(pc[1]>>4)&0x7"};
/* How to get at a byte register from an index in the instruction at
nibble n */
char *breg[] =
{"foo",
"*(blow[b0])",
"*(bhigh[b1])",
"*(blow[b1])"};
/* How to get at a word register from an index in the instruction at
nibble n */
char *wreg[] =
{"foo",
"*(wlow[b0])",
"*(whigh[b1])",
"*(wlow[b1])"};
#define sorted_key noperands
/* sort the opcode table into h8_opcodes_sorted[0..255] */
static void
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;
}
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;
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;
}
}
/* either fetch srca&srcb or store dst */
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 = %s;\n", breg[i]);
break;
case RS16 | B30:
case RS16 | B31:
case RS16:
if (fetch)
printf ("srca = %s;\n", wreg[i]);
break;
case RD8:
if (fetch)
printf ("srcb = %s;\n", breg[i]);
else
printf ("%s = dst;\n", breg[i]);
break;
case RD16 | B30:
case RD16 | B31:
case RD16:
if (fetch)
printf ("srcb = %s;\n", wreg[i]);
else
printf ("%s =dst;\n", wreg[i]);
break;
case IMM8:
if (fetch)
printf ("srca = b1;\n");
break;
case RSINC:
case RSINC | B30:
case RSINC | B31:
if (fetch)
{
printf ("srca = %s_MEM(%s);\n", ss, wreg[i]);
printf ("%s+=%d;\n", wreg[i], size / 8);
}
break;
case RSIND:
case RSIND | B30:
case RSIND | B31:
if (fetch)
{
printf ("lval = %s;\n", wreg[i]);
printf ("srca = %s_MEM(lval);\n", ss);
}
break;
case RDIND:
case RDIND | B30:
case RDIND | B31:
if (fetch)
{
printf ("lval = %s;\n", wreg[i]);
printf ("srcb = %s_MEM(lval);\n", ss);
}
else
{
printf ("SET_%s_MEM(lval,dst);\n", ss);
}
break;
case MEMIND:
if (fetch)
{
printf ("lval = pc[1];\n");
}
break;
case RDDEC:
case RDDEC | B30:
case RDDEC | B31:
if (!fetch)
{
printf ("%s -=%d;\n", wreg[i], size / 8);
printf ("SET_%s_MEM(%s, dst);\n", ss, wreg[i]);
}
break;
case IMM3:
case IMM3 | B31:
case IMM3 | B30:
if (fetch)
printf ("srca = %s;\n", imm3[i]);
break;
case IMM16:
if (fetch)
printf ("srca =( pc[1]);\n");
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 = ((b1&0x80)?2:1);\n");
break;
case ABS16ORREL8SRC:
case ABS16SRC:
if (fetch)
{
printf ("lval = pc[1];\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[1] +reg[rn]);\n");
printf ("srca = %s_MEM(lval);\n", size == 8 ? "BYTE" : "WORD");
}
break;
case DISPDST:
if (fetch)
{
printf ("lval = 0xffff&(pc[1] +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[1]);\n");
printf ("srcb = %s_MEM(lval);\n", ss);
}
else
{
printf ("SET_%s_MEM(lval,dst);\n", ss);
}
break;
case IGNORE:
break;
case DISP8:
printf (" /* DISP8 handled in opcode */\n");
break;
default:
if (p->data.nib[i] > HexF)
{
printf ("saved_state.exception = SIGILL;\n");
}
}
}
}
static void
esleep ()
{
printf ("saved_state.exception = SIGSTOP;\n");
}
static void
mov (p, s, sz)
struct h8_opcode *p;
char *s;
int sz;
{
printf ("dst = srca;\n");
}
static void
andc (p)
struct h8_opcode *p;
{
printf ("SET_CCR(GET_CCR() & srca);\n");
}
static void
addx (p)
struct h8_opcode *p;
{
printf ("dst = srca + srcb+ (c != 0);\n");
}
static void
subx (p)
struct h8_opcode *p;
{
printf ("dst = srcb - srca - (c != 0);\n");
}
static void
add (p, s, sz)
struct h8_opcode *p;
char *s;
int sz;
{
printf ("%s;\n", s);
}
static void
adds (p, s)
struct h8_opcode *p;
char *s;
{
printf ("%s;\n", s);
}
static void
bra (p, a)
struct h8_opcode *p;
char *a;
{
printf ("if (%s) npc += ((char )b1)>>1;\n", a);
}
static 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-saved_state.mem)*2);\n");
printf ("npc += ((char)b1)>>1;\n");
}
static 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");
}
static
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-saved_state.mem)*2);\n");
printf ("npc = (lval>>1) + saved_state.mem;\n");
printf ("}");
}
static void
jmp (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("npc = (lval>>1) + saved_state.mem;\n");
}
static 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 = saved_state.mem + (WORD_MEM(tmp)>>1);\n");
}
static void
rte (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("reg[7]+=2;\n");
printf ("tmp = reg[7];\n");
printf ("reg[7]+=2;\n");
printf ("SET_CCR(tmp);\n");
printf ("npc = saved_state.mem + (WORD_MEM(tmp)>>1);\n");
}
static void
setf (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("tmp = GET_CCR();\n");
printf ("tmp %s= srca;\n", a);
}
static void
bpt (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("saved_state.exception = SIGTRAP;\n");
printf ("npc = pc;\n");
}
static void
log (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("dst = srcb %s srca;\n", a);
}
static void
ulog (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("dst = %s srcb ;\n", a);
}
static void
nop ()
{
}
static void
rotl ()
{
printf ("c = srcb & 0x80;\n");
printf ("dst = srcb << 1;\n");
printf ("if (c) dst|=1;\n");
}
static void
rotr ()
{
printf ("c = srcb & 1;\n");
printf ("dst = srcb >> 1;\n");
printf ("if (c) dst|=0x80;\n");
}
static void
rotxl ()
{
printf ("tmp = srcb & 0x80;\n");
printf ("dst = srcb << 1;\n");
printf ("if (c) dst|=1;\n");
printf ("c = tmp;\n");
}
static void
rotxr ()
{
printf ("tmp = srcb & 1;\n");
printf ("dst = srcb >> 1;\n");
printf ("if (c) dst|=0x80;\n");
printf ("c = tmp;\n");
}
static void
shal ()
{
printf ("c = srcb&0x80;\n");
printf ("dst = srcb << 1;\n");
}
static
void
shar ()
{
printf ("c = srcb&0x1;\n");
printf ("if (srcb&0x80) dst = (srcb>>1) | 0x80;\n");
printf ("else dst = (srcb>>1) &~ 0x80;\n");
}
static
void
shll ()
{
printf ("c = srcb&0x80;\n");
printf ("dst = srcb << 1;\n");
}
static
void
shlr ()
{
printf ("c = srcb&0x1;\n");
printf ("dst = (srcb>>1) &~ 0x80;\n");
}
static
void
divxu ()
{
printf ("srca = %s;\n", breg[2]);
printf ("srcb = %s;\n", wreg[3]);
printf ("n = srca & 0x80;\n");
printf ("z = !srca;\n");
printf ("if (srca) dst = srcb / srca;tmp = srcb %% srca;\n");
printf ("%s = (dst & 0xff) | (tmp << 8);\n", wreg[3]);
}
static
void
mulxu ()
{
printf ("srca = %s;\n", breg[2]);
printf ("srcb = %s;\n", wreg[3]);
printf ("dst = (srcb&0xff) * srca;\n");
printf ("%s = dst;\n", wreg[3]);
}
static
void
inc ()
{
printf ("dst = %s;\n", breg[3]);
printf ("v = (dst==0x7f);\n");
printf ("dst++;\n");
printf ("%s= dst;\n", breg[3]);
}
static
void
bit (p, a, s)
struct h8_opcode *p;
char *a;
int s;
{
printf ("%s\n", a);
}
static
void
dec ()
{
printf ("dst = %s;\n", breg[3]);
printf ("v = (dst==0x80);\n");
printf ("dst--;\n");
printf ("%s = dst;\n", breg[3]);
}
char saf[] = "goto setflags;";
char sf[] = "goto shiftflags;";
char af8[] = "goto aluflags8;";
char af16[] = "goto aluflags16;";
char lf[] = "goto logflags;";
char icf[] = "goto incflags;";
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 [] =
{
{
nx, 1, "bld", bit, "dst = srcb; c = (srcb>>srca)&1;", 8
}
,
{
nx, 1, "bild", bit, "dst = srcb; c = !((srcb>>srca)&1);", 8
}
,
{
nx, 1, "band", bit, "dst = srcb; c = C &&((srcb>>srca)&1);", 8
}
,
{
nx, 1, "biand", bit, "dst = srcb; c = C &&(!((srcb>>srca)&1));", 8
}
,
{
nx, 1, "bior", bit, "dst = srcb; c = C ||(!((srcb>>srca)&1));", 8
}
,
{
nx, 1, "bor", bit, "dst = srcb; c = C ||(((srcb>>srca)&1));", 8
}
,
{
nx, 1, "bixor", bit, "dst = srcb; c = C ^(!((srcb>>srca)&1));", 8
}
,
{
nx, 1, "bxor", bit, "dst = srcb; c = C ^(((srcb>>srca)&1));", 8
}
,
{
nx, 1, "bnot", bit, "dst = srcb ^ (1<<srca);", 8
}
,
{
nx, 1, "bclr", bit, "dst = srcb & ~(1<<srca);", 8
}
,
{
nx, 1, "bset", bit, "dst = srcb | (1<<srca);", 8
}
,
{
nx, 1, "bst", bit, "dst = (srcb & ~(1<<srca))| ((C)<<srca);", 8
}
,
{
nx, 1, "bist", bit, "dst = (srcb & ~(1<<srca))| ((!C)<<srca);", 8
}
,
{
nx, 1, "btst", bit, "dst = srcb; z = !((srcb>>srca)&1);", 8
}
,
{
icf, 0, "dec", dec, 0, 0
}
,
{
icf, 0, "inc", inc, 0, 0
}
,
{
saf, 1, "orc", setf, "|", 0
}
,
{
saf, 1, "xorc", setf, "^", 0
}
,
{
saf, 1, "andc", setf, "&", 0
}
,
{
nx, 1, "nop", nop, 0, 0
}
,
{
nx, 1, "bra", bra, "1", 0
}
,
{
nx, 1, "brn", bra, "0", 0
}
,
{
nx, 1, "bhi", bra, "(C||Z)==0", 0
}
,
{
nx, 1, "bls", bra, "(C||Z)==1", 0
}
,
{
nx, 1, "bcs", bra, "C==1", 0
}
,
{
nx, 1, "bcc", bra, "C==0", 0
}
,
{
nx, 1, "bpl", bra, "N==0", 0
}
,
{
nx, 1, "bmi", bra, "N==1", 0
}
,
{
nx, 1, "bvs", bra, "V==1", 0
}
,
{
nx, 1, "bvc", bra, "V==0", 0
}
,
{
nx, 1, "bge", bra, "(N^V)==0", 0
}
,
{
nx, 1, "bgt", bra, "(Z|(N^V))==0", 0
}
,
{
nx, 1, "blt", bra, "(N^V)==1", 0
}
,
{
nx, 1, "ble", bra, "(Z|(N^V))==1", 0
}
,
{
nx, 1, "beq", bra, "Z==1", 0
}
,
{
nx, 1, "bne", bra, "Z==0", 0
}
,
{
nx, 1, "bsr", bsr, "", 0
}
,
{
nx, 1, "jsr", jsr, 0, 0
}
,
{
nx, 1, "jmp", jmp, 0, 0
}
,
{
nx, 0, "rts", rts, 0, 0
}
,
{
nx, 0, "rte", rte, 0, 0
}
,
{
nx, 1, "andc", andc, 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
}
,
{
nx, 1, "adds", adds, "dst = srca + srcb", 0
}
,
{
nx, 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
}
,
{
nx, 1, "sleep", esleep, 0, 0
}
,
{
nx, 0, "bpt", bpt, 0, 8
}
,
{
nx, 0, "divxu", divxu, 0, 0
}
,
{
nx, 0, "mulxu", mulxu, 0, 0
}
,
{
mf8, 1, "mov.b", mov, 0, 8
}
,
{
mf8, 1, "movtpe", mov, 0, 8
}
,
{
mf8, 1, "movfpe", mov, 0, 8
}
,
{
mf16, 1, "mov.w", mov, 0, 16
}
,
{
0
}
};
static
void
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, table[i].size);
printf ("cycles += %d;\n", p->time);
printf ("npc = pc + %d;\n", p->length / 2);
table[i].func (p, table[i].arg, table[i].size);
if (table[i].decode)
decode (p, 0, table[i].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 ("saved_state.exception = SIGILL;\n");
printf ("break;\n");
}
static
int
owrite (i)
int 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])
{
int sh;
if (needand)
printf ("\n&&");
if (c & 1)
sh = 0;
else
sh = 8;
if (c / 2 == 0 && sh == 0)
printf ("((b1&0x%x)==0x%x)", mask0[c] | mask1[c],
mask1[c]);
else
{
printf ("((pc[%d]&(0x%02x<<%d))==(0x%x<<%d))",
c / 2, mask0[c] | mask1[c], sh,
mask1[c], sh);
}
needand = 1;
}
}
printf (")\n");
}
edo (*p);
p++;
}
}
return i;
}
static
void
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, "bhs") == 0)
doit = 0;
if (strcmp (s->name, "blo") == 0)
doit = 0;
if (strcmp (s->name, "bt") == 0)
doit = 0;
if (strcmp (s->name, "bf") == 0)
doit = 0;
if (strcmp (s->name, "pop") == 0)
doit = 0;
if (doit)
{
*d++ = *s;
}
}
*d++ = *s++;
}
int
main ()
{
int i;
remove_dups ();
init ();
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");
return 0;
}