snapshot, upper opcode table done, modulo testing

This commit is contained in:
Doug Evans 1998-01-14 20:13:07 +00:00
parent 3b542e9430
commit 3f89726318

View File

@ -57,7 +57,18 @@ PRINT_FN (dotdest);
PARSE_FN (vfreg);
PRINT_FN (vfreg);
/* Various types of ARC operands, including insn suffixes.
PARSE_FN (bc);
PRINT_FN (bc);
PARSE_FN (ftregbc);
PRINT_FN (ftregbc);
PARSE_FN (accdest);
PRINT_FN (accdest);
PARSE_FN (xyz);
/* Various types of TXVU operands, including insn suffixes.
Fields are:
@ -68,37 +79,95 @@ PRINT_FN (vfreg);
const struct txvu_operand txvu_operands[] =
{
/* place holder (??? not sure if needed) */
/* place holder (??? not sure if needed) */
#define UNUSED 128
{ 0 },
/* Destination indicator, with leading '.'. */
/* Destination indicator, with leading '.'. */
#define DOTDEST (UNUSED + 1)
{ 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest },
/* ft reg */
/* ft reg */
#define FTREG (DOTDEST + 1)
{ 5, TXVU_SHIFT_FTREG, 0, parse_vfreg, 0, 0, print_vfreg },
/* fs reg */
/* fs reg */
#define FSREG (FTREG + 1)
{ 5, TXVU_SHIFT_FSREG, 0, parse_vfreg, 0, 0, print_vfreg },
/* fd reg */
/* fd reg */
#define FDREG (FSREG + 1)
{ 5, TXVU_SHIFT_FDREG, 0, parse_vfreg, 0, 0, print_vfreg },
/* broadcast */
#define BC (FDREG + 1)
{ 2, 0, 0, parse_bc, 0, 0, print_bc },
/* ftreg in broadcast case */
#define FTREGBC (BC + 1)
{ 5, TXVU_SHIFT_FTREG, 0, parse_ftregbc, 0, 0, print_ftregbc },
/* accumulator dest */
#define ACCDEST (FTREGBC + 1)
{ 0, 0, TXVU_OPERAND_FAKE, parse_accdest, 0, 0, print_accdest },
/* The XYZ operand is a fake one that is used to ensure only "xyz" is
specified. It simplifies the opmula and opmsub entries. */
#define XYZ (FDREG + 1)
{ 0, 0, TXVU_OPERAND_FAKE, parse_xyz, 0, 0, 0 },
/* end of list place holder */
{ 0 }
};
/* Macros to put a field's value into the right place. */
#define FT(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FTREG)
#define FS(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FSREG)
#define FD(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FDREG)
/* FIXME: If assembler needs these, move to opcode/txvu.h. */
#define R(x,b,m) (((x) & (m)) << (b)) /* value X, mask M, at bit B */
/* Upper Flag bits. */
#define UF(x) R ((x), 27, 31)
/* Upper REServed two bits next to flag bits. */
#define URES(x) R ((x), 25, 3)
/* The DEST field. */
#define UDEST(x) R ((x), 21, 15)
/* The FT reg field. */
#define UFT(x) R ((x), TXVU_SHIFT_FTREG, TXVU_MASK_VFREG)
/* The FS reg field. */
#define UFS(x) R ((x), TXVU_SHIFT_FSREG, TXVU_MASK_VFREG)
/* The FD reg field. */
#define UFD(x) R ((x), TXVU_SHIFT_FDREG, TXVU_MASK_VFREG)
/* The 4 bit opcode field. */
#define UOP4(x) R ((x), 2, 15)
/* The 6 bit opcode field. */
#define UOP6(x) R ((x), 0, 63)
/* The 9 bit opcode field. */
#define UOP9(x) R ((x), 2, 0x1ff)
/* The 11 bit opcode field. */
#define UOP11(x) R ((x), 0, 0x7ff)
/* The BroadCast field. */
#define UBC(x) R ((x), 0, 3)
/* Macros for special field values. */
/* The upper 7 bits of the upper word. */
#define UUBITS (UF (0) + URES (0))
/* Mask for UBITS. */
#define MUUBITS (UF (~0) + URES (~0))
/* Mask for URES. */
#define MURES URES (~0)
/* Mask for OP4. */
#define MUOP4 UOP4 (~0)
/* Mask for OP6. */
#define MUOP6 UOP6 (~0)
/* Mask for OP9. */
#define MUOP9 UOP9 (~0)
/* Mask for OP11. */
#define MUOP11 UOP11 (~0)
/* A space, separates instruction name (mnemonic + mnemonic operands) from operands. */
#define SP ' '
/* TXVU instructions.
[??? some of these comments are left over from the ARC port from which
this code is borrowed, delete in time]
@ -128,10 +197,67 @@ struct txvu_opcode txvu_upper_opcodes[] = {
/* Macros appear first. */
/* ??? Any aliases? */
/* The rest of these needn't be sorted, but it helps to find them if they
are. */
{ "abs", { DOTDEST, ' ', FTREG, FSREG }, 0xfe0001ff, 0x1fd, 0 },
{ "add", { DOTDEST, ' ', FDREG, FSREG, FTREG }, 0xfe00003f, 0x28, 0 },
/* The rest of these needn't be sorted, but it helps to find them if they are. */
{ "abs", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x1fd) },
{ "add", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x28) },
{ "addi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x22) },
{ "addq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x20) },
{ "add", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (0) },
{ "adda", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2bc) },
{ "addai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23e) },
{ "addaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23c) },
{ "adda", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0xf) },
{ "clip", { DOTDEST, SP, FSREG }, MURES + UDEST (~0) + UFT (~0) + MUOP11, UDEST (0xf) + UOP11 (0x1ff) },
{ "ftoi0", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17c) },
{ "ftoi4", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17d) },
{ "ftoi12", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17e) },
{ "ftoi15", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17f) },
{ "itof0", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13c) },
{ "itof4", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13d) },
{ "itof12", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13e) },
{ "itof15", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13f) },
{ "madd", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x29) },
{ "maddi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x23) },
{ "maddq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x21) },
{ "madd", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x2) },
{ "madda", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2bd) },
{ "maddai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23f) },
{ "maddaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23d) },
{ "madda", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x2f) },
{ "max", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2b) },
{ "maxi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x2d) },
{ "max", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x4) },
/* FIXME: mini or min? */
{ "mini", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2f) },
{ "mini", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1f) },
{ "mini", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x5) },
{ "msub", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2d) },
{ "msubi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x27) },
{ "msubq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x25) },
{ "msub", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x3) },
{ "msuba", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2fd) },
{ "msubai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27f) },
{ "msubaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27d) },
{ "msuba", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x3f) },
{ "mul", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2a) },
{ "muli", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1e) },
{ "mulq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1c) },
{ "mul", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (6) },
{ "mula", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2be) },
{ "mulai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x1fe) },
{ "mulaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x1fc) },
{ "mula", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x6f) },
{ "nop", { 0 }, MURES + UDEST (~0) + UFT (~0) + UFS (~0) + MUOP11, UOP11 (0x2ff) },
{ "opmula", { DOTDEST, SP, ACCDEST, FSREG, FTREG, XYZ }, MURES + MUOP11, UOP11 (0x2fe) },
{ "opmsub", { DOTDEST, SP, FDREG, FSREG, FTREG, XYZ }, MURES + MUOP6, UOP6 (0x2e) },
{ "sub", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2c) },
{ "subi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x26) },
{ "subq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x24) },
{ "sub", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (1) },
{ "suba", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2fc) },
{ "subai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27e) },
{ "subaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27c) },
{ "suba", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x1f) }
};
const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_opcodes[0]);
@ -253,6 +379,11 @@ txvu_lower_opcode_lookup_dis (insn)
Each of the registers must specify the same value as the opcode.
??? Perhaps remove the duplication? */
static int dest;
/* Value of BC to use.
The register specified for the ftreg must match the broadcast register
specified in the opcode. */
static int bc;
/* Init fns.
These are called before doing each of the respective activities. */
@ -263,6 +394,7 @@ void
txvu_opcode_init_parse ()
{
dest = -1;
bc = -1;
}
/* Called by the disassembler before printing an instruction. */
@ -271,6 +403,7 @@ void
txvu_opcode_init_print ()
{
dest = -1;
bc = -1;
}
/* Destination choice support.
@ -428,3 +561,152 @@ print_vfreg (info, insn, value)
(*info->fprintf_func) (info->stream, "vf%ld", value);
print_dest (info, insn, dest);
}
/* Broadcast handling. */
static long
parse_bc (pstr, errmsg)
char **pstr;
const char **errmsg;
{
long dest = 0;
switch (**pstr)
{
case 'x' : case 'X' : dest = TXVU_BC_X; break;
case 'y' : case 'Y' : dest = TXVU_BC_Y; break;
case 'z' : case 'Z' : dest = TXVU_BC_Z; break;
case 'w' : case 'W' : dest = TXVU_BC_W; break;
default : *errmsg = "invalid `bc'"; return 0;
}
++*pstr;
*errmsg = NULL;
return dest;
}
static void
print_bc (info, insn, value)
disassemble_info *info;
TXVU_INSN insn;
long value;
{
char c;
switch (value)
{
case TXVU_BC_X : c = 'x' ; break;
case TXVU_BC_Y : c = 'y' ; break;
case TXVU_BC_Z : c = 'z' ; break;
case TXVU_BC_W : c = 'w' ; break;
}
(*info->fprintf_func) (info->stream, "%c", c);
}
/* FT register in broadcast case. */
static long
parse_ftregbc (pstr, errmsg)
char **pstr;
const char **errmsg;
{
char *str = *pstr;
char *start;
long reg;
int reg_bc;
if (tolower (str[0]) != 'v'
|| tolower (str[1]) != 'f')
{
*errmsg = "unknown register";
return 0;
}
/* FIXME: quick hack until the framework works. */
start = str = str + 2;
while (*str && isdigit (*str))
++str;
reg = atoi (start);
reg_bc = parse_bc (&str, errmsg);
if (*errmsg)
return 0;
if (reg_bc != bc)
{
*errmsg = "register `bc' does not match instruction `bc'";
return 0;
}
*pstr = str;
*errmsg = NULL;
return reg;
}
static void
print_ftregbc (info, insn, value)
disassemble_info *info;
TXVU_INSN insn;
long value;
{
(*info->fprintf_func) (info->stream, "vf%ld", value);
print_bc (info, insn, bc);
}
/* ACC handling. */
static long
parse_accdest (pstr, errmsg)
char **pstr;
const char **errmsg;
{
char *str = *pstr;
long acc_dest = 0;
if (strncasecmp (str, "acc", 3) != 0)
{
*errmsg = "expecting `acc'";
return 0;
}
str += 3;
acc_dest = parse_dest (&str);
if (acc_dest == 0 || isalnum (*str))
{
*errmsg = "invalid `dest'";
return 0;
}
if (acc_dest != dest)
{
*errmsg = "acc `dest' does not match instruction `dest'";
return 0;
}
*pstr = str;
*errmsg = NULL;
/* Value isn't used, but we must return something. */
return 0;
}
static void
print_accdest (info, insn, value)
disassemble_info *info;
TXVU_INSN insn;
long value;
{
(*info->fprintf_func) (info->stream, "acc");
print_dest (info, insn, value);
}
/* XYZ operand handling.
This simplifies the opmula,opmsub entries by keeping them equivalent to
the others. */
static long
parse_xyz (pstr, errmsg)
char **pstr;
const char **errmsg;
{
if (dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z))
{
*errmsg = "expecting `xyz' for `dest' value";
return 0;
}
return 0;
}