From 3f89726318aaf4010045bf2eec07ce6f56488edd Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Wed, 14 Jan 1998 20:13:07 +0000 Subject: [PATCH] snapshot, upper opcode table done, modulo testing --- opcodes/txvu-opc.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 295 insertions(+), 13 deletions(-) diff --git a/opcodes/txvu-opc.c b/opcodes/txvu-opc.c index 8a7e12e..bd64df5 100644 --- a/opcodes/txvu-opc.c +++ b/opcodes/txvu-opc.c @@ -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; +} -- 2.7.4