diff options
Diffstat (limited to 'opcodes/txvu-opc.c')
-rw-r--r-- | opcodes/txvu-opc.c | 557 |
1 files changed, 324 insertions, 233 deletions
diff --git a/opcodes/txvu-opc.c b/opcodes/txvu-opc.c index 881da9b..2eab05f 100644 --- a/opcodes/txvu-opc.c +++ b/opcodes/txvu-opc.c @@ -38,16 +38,16 @@ static long CONCAT2 (parse_,fn) \ PARAMS ((char **, const char **)); #define INSERT_FN(fn) \ -static TXVU_INSN CONCAT2 (insert_,fn) \ - PARAMS ((TXVU_INSN, const struct txvu_operand *, \ +static void CONCAT2 (insert_,fn) \ + PARAMS ((TXVU_INSN *, const struct txvu_operand *, \ int, long, const char **)) #define EXTRACT_FN(fn) \ static long CONCAT2 (extract_,fn) \ - PARAMS ((TXVU_INSN, const struct txvu_operand *, \ + PARAMS ((TXVU_INSN *, const struct txvu_operand *, \ int, int *)) #define PRINT_FN(fn) \ static void CONCAT2 (print_,fn) \ - PARAMS ((disassemble_info *, TXVU_INSN, long)); + PARAMS ((disassemble_info *, TXVU_INSN *, long)); PARSE_FN (dotdest); INSERT_FN (dotdest); @@ -495,108 +495,6 @@ struct txvu_opcode txvu_lower_opcodes[] = }; const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_lower_opcodes[0]); -/* Indexed by first letter of opcode. Points to chain of opcodes with same - first letter. */ -/* ??? One can certainly use a better hash. Later. */ -static struct txvu_opcode *upper_opcode_map[26 + 1]; -static struct txvu_opcode *lower_opcode_map[26 + 1]; - -/* Indexed by insn code. Points to chain of opcodes with same insn code. */ -static struct txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1]; -static struct txvu_opcode *lower_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1]; - -/* Initialize any tables that need it. - Must be called once at start up (or when first needed). - - FLAGS is currently unused but is intended to control initialization. */ - -void -txvu_opcode_init_tables (flags) - int flags; -{ - static int init_p = 0; - - /* We may be intentionally called more than once (for example gdb will call - us each time the user switches cpu). These tables only need to be init'd - once though. */ - /* ??? We can remove the need for txvu_opcode_supported by taking it into - account here, but I'm not sure I want to do that yet (if ever). */ - if (!init_p) - { - int i,n; - - memset (upper_opcode_map, 0, sizeof (upper_opcode_map)); - memset (upper_icode_map, 0, sizeof (upper_icode_map)); - - /* Scan the table backwards so macros appear at the front. */ - for (i = txvu_upper_opcodes_count - 1; i >= 0; --i) - { - int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic); - int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value); - - txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash]; - upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i]; - - txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash]; - upper_icode_map[icode_hash] = &txvu_upper_opcodes[i]; - } - - memset (lower_opcode_map, 0, sizeof (lower_opcode_map)); - memset (lower_icode_map, 0, sizeof (lower_icode_map)); - - /* Scan the table backwards so macros appear at the front. */ - for (i = txvu_lower_opcodes_count - 1; i >= 0; --i) - { - int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic); - int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value); - - txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash]; - lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i]; - - txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash]; - lower_icode_map[icode_hash] = &txvu_lower_opcodes[i]; - } - - init_p = 1; - } -} - -/* Return the first insn in the chain for assembling upper INSN. */ - -const struct txvu_opcode * -txvu_upper_opcode_lookup_asm (insn) - const char *insn; -{ - return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)]; -} - -/* Return the first insn in the chain for assembling lower INSN. */ - -const struct txvu_opcode * -txvu_lower_opcode_lookup_asm (insn) - const char *insn; -{ - return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)]; -} - -/* Return the first insn in the chain for disassembling upper INSN. */ - -const struct txvu_opcode * -txvu_upper_opcode_lookup_dis (insn) - TXVU_INSN insn; -{ - return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)]; -} - -/* Return the first insn in the chain for disassembling lower INSN. */ - -const struct txvu_opcode * -txvu_lower_opcode_lookup_dis (insn) - TXVU_INSN insn; -{ - return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)]; -} - /* Value of DEST in use. Each of the registers must specify the same value as the opcode. ??? Perhaps remove the duplication? */ @@ -607,27 +505,6 @@ static int mnemonic_dest; specified in the opcode. */ static int mnemonic_bc; -/* Init fns. - These are called before doing each of the respective activities. */ - -/* Called by the assembler before parsing an instruction. */ - -void -txvu_opcode_init_parse () -{ - mnemonic_dest = -1; - mnemonic_bc = -1; -} - -/* Called by the disassembler before printing an instruction. */ - -void -txvu_opcode_init_print () -{ - mnemonic_dest = -1; - mnemonic_bc = -1; -} - /* Multiple destination choice support. The "dest" string selects any combination of x,y,z,w. [The letters are ordered that way to follow the manual's style.] */ @@ -680,7 +557,6 @@ parse_dotdest (pstr, errmsg) return 0; } - *errmsg = NULL; return dest; } @@ -723,7 +599,6 @@ parse_dotdest1 (pstr, errmsg) return 0; } - *errmsg = NULL; return dest; } @@ -755,13 +630,12 @@ parse_dest1 (pstr, errmsg) return 0; } - *errmsg = NULL; return dest; } -static TXVU_INSN +static void insert_dotdest (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; @@ -769,18 +643,18 @@ insert_dotdest (insn, operand, mods, value, errmsg) { /* Record the DEST value in use so the register parser can use it. */ mnemonic_dest = value; - return insn |= value << operand->shift; + *insn |= value << operand->shift; } static long extract_dotdest (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; { /* Record the DEST value in use so the register printer can use it. */ - mnemonic_dest = (insn >> operand->shift) & ((1 << operand->bits) - 1); + mnemonic_dest = (*insn >> operand->shift) & ((1 << operand->bits) - 1); return mnemonic_dest; } @@ -789,7 +663,7 @@ extract_dotdest (insn, operand, mods, pinvalid) static void _print_dest (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { if (value & TXVU_DEST_X) @@ -805,7 +679,7 @@ _print_dest (info, insn, value) static void print_dotdest (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "."); @@ -815,7 +689,7 @@ print_dotdest (info, insn, value) static void print_dest1 (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { _print_dest (info, insn, mnemonic_dest); @@ -852,14 +726,13 @@ _parse_sdest (pstr, errmsg) return 0; } - *errmsg = NULL; return dest; } static void print_sdest (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { char c; @@ -896,12 +769,12 @@ parse_bc (pstr, errmsg) static long extract_bc (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; { - mnemonic_bc = insn & 3; + mnemonic_bc = *insn & 3; return mnemonic_bc; } @@ -944,14 +817,13 @@ parse_vfreg (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; return reg; } static void print_vfreg (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vf%02ld", value); @@ -996,14 +868,13 @@ parse_bcftreg (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; return reg; } static void print_bcftreg (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vf%02ld", value); @@ -1038,7 +909,6 @@ parse_accdest (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; /* Value isn't used, but we must return something. */ return 0; } @@ -1046,7 +916,7 @@ parse_accdest (pstr, errmsg) static void print_accdest (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "acc"); @@ -1057,20 +927,16 @@ print_accdest (info, insn, value) This simplifies the opmula,opmsub entries by keeping them equivalent to the others. */ -static TXVU_INSN +static void insert_xyz (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { if (mnemonic_dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z)) - { - *errmsg = "expecting `xyz' for `dest' value"; - return insn; - } - return insn; + *errmsg = "expecting `xyz' for `dest' value"; } /* F[ST] register using selector in F[ST]F field. @@ -1107,45 +973,44 @@ parse_ffstreg (pstr, errmsg) if (*errmsg) return 0; *pstr = str; - *errmsg = NULL; return reg | (xyzw << 5); } static void print_ffstreg (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vf%02ld", value & TXVU_MASK_REG); print_sdest (info, insn, (value >> 5) & 3); } -static TXVU_INSN +static void insert_ffstreg (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { if (operand->shift == TXVU_SHIFT_SREG) - return insn | VLFSF (value >> 5) | VS (value); + *insn |= VLFSF (value >> 5) | VS (value); else - return insn | VLFTF (value >> 5) | VT (value); + *insn |= VLFTF (value >> 5) | VT (value); } static long extract_ffstreg (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; { if (operand->shift == TXVU_SHIFT_SREG) - return (((insn & VLFSF (~0)) >> 21) << 5) | VS (insn); + return (((*insn & VLFSF (~0)) >> 21) << 5) | VS (*insn); else - return (((insn & VLFTF (~0)) >> 21) << 5) | VT (insn); + return (((*insn & VLFTF (~0)) >> 21) << 5) | VT (*insn); } /* F register. */ @@ -1177,14 +1042,13 @@ parse_freg (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; return reg; } static void print_freg (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vf%02ld", value); @@ -1219,14 +1083,13 @@ parse_ireg (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; return reg; } static void print_ireg (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vi%02ld", value); @@ -1261,14 +1124,13 @@ parse_vi01 (pstr, errmsg) return 0; } *pstr = str; - *errmsg = NULL; return reg; } static void print_vi01 (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "vi01"); @@ -1276,61 +1138,61 @@ print_vi01 (info, insn, value) /* Lower instruction 12 bit unsigned immediate. */ -static TXVU_INSN +static void insert_luimm12 (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return insn | VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value); + *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value); } static long extract_luimm12 (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; { - return (((insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (insn); + return (((*insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (*insn); } /* Lower instruction 12 bit unsigned immediate, upper 6 bits. */ -static TXVU_INSN +static void insert_luimm12up6 (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return insn | VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0); + *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0); } /* Lower instruction 15 bit unsigned immediate. */ -static TXVU_INSN +static void insert_luimm15 (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return insn | VLUIMM15TOP (value >> 11) | VLIMM11 (value); + *insn |= VLUIMM15TOP (value >> 11) | VLIMM11 (value); } static long extract_luimm15 (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; { - return (((insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (insn); + return (((*insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (*insn); } /* PKE support. */ @@ -1356,7 +1218,7 @@ PRINT_FN (pke_unpacktype); PARSE_FN (pke_unpackaddr); -const struct txvu_operand txvu_pke_operands[] = +const struct txvu_operand pke_operands[] = { /* place holder (??? not sure if needed) */ #define PKE_UNUSED 128 @@ -1427,7 +1289,7 @@ const struct txvu_operand txvu_pke_operands[] = #define VPKECMD(x) V ((x), 7, 24) #define VPKEUNPACK V (0x60, 8, 24) -struct txvu_opcode txvu_pke_opcodes[] = +struct txvu_opcode pke_opcodes[] = { { "pkenop", { PKE_IBIT }, 0x7fffffff, 0 }, { "stcycle", { PKE_IBIT, SP, PKE_UIMM8UP, C, PKE_UIMM8LO }, MPKECMD, VPKECMD (1) }, @@ -1457,7 +1319,7 @@ struct txvu_opcode txvu_pke_opcodes[] = { "directhl", { PKE_IBIT, SP, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x51), PKE_OPCODE_LENVAR + PKE_OPCODE_DIRECT }, { "unpack", { PKE_IMRBITS, SP, PKE_UNPACKTYPE, C, PKE_UNPACKADDR, C, PKE_VARLENDATA }, MPKEUNPACK, VPKEUNPACK, PKE_OPCODE_LENVAR + PKE_OPCODE_UNPACK }, }; -const int txvu_pke_opcodes_count = sizeof (txvu_pke_opcodes) / sizeof (txvu_pke_opcodes[0]); +const int pke_opcodes_count = sizeof (pke_opcodes) / sizeof (pke_opcodes[0]); /* PKE parse,insert,extract,print helper fns. */ @@ -1471,7 +1333,7 @@ parse_pke_ibit (pstr, errmsg) static void print_pke_ibit (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1487,7 +1349,7 @@ parse_pke_mode (pstr, errmsg) static void print_pke_mode (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1503,7 +1365,7 @@ parse_pke_ability (pstr, errmsg) static void print_pke_ability (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1535,7 +1397,7 @@ parse_pke_imrbits (pstr, errmsg) static void print_pke_imrbits (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1551,7 +1413,7 @@ parse_pke_unpacktype (pstr, errmsg) static void print_pke_unpacktype (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1581,7 +1443,7 @@ INSERT_FN (dma_next); EXTRACT_FN (dma_next); PRINT_FN (dma_next); -const struct txvu_operand txvu_dma_operands[] = +const struct txvu_operand dma_operands[] = { /* place holder (??? not sure if needed) */ #define DMA_UNUSED 128 @@ -1606,7 +1468,7 @@ const struct txvu_operand txvu_dma_operands[] = { 0 } }; -struct txvu_opcode txvu_dma_opcodes[] = +struct txvu_opcode dma_opcodes[] = { { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 1 }, { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 2 }, @@ -1616,7 +1478,7 @@ struct txvu_opcode txvu_dma_opcodes[] = { "dmareg", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 6 }, { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 7 } }; -const int txvu_dma_opcodes_count = sizeof (txvu_dma_opcodes) / sizeof (txvu_dma_opcodes[0]); +const int dma_opcodes_count = sizeof (dma_opcodes) / sizeof (dma_opcodes[0]); /* DMA parse,insert,extract,print helper fns. */ @@ -1625,22 +1487,42 @@ parse_dma_flags (pstr, errmsg) char **pstr; const char **errmsg; { + char *str = *pstr; + int flags = 0; + + if (*str != '[') + return 0; + + for (str = str + 1; *str != ']'; ++str) + { + switch (tolower (*str)) + { + case '0' : flags |= DMA_FLAG_PCE0; break; + case '1' : flags |= DMA_FLAG_PCE1; break; + case 'i' : flags |= DMA_FLAG_INT; break; + case 's' : flags |= DMA_FLAG_SPR; break; + default : *errmsg = "unknown dma flag"; return 0; + } + } + + *errmsg = NULL; + *pstr = str + 1; + return flags; } -static TXVU_INSN +static void insert_dma_flags (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_dma_flags (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1651,10 +1533,22 @@ extract_dma_flags (insn, operand, mods, pinvalid) static void print_dma_flags (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { - (*info->fprintf_func) (info->stream, "???"); + if (value) + { + (*info->fprintf_func) (info->stream, "["); + if (value & DMA_FLAG_PCE0) + (*info->fprintf_func) (info->stream, "0"); + if (value & DMA_FLAG_PCE1) + (*info->fprintf_func) (info->stream, "1"); + if (value & DMA_FLAG_INT) + (*info->fprintf_func) (info->stream, "i"); + if (value & DMA_FLAG_SPR) + (*info->fprintf_func) (info->stream, "s"); + (*info->fprintf_func) (info->stream, "]"); + } } static long @@ -1664,20 +1558,19 @@ parse_dma_data (pstr, errmsg) { } -static TXVU_INSN +static void insert_dma_data (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_dma_data (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1688,7 +1581,7 @@ extract_dma_data (insn, operand, mods, pinvalid) static void print_dma_data (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1701,20 +1594,19 @@ parse_dma_next (pstr, errmsg) { } -static TXVU_INSN +static void insert_dma_next (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_dma_next (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1725,7 +1617,7 @@ extract_dma_next (insn, operand, mods, pinvalid) static void print_dma_next (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1753,7 +1645,7 @@ INSERT_FN (gpuif_eop); EXTRACT_FN (gpuif_eop); PRINT_FN (gpuif_eop); -const struct txvu_operand txvu_gpuif_operands[] = +const struct txvu_operand gpuif_operands[] = { /* place holder (??? not sure if needed) */ #define GPUIF_UNUSED 128 @@ -1779,13 +1671,13 @@ const struct txvu_operand txvu_gpuif_operands[] = { 0 } }; -struct txvu_opcode txvu_gpuif_opcodes[] = +struct txvu_opcode gpuif_opcodes[] = { { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 1 }, { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 2 }, { "gpuifimage", { SP, GPUIF_NLOOP }, 0, 3 }, }; -const int txvu_gpuif_opcodes_count = sizeof (txvu_gpuif_opcodes) / sizeof (txvu_gpuif_opcodes[0]); +const int gpuif_opcodes_count = sizeof (gpuif_opcodes) / sizeof (gpuif_opcodes[0]); /* GPUIF parse,insert,extract,print helper fns. */ @@ -1796,20 +1688,19 @@ parse_gpuif_prim (pstr, errmsg) { } -static TXVU_INSN +static void insert_gpuif_prim (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_gpuif_prim (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1820,7 +1711,7 @@ extract_gpuif_prim (insn, operand, mods, pinvalid) static void print_gpuif_prim (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1833,20 +1724,19 @@ parse_gpuif_regs (pstr, errmsg) { } -static TXVU_INSN +static void insert_gpuif_regs (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_gpuif_regs (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1857,7 +1747,7 @@ extract_gpuif_regs (insn, operand, mods, pinvalid) static void print_gpuif_regs (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1870,20 +1760,19 @@ parse_gpuif_nloop (pstr, errmsg) { } -static TXVU_INSN +static void insert_gpuif_nloop (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_gpuif_nloop (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1894,7 +1783,7 @@ extract_gpuif_nloop (insn, operand, mods, pinvalid) static void print_gpuif_nloop (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); @@ -1907,20 +1796,19 @@ parse_gpuif_eop (pstr, errmsg) { } -static TXVU_INSN +static void insert_gpuif_eop (insn, operand, mods, value, errmsg) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; long value; const char **errmsg; { - return 0; } static long extract_gpuif_eop (insn, operand, mods, pinvalid) - TXVU_INSN insn; + TXVU_INSN *insn; const struct txvu_operand *operand; int mods; int *pinvalid; @@ -1931,8 +1819,211 @@ extract_gpuif_eop (insn, operand, mods, pinvalid) static void print_gpuif_eop (info, insn, value) disassemble_info *info; - TXVU_INSN insn; + TXVU_INSN *insn; long value; { (*info->fprintf_func) (info->stream, "???"); } + +/* Init fns. + These are called before doing each of the respective activities. */ + +/* Called by the assembler before parsing an instruction. */ + +void +txvu_opcode_init_parse () +{ + mnemonic_dest = -1; + mnemonic_bc = -1; +} + +/* Called by the disassembler before printing an instruction. */ + +void +txvu_opcode_init_print () +{ + mnemonic_dest = -1; + mnemonic_bc = -1; +} + +/* Indexed by first letter of opcode. Points to chain of opcodes with same + first letter. */ +/* ??? One can certainly use a better hash. Later. */ +static struct txvu_opcode *upper_opcode_map[26 + 1]; +static struct txvu_opcode *lower_opcode_map[26 + 1]; + +/* Indexed by insn code. Points to chain of opcodes with same insn code. */ +static struct txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1]; +static struct txvu_opcode *lower_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1]; + +/* Initialize any tables that need it. + Must be called once at start up (or when first needed). + + FLAGS is currently unused but is intended to control initialization. */ + +void +txvu_opcode_init_tables (flags) + int flags; +{ + static int init_p = 0; + + /* We may be intentionally called more than once (for example gdb will call + us each time the user switches cpu). These tables only need to be init'd + once though. */ + /* ??? We can remove the need for txvu_opcode_supported by taking it into + account here, but I'm not sure I want to do that yet (if ever). */ + if (!init_p) + { + int i,n; + + /* Upper VU table. */ + + memset (upper_opcode_map, 0, sizeof (upper_opcode_map)); + memset (upper_icode_map, 0, sizeof (upper_icode_map)); + /* Scan the table backwards so macros appear at the front. */ + for (i = txvu_upper_opcodes_count - 1; i >= 0; --i) + { + int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic); + int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value); + + txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash]; + upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i]; + + txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash]; + upper_icode_map[icode_hash] = &txvu_upper_opcodes[i]; + } + + /* Lower VU table. */ + + memset (lower_opcode_map, 0, sizeof (lower_opcode_map)); + memset (lower_icode_map, 0, sizeof (lower_icode_map)); + /* Scan the table backwards so macros appear at the front. */ + for (i = txvu_lower_opcodes_count - 1; i >= 0; --i) + { + int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic); + int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value); + + txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash]; + lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i]; + + txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash]; + lower_icode_map[icode_hash] = &txvu_lower_opcodes[i]; + } + + /* PKE table. */ + + for (i = pke_opcodes_count - 2; i >= 0; --i) + { + pke_opcodes[i].next_asm = & pke_opcodes[i+1]; + pke_opcodes[i].next_dis = & pke_opcodes[i+1]; + } + + /* DMA table. */ + + for (i = dma_opcodes_count - 2; i >= 0; --i) + { + dma_opcodes[i].next_asm = & dma_opcodes[i+1]; + dma_opcodes[i].next_dis = & dma_opcodes[i+1]; + } + + /* GPUIF table. */ + + for (i = gpuif_opcodes_count - 2; i >= 0; --i) + { + gpuif_opcodes[i].next_asm = & gpuif_opcodes[i+1]; + gpuif_opcodes[i].next_dis = & gpuif_opcodes[i+1]; + } + + init_p = 1; + } +} + +/* Return the first insn in the chain for assembling upper INSN. */ + +const struct txvu_opcode * +txvu_upper_opcode_lookup_asm (insn) + const char *insn; +{ + return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)]; +} + +/* Return the first insn in the chain for disassembling upper INSN. */ + +const struct txvu_opcode * +txvu_upper_opcode_lookup_dis (insn) + TXVU_INSN insn; +{ + return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)]; +} + +/* Return the first insn in the chain for assembling lower INSN. */ + +const struct txvu_opcode * +txvu_lower_opcode_lookup_asm (insn) + const char *insn; +{ + return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)]; +} + +/* Return the first insn in the chain for disassembling lower INSN. */ + +const struct txvu_opcode * +txvu_lower_opcode_lookup_dis (insn) + TXVU_INSN insn; +{ + return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)]; +} + +/* Return the first insn in the chain for assembling lower INSN. */ + +const struct txvu_opcode * +pke_opcode_lookup_asm (insn) + const char *insn; +{ + return &pke_opcodes[0]; +} + +/* Return the first insn in the chain for disassembling lower INSN. */ + +const struct txvu_opcode * +pke_opcode_lookup_dis (insn) + TXVU_INSN insn; +{ + return &pke_opcodes[0]; +} + +/* Return the first insn in the chain for assembling lower INSN. */ + +const struct txvu_opcode * +dma_opcode_lookup_asm (insn) + const char *insn; +{ + return &dma_opcodes[0]; +} + +/* Return the first insn in the chain for disassembling lower INSN. */ + +const struct txvu_opcode * +dma_opcode_lookup_dis (insn) + TXVU_INSN insn; +{ + return &dma_opcodes[0]; +} + +/* Return the first insn in the chain for assembling lower INSN. */ + +const struct txvu_opcode * +gpuif_opcode_lookup_asm (insn) + const char *insn; +{ + return &gpuif_opcodes[0]; +} + +/* Return the first insn in the chain for disassembling lower INSN. */ + +const struct txvu_opcode * +gpuif_opcode_lookup_dis (insn) + TXVU_INSN insn; +{ + return &gpuif_opcodes[0]; +} |