diff options
author | Doug Evans <dje@google.com> | 1998-01-28 21:58:23 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 1998-01-28 21:58:23 +0000 |
commit | 37130f1153da94302ab835e26fdc749c0bd74c87 (patch) | |
tree | 8e4b2e2915d933d241e688a040bbb8877d3f94f9 /opcodes | |
parent | 0040c1e966c3d097547cd24e60459b2c57decff4 (diff) | |
download | gdb-37130f1153da94302ab835e26fdc749c0bd74c87.zip gdb-37130f1153da94302ab835e26fdc749c0bd74c87.tar.gz gdb-37130f1153da94302ab835e26fdc749c0bd74c87.tar.bz2 |
* dvp-dis.c, dvp-opc.c: New files.
* configure.in: Compile them if bfd_dvp_arch, as well as mips.
* configure: Regenerate.
* Makefile.am (ALL_MACHINES): Add dvp-{dis,opc}.lo.
(dvp-dis.lo,dvp-opc.lo): Add rules for.
(mips-dis.lo): Compile with @archdefs@.
* Makefile.in: Regenerate.
* disassemble.c: Define ARCH_mips ifdef ARCH_dvp.
* mips-dis.c (print_insn_little_mips): Check for DVP insns.
plus delete old txvu stuff
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/.Sanitize | 4 | ||||
-rw-r--r-- | opcodes/ChangeLog | 71 | ||||
-rw-r--r-- | opcodes/Makefile.am | 13 | ||||
-rw-r--r-- | opcodes/Makefile.in | 13 | ||||
-rwxr-xr-x | opcodes/configure | 2 | ||||
-rw-r--r-- | opcodes/configure.in | 2 | ||||
-rw-r--r-- | opcodes/disassemble.c | 16 | ||||
-rw-r--r-- | opcodes/mips-dis.c | 10 | ||||
-rw-r--r-- | opcodes/txvu-dis.c | 202 | ||||
-rw-r--r-- | opcodes/txvu-opc.c | 2722 |
10 files changed, 49 insertions, 3006 deletions
diff --git a/opcodes/.Sanitize b/opcodes/.Sanitize index 2b17516..f751d3d 100644 --- a/opcodes/.Sanitize +++ b/opcodes/.Sanitize @@ -39,7 +39,7 @@ else lose_these_too="${tic80_files} ${lose_these_too}" fi -sky_files="txvu-opc.c txvu-dis.c" +sky_files="dvp-opc.c dvp-dis.c" if ( echo $* | grep keep\-sky > /dev/null ) ; then keep_these_too="${sky_files} ${keep_these_too}" @@ -409,7 +409,7 @@ else done fi -sky_files="ChangeLog Makefile.in Makefile.am configure.in configure disassemble.c" +sky_files="ChangeLog Makefile.in Makefile.am configure.in configure disassemble.c mips-dis.c" if ( echo $* | grep keep\-sky > /dev/null ) ; then for i in $sky_files ; do if test ! -d $i && (grep sanitize-sky $i > /dev/null) ; then diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index bdaee32..e640321 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,16 @@ +start-sanitize-sky +Wed Jan 28 13:46:19 1998 Doug Evans <devans@canuck.cygnus.com> + + * dvp-dis.c, dvp-opc.c: New files. + * configure.in: Compile them if bfd_dvp_arch, as well as mips. + * configure: Regenerate. + * Makefile.am (ALL_MACHINES): Add dvp-{dis,opc}.lo. + (dvp-dis.lo,dvp-opc.lo): Add rules for. + * Makefile.in: Regenerate. + * disassemble.c: Define ARCH_mips ifdef ARCH_dvp. + * mips-dis.c (print_insn_little_mips): Check for DVP insns. + +end-sanitize-sky Wed Jan 28 09:55:03 1998 Nick Clifton <nickc@cygnus.com> * v850-opc.c (insertion routines): If both alignment and size is @@ -8,42 +21,6 @@ Tue Jan 27 21:52:59 1998 Jeffrey A Law (law@cygnus.com) * mips-dis.c (_print_insn_mips): Set target_processor as appropriate. Only recognize instructions for the current target_processor. -start-sanitize-sky -Tue Jan 27 14:11:04 1998 Doug Evans <devans@seba.cygnus.com> - - * txvu-dis.c (*): Update to use new arguments in - parse/insert/extract/print fns. - * txvu-opc.c (*): Likewise. - -Mon Jan 26 16:25:51 1998 Doug Evans <devans@seba.cygnus.com> - - * txvu-dis.c (print_insn): Extract/print fns take pointer to - insn now and not insn itself. - * txvu-opc.c: insert/extract/print fns take pointer to - insn now and not insn itself. Add initial dma,pke,gpuif support. - Parse fn no longer needs to set errmsg = NULL for success. - (lookup_keyword_{value,name}): New functions. - (scan_symbol): New function. - (issymchar,SKIP_BLANKS): New macros. - -Fri Jan 23 01:49:24 1998 Doug Evans <devans@seba.cygnus.com> - - * txvu-opc.c (txvu_operands, UBC): Add extract entry. - (txvu_operands, UACCDEST): Not a fake operand. - (txvu_operands, UXYZ): Move parse entry to insert entry. - (txvu_operands, LVI01): Not a fake operand. - (txvu_upper_opcodes): Fix spelling of minii instruction. - (printf_vfreg): Print register number with "%02ld". - (print_bcftreg): Likewise. - (print_accdest): Pass `dest' to _print_dest. - (insert_xyz): Renamed from parse_xyz. - (parse_dest1,insert_luimm12up6): New functions. - (txvu_operands): New operands LUIMM12UP6, LDEST1. - (txvu_lower_opcodes): Clean up pass over table. - (parse_dotdest1): Fix dest calculation. - (_parse_sdest): Fix typo. - -end-sanitize-sky Thu Jan 22 16:20:17 1998 Fred Fish <fnf@cygnus.com> * d10v-dis.c (PC_MASK): Correct value. @@ -91,28 +68,6 @@ start-sanitize-cygnus * cgen.sh, cgen-asm.in, cgen-dis.in: New files. end-sanitize-cygnus -start-sanitize-sky -Tue Jan 6 13:08:14 1998 Doug Evans <devans@seba.cygnus.com> - - * txvu-dis.c (print_insn_txvu): Handle no separator between - upper and lower insn #ifndef VERTICAL_BAR_SEPARATOR. - -Mon Jan 5 13:41:07 1998 Doug Evans <devans@seba.cygnus.com> - - * txvu-dis.c, txvu-opc.c: New files. - * configure.in: Compile them. - * configure: Regenerate. - * Makefile.am (ALL_MACHINES): Add txvu-{dis,opc}.lo. - (txvu-dis.lo,txvu-opc.lo): Add rules for. - * Makefile.in: Regenerate. - -Mon Dec 22 17:17:03 1997 Doug Evans <devans@canuck.cygnus.com> - - * configure.in: Add txvu support. - * configure: Regenerate. - * disassemble.c: Add txvu support. - -end-sanitize-sky Mon Dec 22 12:37:06 1997 Ian Lance Taylor <ian@cygnus.com> * mips-opc.c: Add FP_D to s.d instruction flags. diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am index ab79a12..3378397 100644 --- a/opcodes/Makefile.am +++ b/opcodes/Makefile.am @@ -104,8 +104,8 @@ ALL_MACHINES = \ tic80-opc.lo \ $(end-sanitize-tic80) \ $(start-sanitize-sky) \ - txvu-dis.lo \ - txvu-opc.lo \ + dvp-dis.lo \ + dvp-opc.lo \ $(end-sanitize-sky) \ v850-dis.lo \ v850-opc.lo \ @@ -184,9 +184,12 @@ tic80-opc.lo: tic80-opc.c $(INCDIR)/opcode/tic80.h # end-sanitize-tic80 # start-sanitize-sky -txvu-dis.lo: txvu-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \ - $(INCDIR)/opcode/txvu.h -txvu-opc.lo: txvu-opc.c $(INCDIR)/opcode/txvu.h +dvp-dis.lo: txvu-dvp.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \ + $(INCDIR)/opcode/dvp.h +dvp-opc.lo: dvp-opc.c $(INCDIR)/opcode/dvp.h + +mips-dis.lo: mips-dis.c + $(LIBTOOL) --mode=compile $(COMPILE) -c @archdefs@ $(srcdir)/mips-dis.c # end-sanitize-sky # This dependency stuff is copied from BFD. diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index 580bcac..108ba6c 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -174,8 +174,8 @@ ALL_MACHINES = \ tic80-opc.lo \ $(end-sanitize-tic80) \ $(start-sanitize-sky) \ - txvu-dis.lo \ - txvu-opc.lo \ + dvp-dis.lo \ + dvp-opc.lo \ $(end-sanitize-sky) \ v850-dis.lo \ v850-opc.lo \ @@ -540,9 +540,12 @@ tic80-opc.lo: tic80-opc.c $(INCDIR)/opcode/tic80.h # end-sanitize-tic80 # start-sanitize-sky -txvu-dis.lo: txvu-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \ - $(INCDIR)/opcode/txvu.h -txvu-opc.lo: txvu-opc.c $(INCDIR)/opcode/txvu.h +dvp-dis.lo: txvu-dvp.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \ + $(INCDIR)/opcode/dvp.h +dvp-opc.lo: dvp-opc.c $(INCDIR)/opcode/dvp.h + +mips-dis.lo: mips-dis.c + $(LIBTOOL) --mode=compile $(COMPILE) -c @archdefs@ $(srcdir)/mips-dis.c # end-sanitize-sky # This dependency stuff is copied from BFD. diff --git a/opcodes/configure b/opcodes/configure index 3dd46c7..01276be 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -1885,7 +1885,7 @@ if test x${all_targets} = xfalse ; then bfd_tic80_arch) ta="$ta tic80-dis.lo tic80-opc.lo" ;; # end-sanitize-tic80 # start-sanitize-sky - bfd_txvu_arch) ta="$ta txvu-dis.lo txvu-opc.lo" ;; + bfd_dvp_arch) ta="$ta mips-dis.lo mips-opc.lo mips16-opc.lo dvp-dis.lo dvp-opc.lo" ;; # end-sanitize-sky bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; # start-sanitize-v850e diff --git a/opcodes/configure.in b/opcodes/configure.in index 15723bd..fbbd94e 100644 --- a/opcodes/configure.in +++ b/opcodes/configure.in @@ -154,7 +154,7 @@ if test x${all_targets} = xfalse ; then bfd_tic80_arch) ta="$ta tic80-dis.lo tic80-opc.lo" ;; # end-sanitize-tic80 # start-sanitize-sky - bfd_txvu_arch) ta="$ta txvu-dis.lo txvu-opc.lo" ;; + bfd_dvp_arch) ta="$ta mips-dis.lo mips-opc.lo mips16-opc.lo dvp-dis.lo dvp-opc.lo" ;; # end-sanitize-sky bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; # start-sanitize-v850e diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 0745854..31f6a54 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -46,14 +46,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* start-sanitize-tic80 */ #define ARCH_tic80 /* end-sanitize-tic80 */ -/* start-sanitize-sky */ -#define ARCH_txvu -/* end-sanitize-sky */ #define ARCH_v850 #define ARCH_w65 #define ARCH_z8k #endif +/* start-sanitize-sky */ +#if defined (ARCH_dvp) && ! defined (ARCH_mips) +#define ARCH_mips +#endif +/* end-sanitize-sky */ + disassembler_ftype disassembler (abfd) bfd *abfd; @@ -205,13 +208,6 @@ disassembler (abfd) break; #endif /* end-sanitize-tic80 */ -/* start-sanitize-sky */ -#ifdef ARCH_txvu - case bfd_arch_txvu: - disassemble = print_insn_txvu; - break; -#endif -/* end-sanitize-sky */ #ifdef ARCH_v850 case bfd_arch_v850: disassemble = print_insn_v850; diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index 7f3a3a1..1e7acc2 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -467,6 +467,16 @@ print_insn_little_mips (memaddr, info) bfd_byte buffer[4]; int status; + /* start-sanitize-sky */ +#ifdef ARCH_dvp + if (bfd_mach_dvp_p (info->mach) + || (info->flavour == bfd_target_elf_flavour + && info->symbol != NULL + && MIPS_STO_DVP_P (((elf_symbol_type *) info->symbol)->internal_elf_sym.st_other))) + return print_insn_dvp (memaddr, info); +#endif + /* end-sanitize-sky */ + if (info->mach == 16 || (info->flavour == bfd_target_elf_flavour && info->symbol != NULL diff --git a/opcodes/txvu-dis.c b/opcodes/txvu-dis.c deleted file mode 100644 index eccb0e8..0000000 --- a/opcodes/txvu-dis.c +++ /dev/null @@ -1,202 +0,0 @@ -/* Instruction printing code for the TXVU - Copyright (C) 1998 Free Software Foundation, Inc. - - 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., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "dis-asm.h" -#include "opcode/txvu.h" -#include "elf-bfd.h" -#include "elf/txvu.h" - -static void print_insn PARAMS ((bfd_vma, disassemble_info *, TXVU_INSN, int)); - -/* Print one instruction from PC on INFO->STREAM. - Return the size of the instruction. */ - -int -print_insn_txvu (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - bfd_byte buffer[8]; - void *stream = info->stream; - fprintf_ftype func = info->fprintf_func; - int status; - /* First element is upper, second is lower. */ - TXVU_INSN upper,lower; - static int initialized = 0; - - if (!initialized) - { - initialized = 1; - txvu_opcode_init_tables (0); - } - - status = (*info->read_memory_func) (pc, buffer, 8, info); - if (status != 0) - { - (*info->memory_error_func) (status, pc, info); - return -1; - } - /* The lower instruction has the lower address. */ - upper = bfd_getl32 (buffer + 4); - lower = bfd_getl32 (buffer); - - /* FIXME: This will need revisiting. */ - print_insn (pc, info, upper, 0); -#ifdef VERTICAL_BAR_SEPARATOR - (*func) (stream, " | "); -#else - /* Not sure how much whitespace to print here. - At least two spaces, not more than 9, and having columns line up somewhat - seems reasonable. */ - (*func) (stream, " \t"); -#endif - print_insn (pc, info, lower, 1); - - return 8; -} - -/* Print one instruction. - LOWER_P is non-zero if disassembling a lower slot insn. */ - -static void -print_insn (pc, info, insn, lower_p) - bfd_vma pc; - disassemble_info *info; - TXVU_INSN insn; - int lower_p; -{ - const txvu_opcode *opcode; - void *stream = info->stream; - fprintf_ftype func = info->fprintf_func; - - /* The instructions are stored in lists hashed by the insn code - (though we needn't care how they're hashed). */ - - if (lower_p) - opcode = txvu_lower_opcode_lookup_dis (insn); - else - opcode = txvu_upper_opcode_lookup_dis (insn); - for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_DIS (opcode)) - { - const unsigned char *syn; - int mods,invalid,num_operands; - long value; - const txvu_operand *operand; - - /* Basic bit mask must be correct. */ - if ((insn & opcode->mask) != opcode->value) - continue; - - /* Make two passes over the operands. First see if any of them - have extraction functions, and, if they do, make sure the - instruction is valid. */ - - txvu_opcode_init_print (); - invalid = 0; - - for (syn = opcode->syntax; *syn; ++syn) - { - int index; - - if (*syn < 128) - continue; - - mods = 0; - index = TXVU_OPERAND_INDEX (*syn); - while (TXVU_MOD_P (txvu_operands[index].flags)) - { - mods |= txvu_operands[index].flags & TXVU_MOD_BITS; - ++syn; - index = TXVU_OPERAND_INDEX (*syn); - } - operand = txvu_operands + index; - if (operand->extract) - (*operand->extract) (opcode, operand, mods, &insn, &invalid); - } - if (invalid) - continue; - - /* The instruction is valid. */ - - (*func) (stream, "%s", opcode->mnemonic); - num_operands = 0; - for (syn = opcode->syntax; *syn; ++syn) - { - int index; - - if (*syn < 128) - { - (*func) (stream, "%c", *syn); - continue; - } - - /* We have an operand. Fetch any special modifiers. */ - mods = 0; - index = TXVU_OPERAND_INDEX (*syn); - while (TXVU_MOD_P (txvu_operands[index].flags)) - { - mods |= txvu_operands[index].flags & TXVU_MOD_BITS; - ++syn; - index = TXVU_OPERAND_INDEX (*syn); - } - operand = txvu_operands + index; - - /* Extract the value from the instruction. */ - if (operand->extract) - { - value = (*operand->extract) (opcode, operand, mods, - &insn, (int *) NULL); - } - else - { - value = (insn >> operand->shift) & ((1 << operand->bits) - 1); - if ((operand->flags & TXVU_OPERAND_SIGNED) != 0 - && (value & (1 << (operand->bits - 1)))) - value -= 1 << operand->bits; - } - -#if 0 /* commas are part of the syntax string now */ - /* If second or later operand, print a comma. */ - if (num_operands > 0) - (*func) (stream, ","); -#endif - - /* Print the operand as directed by the flags. */ - if (operand->print) - (*operand->print) (opcode, operand, mods, &insn, info, value); - else if (operand->flags & TXVU_OPERAND_FAKE) - ; /* nothing to do (??? at least not yet) */ - else if (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) - (*info->print_address_func) (pc + (value << 3), info); - /* ??? Not all cases of this are currently caught. */ - else if (operand->flags & TXVU_OPERAND_ABSOLUTE_BRANCH) - (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); - else if (operand->flags & TXVU_OPERAND_ADDRESS) - (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); - else - (*func) (stream, "%ld", value); - - if (! (operand->flags & TXVU_OPERAND_SUFFIX)) - ++num_operands; - } - - /* We have found and printed an instruction; return. */ - return; - } - - (*func) (stream, "*unknown*"); -} diff --git a/opcodes/txvu-opc.c b/opcodes/txvu-opc.c deleted file mode 100644 index 1d4d0f7..0000000 --- a/opcodes/txvu-opc.c +++ /dev/null @@ -1,2722 +0,0 @@ -/* Opcode table for the TXVU - Copyright 1998 Free Software Foundation, Inc. - - 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, 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., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "ansidecl.h" -#include "sysdep.h" -#include "dis-asm.h" -#include "opcode/txvu.h" - -#ifndef NULL -#define NULL 0 -#endif - -#if defined (__STDC__) || defined (ALMOST_STDC) -#define XCONCAT2(a,b) a##b -#else -#define XCONCAT2(a,b) a/**/b -#endif -#define CONCAT2(a,b) XCONCAT2(a,b) - -typedef struct { - int value; - const char *name; -} keyword; - -static int lookup_keyword_value PARAMS ((const keyword *, const char *, int)); -static const char *lookup_keyword_name PARAMS ((const keyword *table, int)); - -static char *scan_symbol PARAMS ((char *)); - -/* Return non-zero if CH is a character that may appear in a symbol. */ -/* FIXME: This will need revisiting. */ -#define issymchar(ch) (isalnum (ch) || ch == '_') - -#define SKIP_BLANKS(var) while (isspace (*(var))) ++(var) - -/* ??? One can argue it's preferable to have the PARSE_FN support in tc-txvu.c - and the PRINT_FN support in txvu-dis.c. For this project I like having - them all in one place. */ - -#define PARSE_FN(fn) \ -static long CONCAT2 (parse_,fn) \ - PARAMS ((const txvu_opcode *, const txvu_operand *, int, char **, \ - const char **)); -#define INSERT_FN(fn) \ -static void CONCAT2 (insert_,fn) \ - PARAMS ((const txvu_opcode *, const txvu_operand *, int, TXVU_INSN *, \ - long, const char **)) -#define EXTRACT_FN(fn) \ -static long CONCAT2 (extract_,fn) \ - PARAMS ((const txvu_opcode *, const txvu_operand *, int, TXVU_INSN *, \ - int *)); -#define PRINT_FN(fn) \ -static void CONCAT2 (print_,fn) \ - PARAMS ((const txvu_opcode *, const txvu_operand *, int, TXVU_INSN *, \ - disassemble_info *, long)); - -PARSE_FN (dotdest); -INSERT_FN (dotdest); -EXTRACT_FN (dotdest); -PRINT_FN (dotdest); - -PARSE_FN (dotdest1); -PARSE_FN (dest1); -PRINT_FN (dest1); - -PARSE_FN (bc); -EXTRACT_FN (bc); -PRINT_FN (sdest); - -PARSE_FN (vfreg); -PRINT_FN (vfreg); - -PARSE_FN (bcftreg); -PRINT_FN (bcftreg); - -PARSE_FN (accdest); -PRINT_FN (accdest); - -INSERT_FN (xyz); - -PARSE_FN (ireg); -PRINT_FN (ireg); - -PARSE_FN (freg); -PRINT_FN (freg); - -PARSE_FN (ffstreg); -INSERT_FN (ffstreg); -EXTRACT_FN (ffstreg); -PRINT_FN (ffstreg); - -PARSE_FN (vi01); -PRINT_FN (vi01); - -INSERT_FN (luimm12); -EXTRACT_FN (luimm12); - -INSERT_FN (luimm12up6); - -INSERT_FN (luimm15); -EXTRACT_FN (luimm15); - -/* Various types of TXVU operands, including insn suffixes. - - Fields are: - - BITS SHIFT FLAGS PARSE_FN INSERT_FN EXTRACT_FN PRINT_FN - - Operand values are 128 + table index. This allows ASCII chars to be - included in the syntax spec. */ - -const txvu_operand txvu_operands[] = -{ - /* place holder (??? not sure if needed) */ -#define UNUSED 128 - { 0 }, - - /* Operands that exist in the same place for essentially the same purpose - in both upper and lower instructions. These don't have a U or L prefix. - Operands specific to the upper or lower instruction are so prefixed. */ - - /* Destination indicator attached to mnemonic, with leading '.' or '/'. - After parsing this, the value is stored in global `dest' so that the - register parser can verify the same choice of xyzw is used. */ -#define DOTDEST (UNUSED + 1) - { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX, - parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest }, - - /* ft reg, with vector specification same as DOTDEST */ -#define VFTREG (DOTDEST + 1) - { 5, TXVU_SHIFT_TREG, 0, parse_vfreg, 0, 0, print_vfreg }, - - /* fs reg, with vector specification same as DOTDEST */ -#define VFSREG (VFTREG + 1) - { 5, TXVU_SHIFT_SREG, 0, parse_vfreg, 0, 0, print_vfreg }, - - /* fd reg, with vector specification same as DOTDEST */ -#define VFDREG (VFSREG + 1) - { 5, TXVU_SHIFT_DREG, 0, parse_vfreg, 0, 0, print_vfreg }, - - /* Upper word operands. */ - - /* broadcast */ -#define UBC (VFDREG + 1) - { 2, 0, TXVU_OPERAND_SUFFIX, parse_bc, 0, extract_bc, print_sdest }, - - /* ftreg in broadcast case */ -#define UBCFTREG (UBC + 1) - { 5, TXVU_SHIFT_TREG, 0, parse_bcftreg, 0, 0, print_bcftreg }, - - /* accumulator dest */ -#define UACCDEST (UBCFTREG + 1) - { 0, 0, 0, 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 UXYZ (UACCDEST + 1) - { 0, 0, TXVU_OPERAND_FAKE, 0, insert_xyz, 0, 0 }, - - /* Lower word operands. */ - - /* 5 bit signed immediate. */ -#define LIMM5 (UXYZ + 1) - { 5, 6, TXVU_OPERAND_SIGNED, 0, 0, 0, 0 }, - - /* 11 bit signed immediate. */ -#define LIMM11 (LIMM5 + 1) - { 11, 0, TXVU_OPERAND_SIGNED, 0, 0, 0, 0 }, - - /* 15 bit unsigned immediate. */ -#define LUIMM15 (LIMM11 + 1) - { 15, 0, 0, 0, insert_luimm15, extract_luimm15, 0 }, - - /* ID register. */ -#define LIDREG (LUIMM15 + 1) - { 5, 6, 0, parse_ireg, 0, 0, print_ireg }, - - /* IS register. */ -#define LISREG (LIDREG + 1) - { 5, 11, 0, parse_ireg, 0, 0, print_ireg }, - - /* IT register. */ -#define LITREG (LISREG + 1) - { 5, 16, 0, parse_ireg, 0, 0, print_ireg }, - - /* FS reg, with FSF field selector. */ -#define LFSFFSREG (LITREG + 1) - { 5, 11, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg }, - - /* FS reg, no selector (choice of x,y,z,w is provided by opcode). */ -#define LFSREG (LFSFFSREG + 1) - { 5, 11, 0, parse_freg, 0, 0, print_freg }, - - /* FT reg, with FTF field selector. */ -#define LFTFFTREG (LFSREG + 1) - { 5, 16, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg }, - - /* VI01 register. */ -#define LVI01 (LFTFFTREG + 1) - { 0, 0, 0, parse_vi01, 0, 0, print_vi01 }, - - /* 24 bit unsigned immediate. */ -#define LUIMM24 (LVI01 + 1) - { 24, 0, 0, 0, 0, 0, 0 }, - - /* 12 bit unsigned immediate, split into 1 and 11 bit pieces. */ -#define LUIMM12 (LUIMM24 + 1) - { 12, 0, 0, 0, insert_luimm12, extract_luimm12, 0 }, - - /* upper 6 bits of 12 bit unsigned immediate */ -#define LUIMM12UP6 (LUIMM12 + 1) - { 12, 0, 0, 0, insert_luimm12up6, extract_luimm12, 0 }, - - /* 11 bit pc-relative signed immediate. */ -#define LPCREL11 (LUIMM12UP6 + 1) - { 11, 0, TXVU_OPERAND_SIGNED + TXVU_OPERAND_RELATIVE_BRANCH, 0, 0, 0, 0 }, - - /* Destination indicator, single letter only, with leading '.' or '/'. */ -#define LDOTDEST1 (LPCREL11 + 1) - { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX, - /* Note that we borrow the insert/extract/print functions from the - vector case. */ - parse_dotdest1, insert_dotdest, extract_dotdest, print_dotdest }, - - /* Destination indicator, single letter only, no leading '.'. */ -#define LDEST1 (LDOTDEST1 + 1) - { 0, 0, 0, parse_dest1, 0, 0, print_dest1 }, - -/* end of list place holder */ - { 0 } -}; - -/* Macros to put a field's value into the right place. */ -/* ??? If assembler needs these, move to opcode/txvu.h. */ - -/* value X, B bits, shift S */ -#define V(x,b,s) (((x) & ((1 << (b)) - 1)) << (s)) - -/* Field value macros for both upper and lower instructions. - These shift a value into the right place in the instruction. */ - -/* [FI] T reg field (remember it's V for value, not vector, here). */ -#define VT(x) V ((x), 5, TXVU_SHIFT_TREG) -/* [FI] S reg field. */ -#define VS(x) V ((x), 5, TXVU_SHIFT_SREG) -/* [FI] D reg field. */ -#define VD(x) V ((x), 5, TXVU_SHIFT_DREG) -/* DEST field. */ -#define VDEST(x) V ((x), 4, 21) - -/* Masks for fields in both upper and lower instructions. - These mask out all bits but the ones for the field in the instruction. */ - -#define MT VT (~0) -#define MS VS (~0) -#define MD VD (~0) -#define MDEST VDEST (~0) - -/* Upper instruction Value macros. */ - -/* Upper Flag bits. */ -#define VUF(x) V ((x), 5, 27) -/* Upper REServed two bits next to flag bits. */ -#define VURES(x) V ((x), 2, 25) -/* 4 bit opcode field. */ -#define VUOP4(x) V ((x), 4, 2) -/* 6 bit opcode field. */ -#define VUOP6(x) V ((x), 6, 0) -/* 9 bit opcode field. */ -#define VUOP9(x) V ((x), 9, 2) -/* 11 bit opcode field. */ -#define VUOP11(x) V ((x), 11, 0) -/* BroadCast field. */ -#define VUBC(x) V ((x), 2, 0) - -/* Upper instruction field masks. */ -#define MUUBITS (VUF (~0) + VURES (~0)) -#define MURES VURES (~0) -#define MUOP4 VUOP4 (~0) -#define MUOP6 VUOP6 (~0) -#define MUOP9 VUOP9 (~0) -#define MUOP11 VUOP11 (~0) - -/* A space, separates instruction name (mnemonic + mnemonic operands) from - operands. */ -#define SP ' ' -/* Commas separate operands. */ -#define C ',' -/* Special I,P,Q,R operands. */ -#define I 'i' -#define P 'p' -#define Q 'q' -#define R 'r' - -/* TXVU instructions. - [??? some of these comments are left over from the ARC port from which - this code is borrowed, delete in time] - - Longer versions of insns must appear before shorter ones (if gas sees - "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is - junk). This isn't necessary for `ld' because of the trailing ']'. - - Instructions that are really macros based on other insns must appear - before the real insn so they're chosen when disassembling. Eg: The `mov' - insn is really the `and' insn. - - This table is best viewed on a wide screen (161 columns). I'd prefer to - keep it this way. The rest of the file, however, should be viewable on an - 80 column terminal. */ - -/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has - a more general facility for dealing with macros which could be used if - we need to. */ - -/* These tables can't be `const' because members `next_asm' and `next_dis' are - computed at run-time. We could split this into two, as that would put the - constant stuff into a readonly section. */ - -struct txvu_opcode txvu_upper_opcodes[] = -{ - /* Macros appear first, so the disassembler will try them first. */ - /* ??? Any aliases? */ - /* ??? When close to being finished, clean up by aligning fields. */ - - /* The rest of these needn't be sorted, but it helps to find them if they are. */ - { "abs", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x1fd) }, - { "add", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x28) }, - { "addi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x22) }, - { "addq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x20) }, - { "add", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (0) }, - { "adda", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2bc) }, - { "addai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x23e) }, - { "addaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x23c) }, - { "adda", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0xf) }, - { "clip", { DOTDEST, SP, VFSREG }, MURES + MDEST + MT + MUOP11, VDEST (0xf) + VUOP11 (0x1ff) }, - { "ftoi0", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17c) }, - { "ftoi4", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17d) }, - { "ftoi12", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17e) }, - { "ftoi15", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17f) }, - { "itof0", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13c) }, - { "itof4", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13d) }, - { "itof12", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13e) }, - { "itof15", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13f) }, - { "madd", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x29) }, - { "maddi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x23) }, - { "maddq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x21) }, - { "madd", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x2) }, - { "madda", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2bd) }, - { "maddai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x23f) }, - { "maddaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x23d) }, - { "madda", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x2f) }, - { "max", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2b) }, - { "maxi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x2d) }, - { "max", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x4) }, - /* ??? mini or min? */ - { "mini", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2f) }, - { "minii", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x1f) }, - { "mini", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x5) }, - { "msub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2d) }, - { "msubi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x27) }, - { "msubq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x25) }, - { "msub", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x3) }, - { "msuba", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2fd) }, - { "msubai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x27f) }, - { "msubaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x27d) }, - { "msuba", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x3f) }, - { "mul", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2a) }, - { "muli", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x1e) }, - { "mulq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x1c) }, - { "mul", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (6) }, - { "mula", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2be) }, - { "mulai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x1fe) }, - { "mulaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x1fc) }, - { "mula", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x6f) }, - { "nop", { 0 }, MURES + MDEST + MT + MS + MUOP11, VUOP11 (0x2ff) }, - { "opmula", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG, UXYZ }, MURES + MUOP11, VUOP11 (0x2fe) }, - { "opmsub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG, UXYZ }, MURES + MUOP6, VUOP6 (0x2e) }, - { "sub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2c) }, - { "subi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x26) }, - { "subq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x24) }, - { "sub", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (1) }, - { "suba", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2fc) }, - { "subai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x27e) }, - { "subaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x27c) }, - { "suba", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x1f) } -}; -const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_upper_opcodes[0]); - -/* Lower instruction Value macros. */ - -/* 6 bit opcode. */ -#define VLOP6(x) V ((x), 6, 0) -/* 7 bit opcode. */ -#define VLOP7(x) V ((x), 7, 25) -/* 11 bit opcode. */ -#define VLOP11(x) V ((x), 11, 0) -/* 11 bit immediate. */ -#define VLIMM11(x) V ((x), 11, 0) -/* FTF field. */ -#define VLFTF(x) V ((x), 2, 23) -/* FSF field. */ -#define VLFSF(x) V ((x), 2, 21) -/* Upper bit of 12 bit unsigned immediate. */ -#define VLUIMM12TOP(x) V ((x), 1, 21) -/* Upper 4 bits of 15 bit unsigned immediate. */ -#define VLUIMM15TOP(x) VDEST (x) - -/* Lower instruction field masks. */ -#define MLOP6 VLOP6 (~0) -#define MLOP7 VLOP7 (~0) -#define MLOP11 VLOP11 (~0) -#define MLIMM11 VLIMM11 (~0) -#define MLB24 V (1, 1, 24) -#define MLUIMM12TOP VLUIMM12TOP (~0) -/* 12 bit unsigned immediates are split into two parts, 1 bit and 11 bits. - The upper 1 bit is part of the `dest' field. This mask is for the - other 3 bits of the dest field. */ -#define MLUIMM12UNUSED V (7, 3, 22) -#define MLUIMM15TOP MDEST - -struct txvu_opcode txvu_lower_opcodes[] = -{ - /* Macros appear first, so the disassembler will try them first. */ - /* ??? Any aliases? */ - /* ??? There isn't an explicit nop. Apparently it's "move vf0,vf0". */ - { "nop", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x33c) }, - - /* The rest of these needn't be sorted, but it helps to find them if they are. */ - { "b", { SP, LPCREL11 }, MLOP7 + MDEST + MT + MS, VLOP7 (0x20) }, - { "bal", { SP, LITREG, C, LPCREL11 }, MLOP7 + MDEST + MS, VLOP7 (0x21) }, - { "div", { SP, Q, C, LFSFFSREG, C, LFTFFTREG }, MLOP7 + MLOP11, VLOP7 (0x40) + VLOP11 (0x3bc) }, - { "eatan", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fd) }, - { "eatanxy", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77c) }, - { "eatanxz", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77d) }, - { "eexp", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fe) }, - { "eleng", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x74e) }, - { "ercpr", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7be) }, - { "erleng", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73f) }, - { "ersadd", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73d) }, - { "ersqrt", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bd) }, - { "esadd", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73c) }, - { "esin", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fc) }, - { "esqrt", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bc) }, - { "esum", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77e) }, - { "fcand", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x12) }, - { "fceq", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x10) }, - { "fcget", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x1c) }, - { "fcor", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x13) }, - { "fcset", { SP, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x11) }, - { "fmand", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1a) }, - { "fmeq", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x18) }, - { "fmor", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1b) }, - { "fsand", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x16) }, - { "fseq", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x14) }, - { "fsor", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x17) }, - { "fsset", { SP, LUIMM12UP6 }, MLOP7 + MLUIMM12UNUSED + V (~0, 6, 0) + MS + MT, VLOP7 (0x15) }, - { "iadd", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x30) }, - { "iaddi", { SP, LITREG, C, LISREG, C, LIMM5 }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x32) }, - { "iaddiu", { SP, LITREG, C, LISREG, C, LUIMM15 }, MLOP7, VLOP7 (0x08) }, - { "iand", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x34) }, - { "ibeq", { SP, LITREG, C, LISREG, C, LPCREL11 }, MLOP7 + MDEST, VLOP7 (0x28) }, - { "ibgez", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2f) }, - { "ibgtz", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2d) }, - { "iblez", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2e) }, - { "ibltz", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2c) }, - { "ibne", { SP, LITREG, C, LISREG, C, LPCREL11 }, MLOP7 + MDEST, VLOP7 (0x29) }, - { "ilw", { LDOTDEST1, SP, LITREG, C, LIMM11, '(', LISREG, ')', LDEST1 }, MLOP7, VLOP7 (0x04) }, - { "ilwr", { LDOTDEST1, SP, LITREG, C, '(', LISREG, ')', LDEST1 }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fe) }, - { "ior", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x35) }, - { "isub", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x31) }, - { "isubiu", { SP, LITREG, C, LISREG, C, LUIMM15 }, MLOP7, VLOP7 (0x09) }, - { "isw", { LDOTDEST1, SP, LITREG, C, LIMM11, '(', LISREG, ')', LDEST1 }, MLOP7, VLOP7 (0x05) }, - { "iswr", { LDOTDEST1, SP, LITREG, C, '(', LISREG, ')', LDEST1 }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3ff) }, - { "jalr", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x25) }, - { "jr", { SP, LISREG }, MLOP7 + MDEST + MT + MLIMM11, VLOP7 (0x24) }, - { "lq", { DOTDEST, SP, VFTREG, C, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x00) }, - { "lqd", { DOTDEST, SP, VFTREG, C, '(', '-', '-', LISREG, ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37e) }, - { "lqi", { DOTDEST, SP, VFTREG, C, '(', LISREG, '+', '+', ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37c) }, - /* Only a single VF reg is allowed here. We can use VFTREG because LDOTDEST1 - handles verifying only a single choice of xyzw is present. */ - { "mfir", { LDOTDEST1, SP, VFTREG, C, LISREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fc) }, - { "mfp", { DOTDEST, SP, VFTREG, C, P }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x67c) }, - { "move", { DOTDEST, SP, VFTREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33c) }, - { "mr32", { DOTDEST, SP, VFTREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33d) }, - { "mtir", { LDOTDEST1, SP, LITREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fd) }, - { "rget", { DOTDEST, SP, VFTREG, C, R }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43d) }, - { "rinit", { SP, R, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43e) }, - { "rnext", { DOTDEST, SP, VFTREG, C, R }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43c) }, - { "rsqrt", { SP, Q, C, LFSFFSREG, C, LFTFFTREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3be) }, - { "rxor", { SP, R, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43f) }, - { "sq", { DOTDEST, SP, VFTREG, C, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x01) }, - { "sqd", { DOTDEST, SP, VFTREG, C, '(', '-', '-', LISREG, ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37f) }, - { "sqi", { DOTDEST, SP, VFTREG, C, '(', LISREG, '+', '+', ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37d) }, - { "sqrt", { SP, Q, C, LFTFFTREG }, MLOP7 + VLFSF (~0) + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3bd) }, - { "waitp", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x7bf) }, - { "waitq", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x3bf) }, - { "xgkick", { SP, LISREG }, MLOP7 + MDEST + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6fc) }, - { "xitop", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6bd) }, - { "xtop", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6bc) } -}; -const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_lower_opcodes[0]); - -/* Value of DEST in use. - Each of the registers must specify the same value as the opcode. - ??? Perhaps remove the duplication? */ -static int state_vu_mnemonic_dest; - -/* Value of BC to use. - The register specified for the ftreg must match the broadcast register - specified in the opcode. */ -static int state_vu_mnemonic_bc; - -/* 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.] */ - -/* Utility to parse a `dest' spec. - Return the found value. - *PSTR is set to the character that terminated the parsing. - It is up to the caller to do any error checking. */ - -static long -u_parse_dest (pstr) - char **pstr; -{ - long dest = 0; - - while (**pstr) - { - switch (**pstr) - { - case 'x' : case 'X' : dest |= TXVU_DEST_X; break; - case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break; - case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break; - case 'w' : case 'W' : dest |= TXVU_DEST_W; break; - default : return dest; - } - ++*pstr; - } - - return dest; -} - -static long -parse_dotdest (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - long dest; - - if (**pstr != '.' && **pstr != '/') - { - *errmsg = "missing `.'"; - return 0; - } - - ++*pstr; - dest = u_parse_dest (pstr); - if (dest == 0 || isalnum (**pstr)) - { - *errmsg = "invalid `dest'"; - return 0; - } - - return dest; -} - -/* Parse a `dest' spec where only a single letter is allowed, - but the encoding handles all four. */ - -static long -parse_dotdest1 (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char c; - long dest; - - if (**pstr != '.' && **pstr != '/') - { - *errmsg = "missing `.'"; - return 0; - } - - ++*pstr; - switch (**pstr) - { - case 'x' : case 'X' : dest = TXVU_DEST_X; break; - case 'y' : case 'Y' : dest = TXVU_DEST_Y; break; - case 'z' : case 'Z' : dest = TXVU_DEST_Z; break; - case 'w' : case 'W' : dest = TXVU_DEST_W; break; - default : *errmsg = "invalid `dest'"; return 0; - } - ++*pstr; - c = tolower (**pstr); - if (c == 'x' || c == 'y' || c == 'z' || c == 'w') - { - *errmsg = "only one of x,y,z,w can be specified"; - return 0; - } - if (isalnum (**pstr)) - { - *errmsg = "invalid `dest'"; - return 0; - } - - return dest; -} - -/* Parse a `dest' spec with no leading '.', where only a single letter is - allowed, but the encoding handles all four. The parsed value must match - that recorded in `dest'. */ - -static long -parse_dest1 (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char c; - long dest; - - dest = u_parse_dest (pstr); - if (dest != TXVU_DEST_X - && dest != TXVU_DEST_Y - && dest != TXVU_DEST_Z - && dest != TXVU_DEST_W) - { - *errmsg = "expecting one of x,y,z,w"; - return 0; - } - - if (dest != state_vu_mnemonic_dest) - { - *errmsg = "`dest' suffix does not match instruction `dest'"; - return 0; - } - - return dest; -} - -static void -insert_dotdest (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - /* Record the DEST value in use so the register parser can use it. */ - state_vu_mnemonic_dest = value; - *insn |= value << operand->shift; -} - -static long -extract_dotdest (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - /* Record the DEST value in use so the register printer can use it. */ - state_vu_mnemonic_dest = (*insn >> operand->shift) & ((1 << operand->bits) - 1); - return state_vu_mnemonic_dest; -} - -/* Utility to print a multiple dest spec. */ - -static void -u_print_dest (info, insn, value) - disassemble_info *info; - TXVU_INSN *insn; - long value; -{ - if (value & TXVU_DEST_X) - (*info->fprintf_func) (info->stream, "x"); - if (value & TXVU_DEST_Y) - (*info->fprintf_func) (info->stream, "y"); - if (value & TXVU_DEST_Z) - (*info->fprintf_func) (info->stream, "z"); - if (value & TXVU_DEST_W) - (*info->fprintf_func) (info->stream, "w"); -} - -static void -print_dotdest (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "."); - u_print_dest (info, insn, value); -} - -static void -print_dest1 (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - u_print_dest (info, insn, state_vu_mnemonic_dest); -} - -/* Utilities for single destination choice handling. */ - -static long -u_parse_sdest (pstr, errmsg) - char **pstr; - const char **errmsg; -{ - char c; - long dest = 0; - - switch (**pstr) - { - case 'x' : case 'X' : dest = TXVU_SDEST_X; break; - case 'y' : case 'Y' : dest = TXVU_SDEST_Y; break; - case 'z' : case 'Z' : dest = TXVU_SDEST_Z; break; - case 'w' : case 'W' : dest = TXVU_SDEST_W; break; - default : *errmsg = "only one of x,y,z,w can be specified"; return 0; - } - ++*pstr; - c = tolower (**pstr); - if (c == 'x' || c == 'y' || c == 'z' || c == 'w') - { - *errmsg = "only one of x,y,z,w can be specified"; - return 0; - } - if (isalnum (**pstr)) - { - *errmsg = "invalid `dest'"; - return 0; - } - - return dest; -} - -static void -print_sdest (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - char c; - - switch (value) - { - case TXVU_SDEST_X : c = 'x'; break; - case TXVU_SDEST_Y : c = 'y'; break; - case TXVU_SDEST_Z : c = 'z'; break; - case TXVU_SDEST_W : c = 'w'; break; - } - - (*info->fprintf_func) (info->stream, "%c", c); -} - -/* Broadcase field. */ - -static long -parse_bc (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - long value = u_parse_sdest (pstr, errmsg); - - if (*errmsg) - return 0; - /* Save value for later verification in register parsing. */ - state_vu_mnemonic_bc = value; - return value; -} - -/* During the extraction process, save the bc field for use in - printing the bc register. */ - -static long -extract_bc (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - state_vu_mnemonic_bc = *insn & 3; - return state_vu_mnemonic_bc; -} - -static long -parse_vfreg (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - long reg; - int reg_dest; - - 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); - if (reg < 0 || reg > 31) - { - *errmsg = "invalid register number"; - return 0; - } - reg_dest = u_parse_dest (&str); - if (reg_dest == 0 || isalnum (*str)) - { - *errmsg = "invalid `dest'"; - return 0; - } - if (reg_dest != state_vu_mnemonic_dest) - { - *errmsg = "register `dest' does not match instruction `dest'"; - return 0; - } - *pstr = str; - return reg; -} - -static void -print_vfreg (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - disassemble_info *info; - TXVU_INSN *insn; - long value; -{ - (*info->fprintf_func) (info->stream, "vf%02ld", value); - u_print_dest (info, insn, state_vu_mnemonic_dest); -} - -/* FT register in broadcast case. */ - -static long -parse_bcftreg (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - 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); - if (reg < 0 || reg > 31) - { - *errmsg = "invalid register number"; - return 0; - } - reg_bc = u_parse_sdest (&str, errmsg); - if (*errmsg) - return 0; - if (reg_bc != state_vu_mnemonic_bc) - { - *errmsg = "register `bc' does not match instruction `bc'"; - return 0; - } - *pstr = str; - return reg; -} - -static void -print_bcftreg (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "vf%02ld", value); - print_sdest (opcode, operand, mods, insn, info, state_vu_mnemonic_bc); -} - -/* ACC handling. */ - -static long -parse_accdest (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - 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 = u_parse_dest (&str); - if (acc_dest == 0 || isalnum (*str)) - { - *errmsg = "invalid `dest'"; - return 0; - } - if (acc_dest != state_vu_mnemonic_dest) - { - *errmsg = "acc `dest' does not match instruction `dest'"; - return 0; - } - *pstr = str; - /* Value isn't used, but we must return something. */ - return 0; -} - -static void -print_accdest (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - disassemble_info *info; - TXVU_INSN *insn; - long value; -{ - (*info->fprintf_func) (info->stream, "acc"); - u_print_dest (info, insn, state_vu_mnemonic_dest); -} - -/* XYZ operand handling. - This simplifies the opmula,opmsub entries by keeping them equivalent to - the others. */ - -static void -insert_xyz (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - if (state_vu_mnemonic_dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z)) - *errmsg = "expecting `xyz' for `dest' value"; -} - -/* F[ST] register using selector in F[ST]F field. - Internally, the value is encoded in 7 bits: the 2 bit xyzw indicator - followed by the 5 bit register number. */ - -static long -parse_ffstreg (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - int reg, xyzw; - - 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); - if (reg < 0 || reg > 31) - { - *errmsg = "invalid register number"; - return 0; - } - xyzw = u_parse_sdest (&str, errmsg); - if (*errmsg) - return 0; - *pstr = str; - return reg | (xyzw << 5); -} - -static void -print_ffstreg (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "vf%02ld", value & TXVU_MASK_REG); - print_sdest (opcode, operand, mods, insn, info, (value >> 5) & 3); -} - -static void -insert_ffstreg (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - if (operand->shift == TXVU_SHIFT_SREG) - *insn |= VLFSF (value >> 5) | VS (value); - else - *insn |= VLFTF (value >> 5) | VT (value); -} - -static long -extract_ffstreg (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - if (operand->shift == TXVU_SHIFT_SREG) - return (((*insn & VLFSF (~0)) >> 21) << 5) | VS (*insn); - else - return (((*insn & VLFTF (~0)) >> 21) << 5) | VT (*insn); -} - -/* F register. */ - -static long -parse_freg (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - long reg; - - 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); - if (reg < 0 || reg > 31) - { - *errmsg = "invalid register number"; - return 0; - } - *pstr = str; - return reg; -} - -static void -print_freg (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "vf%02ld", value); -} - -/* I register. */ - -static long -parse_ireg (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - long reg; - - if (tolower (str[0]) != 'v' - || tolower (str[1]) != 'i') - { - *errmsg = "unknown register"; - return 0; - } - - /* FIXME: quick hack until the framework works. */ - start = str = str + 2; - while (*str && isdigit (*str)) - ++str; - reg = atoi (start); - if (reg < 0 || reg > 31) - { - *errmsg = "invalid register number"; - return 0; - } - *pstr = str; - return reg; -} - -static void -print_ireg (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "vi%02ld", value); -} - -/* VI01 register. */ - -static long -parse_vi01 (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - long reg; - - if (tolower (str[0]) != 'v' - || tolower (str[1]) != 'i') - { - *errmsg = "unknown register"; - return 0; - } - - /* FIXME: quick hack until the framework works. */ - start = str = str + 2; - while (*str && isdigit (*str)) - ++str; - reg = atoi (start); - if (reg != 1) - { - *errmsg = "vi01 required here"; - return 0; - } - *pstr = str; - return reg; -} - -static void -print_vi01 (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "vi01"); -} - -/* Lower instruction 12 bit unsigned immediate. */ - -static void -insert_luimm12 (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value); -} - -static long -extract_luimm12 (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return (((*insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (*insn); -} - -/* Lower instruction 12 bit unsigned immediate, upper 6 bits. */ - -static void -insert_luimm12up6 (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0); -} - -/* Lower instruction 15 bit unsigned immediate. */ - -static void -insert_luimm15 (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ - *insn |= VLUIMM15TOP (value >> 11) | VLIMM11 (value); -} - -static long -extract_luimm15 (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return (((*insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (*insn); -} - -/* PKE support. */ - -PARSE_FN (pke_ibit); -PRINT_FN (pke_ibit); - -PARSE_FN (pke_mode); -PRINT_FN (pke_mode); - -PARSE_FN (pke_ability); -PRINT_FN (pke_ability); - -PARSE_FN (pke_mpgaddr); - -PARSE_FN (pke_varlendata); - -PARSE_FN (pke_imrbits); -PRINT_FN (pke_imrbits); - -PARSE_FN (pke_unpacktype); -PRINT_FN (pke_unpacktype); - -PARSE_FN (pke_unpackaddr); - -const txvu_operand pke_operands[] = -{ - /* place holder (??? not sure if needed) */ -#define PKE_UNUSED 128 - { 0 }, - - /* The I bit. */ -#define PKE_IBIT (PKE_UNUSED + 1) - { 1, 31, TXVU_OPERAND_SUFFIX, parse_pke_ibit, 0, 0, print_pke_ibit }, - - /* An 8 bit unsigned immediate, stored in upper 8 bits of immed field. */ -#define PKE_UIMM8UP (PKE_IBIT + 1) - { 8, 8, 0, 0, 0, 0, 0 }, - - /* An 8 bit unsigned immediate, stored in lower 8 bits of immed field. */ -#define PKE_UIMM8LO (PKE_UIMM8UP + 1) - { 8, 0, 0, 0, 0, 0, 0 }, - - /* An 16 bit unsigned immediate, stored in lower 8 bits of immed field. */ -#define PKE_UIMM16 (PKE_UIMM8LO + 1) - { 16, 0, 0, 0, 0, 0, 0 }, - - /* The mode operand of `stmod'. */ -#define PKE_MODE (PKE_UIMM16 + 1) - { 2, 0, 0, parse_pke_mode, 0, 0, print_pke_mode }, - - /* The ability operand of `mskpath3'. */ -#define PKE_ABILITY (PKE_MODE + 1) - { 1, 15, 0, parse_pke_ability, 0, 0, print_pke_ability }, - - /* A VU address. */ -#define PKE_VUADDR (PKE_ABILITY + 1) - { 16, 0, 0, 0, 0, 0, 0 }, - - /* A 32 bit immediate, appearing in 2nd,3rd,4th,5th words. */ -#define PKE_UIMM32 (PKE_VUADDR + 1) - { 32, 0, 0, 0, 0, 0, 0 }, - - /* VU address used by mpg insn. */ -#define PKE_MPGADDR (PKE_UIMM32 + 1) - { 16, 0, TXVU_OPERAND_ADDRESS, parse_pke_mpgaddr, 0, 0, 0 }, - - /* A variable length data specifier. - Any of: file name, number, or '*'. */ -#define PKE_VARLENDATA (PKE_MPGADDR + 1) - { 0, 0, 0, parse_pke_varlendata, 0, 0, 0 }, - - /* The IMR bits of the unpack insn. */ -#define PKE_IMRBITS (PKE_VARLENDATA + 1) - { 0, 0, TXVU_OPERAND_SUFFIX, parse_pke_imrbits, 0, 0, print_pke_imrbits }, - - /* The type of the unpack insn. */ -#define PKE_UNPACKTYPE (PKE_IMRBITS + 1) - { 4, 24, 0, parse_pke_unpacktype, 0, 0, print_pke_unpacktype }, - - /* VU address used by unpack insn. */ -#define PKE_UNPACKADDR (PKE_UIMM32 + 1) - { 16, 0, TXVU_OPERAND_ADDRESS, parse_pke_unpackaddr, 0, 0, 0 }, - - /* Fake operand processed at end of parsing an insn to set the length. */ - -/* end of list place holder */ - { 0 } -}; - -/* Field mask values. */ -#define MPKECMD 0x7f000000 -#define MPKEUNPACK 0x60000000 - -/* Field values. */ -#define VPKECMD(x) V ((x), 7, 24) -#define VPKEUNPACK V (0x60, 8, 24) - -struct txvu_opcode pke_opcodes[] = -{ - { "pkenop", { PKE_IBIT }, 0x7fffffff, 0 }, - { "stcycle", { PKE_IBIT, SP, PKE_UIMM8UP, C, PKE_UIMM8LO }, MPKECMD, VPKECMD (1) }, - { "offset", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (2) }, - { "base", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (3) }, - { "itop", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (4) }, - { "stmod", { PKE_IBIT, SP, PKE_MODE }, MPKECMD + V (~0, 14, 2), VPKECMD (5) }, - { "mskpath3", { PKE_IBIT, SP, PKE_ABILITY }, MPKECMD + V (~0, 15, 0), VPKECMD (6) }, - { "pkemark", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (7) }, - { "flushe", { PKE_IBIT }, MPKECMD, VPKECMD (16) }, - { "flush", { PKE_IBIT }, MPKECMD, VPKECMD (17) }, - { "flusha", { PKE_IBIT }, MPKECMD, VPKECMD (19) }, - { "pkemscal", { PKE_IBIT, SP, PKE_VUADDR }, MPKECMD, VPKECMD (20) }, - { "pkemscnt", { PKE_IBIT }, MPKECMD, VPKECMD (23) }, - { "pkemscalf", { PKE_IBIT, SP, PKE_VUADDR }, MPKECMD, VPKECMD (21) }, - - /* 2 word instructions */ - { "stmask", { PKE_IBIT, SP, PKE_UIMM32 }, MPKECMD, VPKECMD (32), PKE_OPCODE_LEN2 }, - - /* 5 word instructions */ - { "strow", { PKE_IBIT, SP, PKE_UIMM32, C, PKE_UIMM32, C, PKE_UIMM32, C, PKE_UIMM32 }, MPKECMD, VPKECMD (48), PKE_OPCODE_LEN5 }, - { "stcol", { PKE_IBIT, SP, PKE_UIMM32, C, PKE_UIMM32, C, PKE_UIMM32, C, PKE_UIMM32 }, MPKECMD, VPKECMD (49), PKE_OPCODE_LEN5 }, - - /* variable length instructions */ - { "mpg", { PKE_IBIT, SP, PKE_MPGADDR, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x4a), PKE_OPCODE_LENVAR + PKE_OPCODE_MPG }, - { "direct", { PKE_IBIT, SP, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x50), PKE_OPCODE_LENVAR + PKE_OPCODE_DIRECT }, - { "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 pke_opcodes_count = sizeof (pke_opcodes) / sizeof (pke_opcodes[0]); - -/* Non-zero if a variable length instruction was parsed. */ -static int state_pke_varlen_p; - -/* Length of parsed insn, in 32 bit words, or 0 if unknown. */ -static int state_pke_len; - -/* PKE parse,insert,extract,print helper fns. */ - -static long -parse_pke_ibit (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - 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 'i' : flags = 1; break; - default : *errmsg = "unknown flag"; return 0; - } - } - - *pstr = str + 1; - return flags; -} - -static void -print_pke_ibit (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - if (value) - (*info->fprintf_func) (info->stream, "[i]"); -} - -static const keyword stmod_modes[] = { - { PKE_MODE_DIRECT, "direct" }, - { PKE_MODE_ADD, "add" }, - { PKE_MODE_ADDROW, "addrow" }, - { 0, 0 } -}; - -static long -parse_pke_mode (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - int mode; - char *str = *pstr; - char *start; - char c; - - start = str; - str = scan_symbol (str); - c = *str; - *str = 0; - mode = lookup_keyword_value (stmod_modes, start, 0); - *str = c; - if (mode != -1) - { - *pstr = str; - return mode; - } - *errmsg = "invalid mode"; - return 0; -} - -static void -print_pke_mode (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - disassemble_info *info; - TXVU_INSN *insn; - long value; -{ - const char *name = lookup_keyword_name (stmod_modes, value); - - if (name) - (*info->fprintf_func) (info->stream, name); - else - (*info->fprintf_func) (info->stream, "???"); -} - -static long -parse_pke_ability (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - - if (strncasecmp (str, "disable", 7) == 0) - { - *pstr += 7; - return 0; - } - else if (strncasecmp (str, "enable", 6) == 0) - { - *pstr += 6; - return 1; - } - *errmsg = "invalid ability"; - return 0; -} - -static void -print_pke_ability (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - if (value) - (*info->fprintf_func) (info->stream, "enable"); - else - (*info->fprintf_func) (info->stream, "disable"); -} - -static long -parse_pke_mpgaddr (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - - if (*str == '*') - { - ++*pstr; - return 0; /* FIXME:indicate * somehow */ - } - - start = str; - str = strchr (str, ','); - if (! str) - { - *errmsg = "invalid mpg address"; - return 0; - } - - /* FIXME: call back to expression() to parse address. */ - - *pstr = str; - return 0; -} - -/* The result here is either the length specified, - or PKE_VARLENDATA_FILE or PKE_VARLENDATA_UNKNOWN. */ - -static long -parse_pke_varlendata (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - - if (*str == '*') - { - ++*pstr; - return 0; /* FIXME:indicate * somehow */ - } - - start = str; - - /* FIXME: call back to expression() to parse address, - and pick out filename if such. */ - - *pstr = str + strlen (str); - return 0; -} - -static long -parse_pke_imrbits (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - 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 'i' : flags |= PKE_FLAG_I; break; - case 'm' : flags |= PKE_FLAG_M; break; - case 'r' : flags |= PKE_FLAG_R; break; - default : *errmsg = "unknown pke flag"; return 0; - } - } - - *pstr = str + 1; - return flags; -} - -static void -print_pke_imrbits (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - if (value) - { - (*info->fprintf_func) (info->stream, "["); - if (value & PKE_FLAG_I) - (*info->fprintf_func) (info->stream, "i"); - if (value & PKE_FLAG_M) - (*info->fprintf_func) (info->stream, "m"); - if (value & PKE_FLAG_R) - (*info->fprintf_func) (info->stream, "r"); - (*info->fprintf_func) (info->stream, "]"); - } -} - -static const keyword unpack_types[] = { - { PKE_UNPACK_S_32, "s_32" }, - { PKE_UNPACK_S_16, "s_16" }, - { PKE_UNPACK_S_8, "s_8" }, - { PKE_UNPACK_V2_32, "v2_32" }, - { PKE_UNPACK_V2_16, "v2_16" }, - { PKE_UNPACK_V2_8, "v2_8" }, - { PKE_UNPACK_V3_32, "v3_32" }, - { PKE_UNPACK_V3_16, "v3_16" }, - { PKE_UNPACK_V3_8, "v3_8" }, - { PKE_UNPACK_V4_32, "v4_32" }, - { PKE_UNPACK_V4_16, "v4_16" }, - { PKE_UNPACK_V4_8, "v4_8" }, - { PKE_UNPACK_V4_5, "v4_5" }, - { 0, 0 } -}; - -static long -parse_pke_unpacktype (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - int type; - char *str = *pstr; - char *start; - char c; - - start = str; - str = scan_symbol (str); - c = *str; - *str = 0; - type = lookup_keyword_value (unpack_types, start, 0); - *str = c; - if (type != -1) - { - *pstr = str; - return type; - } - *errmsg = "invalid unpack type"; - return 0; -} - -static void -print_pke_unpacktype (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - const char *name = lookup_keyword_name (unpack_types, value); - - if (name) - (*info->fprintf_func) (info->stream, name); - else - (*info->fprintf_func) (info->stream, "???"); -} - -static long -parse_pke_unpackaddr (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ -} - -/* External PKE supporting routines. */ - -/* Return non-zero if the just parsed pke insn has variable length. */ - -int -pke_varlen_p () -{ - /* This shouldn't be called unless a pke insn was parsed. - Also, we want to catch errors in parsing that don't set this. */ - if (state_pke_varlen_p == -1) - abort (); - - return state_pke_varlen_p; -} - -/* Return length, in 32 bit words, of just parsed pke insn, - or 0 if unknown. */ - -int -pke_len () -{ - /* This shouldn't be called unless a pke insn was parsed. - Also, we want to catch errors in parsing that don't set this. */ - if (state_pke_len == -1) - abort (); - - return state_pke_len; -} - -/* DMA support. */ - -PARSE_FN (dma_flags); -INSERT_FN (dma_flags); -EXTRACT_FN (dma_flags); -PRINT_FN (dma_flags); - -PARSE_FN (dma_data); -INSERT_FN (dma_data); -EXTRACT_FN (dma_data); -PRINT_FN (dma_data); - -PARSE_FN (dma_next); -INSERT_FN (dma_next); -EXTRACT_FN (dma_next); -PRINT_FN (dma_next); - -const txvu_operand dma_operands[] = -{ - /* place holder (??? not sure if needed) */ -#define DMA_UNUSED 128 - { 0 }, - - /* dma tag flag bits */ -#define DMA_FLAGS (DMA_UNUSED + 1) - { 0, 0, TXVU_OPERAND_SUFFIX, - parse_dma_flags, insert_dma_flags, extract_dma_flags, print_dma_flags }, - - /* dma data spec */ -#define DMA_DATA (DMA_FLAGS + 1) - { 0, 0, TXVU_OPERAND_DMA_COUNT, - 0, insert_dma_data, extract_dma_data, print_dma_data }, - - /* dma data finalization spec */ -#define DMA_DATA2 (DMA_DATA + 1) - { 0, 0, TXVU_OPERAND_FAKE, - parse_dma_data2, 0, 0, 0}, - - /* dma next tag spec */ -#define DMA_ADDR (DMA_DATA2 + 1) - { 0, 0, 0, - parse_dma_addr, insert_dma_addr, extract_dma_addr, print_dma_addr}, - -/* end of list place holder */ - { 0 } -}; - -struct txvu_opcode dma_opcodes[] = -{ - /* ??? Some of these may take optional arguments. - The way to handle that is to have multiple table entries, those with and - those without the optional arguments. */ -/*TODO*/ { "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 1}, -/*TODO*/ { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 2}, - { "dmaend", { DMA_FLAGS, SP, DMA_DATA, DMA_DATA2}, 0, 3}, - { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 4}, -/*TODO*/ { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 5}, -/*TODO { "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_PTR_ADDR}, 0, 6}, */ -/*TODO { "dmarefs", { DMA_FLAGS, SP, DMA_DATA, C, DMA_PTR_ADDR}, 0, 7}, */ -/*TODO*/ { "dmaret", { DMA_FLAGS, SP, DMA_DATA, DMA_DATA2}, 0, 8} -/*TODO*/ { "dmaret", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 9} -}; -const int dma_opcodes_count = sizeof (dma_opcodes) / sizeof (dma_opcodes[0]); - -/* Did the current DMA instruction has specify "*" as its length operand? --1=uninitialized, 0=no, 1=yes. */ -static int state_dma_operand_count_p; - -/* DMA parse,insert,extract,print helper fns. */ - -static long -parse_dma_flags (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - 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; - } - } - - *pstr = str + 1; - return flags; -} - -static void -insert_dma_flags (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_dma_flags (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_dma_flags (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - 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 -parse_dma_data2( opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - /* - If txvu_dma_operand_count() < 0 error - if txvu_dma_operand_count() > 0 - if dmaref || dmarefs - compute from two related symbols - else - compute from current addr and end symbol - store value to count field? - */ -} - -static void -insert_dma_data (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_dma_data (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_dma_data (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "???"); -} - -static long -parse_dma_addr (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *start = *pstr; - char *end = scan_symbol( start); - - if( end == start ) - { - *errmsg = "invalid dma next tag"; - return 0; - } - - /* FIXME: unfinished - if txvu_dma_operand_count() > 0 - if dmaref || dmarefs - this operand must be a symbol (vs an expression) - lookup the symbol - store the symbol's value in the addr field (relocs?) - compute the end_symbol's name - lookup the end_symbol - if not found: error - compute the length as _$<name>-<name> - else - evaluate the operand as an expression - store the value to the count field - compute the length as _$EndDma-. - store the count field - else - evaluate the operand as an expression - store the value to the count field - */ - - parse_dma_data2( opcode, operand, mods, pstr, errmsg); - - *pstr = end; - return 0; -} - -static void -insert_dma_addr (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_dma_addr (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_dma_addr (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "???"); -} - -/* GPUIF support. */ - -PARSE_FN (gpuif_prim); -INSERT_FN (gpuif_prim); -EXTRACT_FN (gpuif_prim); -PRINT_FN (gpuif_prim); - -PARSE_FN (gpuif_regs); -INSERT_FN (gpuif_regs); -EXTRACT_FN (gpuif_regs); -PRINT_FN (gpuif_regs); - -PARSE_FN (gpuif_nloop); -INSERT_FN (gpuif_nloop); -EXTRACT_FN (gpuif_nloop); -PRINT_FN (gpuif_nloop); - -PARSE_FN (gpuif_eop); -INSERT_FN (gpuif_eop); -EXTRACT_FN (gpuif_eop); -PRINT_FN (gpuif_eop); - -const txvu_operand gpuif_operands[] = -{ - /* place holder (??? not sure if needed) */ -#define GPUIF_UNUSED 128 - { 0 }, - - /* PRIM=foo operand */ -#define GPUIF_PRIM (GPUIF_UNUSED + 1) - { 0, 0, 0, parse_gpuif_prim, insert_gpuif_prim, extract_gpuif_prim, print_gpuif_prim }, - - /* REGS=foo operand */ -#define GPUIF_REGS (GPUIF_PRIM + 1) - { 0, 0, 0, parse_gpuif_regs, insert_gpuif_regs, extract_gpuif_regs, print_gpuif_regs }, - - /* NLOOP=foo operand */ -#define GPUIF_NLOOP (GPUIF_REGS + 1) - { 0, 0, 0, parse_gpuif_nloop, insert_gpuif_nloop, extract_gpuif_nloop, print_gpuif_nloop }, - - /* EOP operand */ -#define GPUIF_EOP (GPUIF_NLOOP + 1) - { 0, 0, 0, parse_gpuif_eop, insert_gpuif_eop, extract_gpuif_eop, print_gpuif_eop }, - -/* end of list place holder */ - { 0 } -}; - -struct txvu_opcode gpuif_opcodes[] = -{ - /* Some of these may take optional arguments. - The way this is handled is to have multiple table entries, those with and - those without the optional arguments. - !!! The order here is important. The code that scans this table assumes - that if it reaches the end of a syntax string there is nothing more to - parse. This means that longer versions of instructions must appear before - shorter ones. Otherwise the text at the "end" of a longer one may be - interpreted as junk when the parser is using a shorter version of the - syntax string. */ - - { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_EOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_NLOOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_REGS, C, GPUIF_EOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_REGS, C, GPUIF_NLOOP }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS }, 0, 1 }, - { "gpuifpacked", { SP, GPUIF_REGS }, 0, 1 }, - - { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 2 }, - { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_EOP }, 0, 2 }, - { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_NLOOP }, 0, 2 }, - { "gpuifreglist", { SP, GPUIF_REGS }, 0, 2 }, - - { "gpuifimage", { SP, GPUIF_NLOOP }, 0, 3 }, - { "gpuifimage", { 0 }, 0, 3 }, -}; -const int gpuif_opcodes_count = sizeof (gpuif_opcodes) / sizeof (gpuif_opcodes[0]); - -/* GPUIF parse,insert,extract,print helper fns. */ - -static long -parse_gpuif_prim (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - long prim; - - if (strncasecmp (str, "prim=", 5) != 0) - { - *errmsg = "missing PRIM spec"; - return 0; - } - str += 5; - for (start = str; isalnum (*str); ++str) - continue; - if (str == start) - { - *errmsg = "missing PRIM spec"; - return 0; - } - /* FIXME: Yes, atoi doesn't do error checking. Later. */ - prim = atoi (start); - *pstr = str; - return prim; -} - -static void -insert_gpuif_prim (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_gpuif_prim (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_gpuif_prim (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "???"); -} - -static const keyword gpuif_regs[] = { - { GPUIF_REG_PRIM, "prim" }, - { GPUIF_REG_RGBAQ, "rgbaq" }, - { GPUIF_REG_ST, "st" }, - { GPUIF_REG_UV, "uv" }, - { GPUIF_REG_XYZF2, "xyzf2" }, - { GPUIF_REG_TEXCLUT_1, "texclut_1" }, - { GPUIF_REG_TEXCLUT_2, "texclut_2" }, - { GPUIF_REG_TEX0_1, "tex0_1" }, - { GPUIF_REG_TEX0_2, "tex0_2" }, - { GPUIF_REG_TEX1_1, "tex1_1" }, - { GPUIF_REG_TEX1_2, "tex1_2" }, - { GPUIF_REG_XYZF3, "xyzf3" }, - { GPUIF_REG_PRMODE, "prmode" }, - { GPUIF_REG_A_D, "a_d" }, - { GPUIF_REG_NOP, "nop" }, - { 0, 0 } -}; - -/* Parse a REGS= spec. - The result is ???. */ - -static long -parse_gpuif_regs (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - char c; - int reg; - - if (strncasecmp (str, "regs=", 5) != 0) - { - *errmsg = "missing REGS spec"; - return 0; - } - str += 5; - SKIP_BLANKS (str); - if (*str != '{') - { - *errmsg = "missing '{' in REGS spec"; - return 0; - } - ++str; - - while (*str && *str != '}') - { - /* Pick out the register name. */ - - SKIP_BLANKS (str); - start = str; - str = scan_symbol (str); - if (str == start) - { - *errmsg = "invalid REG"; - return 0; - } - - /* Look it up in the table. */ - - c = *str; - *str = 0; - reg = lookup_keyword_value (gpuif_regs, start, 0); - *str = c; - if (reg == -1) - { - *errmsg = "invalid REG"; - return 0; - } - - /* FIXME: save `reg' away somewhere */ - - /* Prepare for the next one. */ - - SKIP_BLANKS (str); - if (*str == ',') - ++str; - else if (*str != '}') - break; - } - if (*str != '}') - { - *errmsg = "missing '{' in REGS spec"; - return 0; - } - - *pstr = str + 1; - return 0; /* FIXME */ -} - -static void -insert_gpuif_regs (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_gpuif_regs (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_gpuif_regs (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "???"); -} - -static long -parse_gpuif_nloop (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - char *str = *pstr; - char *start; - char c; - int nloop; - - if (strncasecmp (str, "nloop=", 6) != 0) - { - *errmsg = "missing NLOOP spec"; - return 0; - } - str += 6; - SKIP_BLANKS (str); - start = str; - str = scan_symbol (str); - if (str == start) - { - *errmsg = "invalid NOOP spec"; - return 0; - } - /* FIXME: error checking */ - nloop = atoi (start); - *pstr = str; - return nloop; -} - -static void -insert_gpuif_nloop (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_gpuif_nloop (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_gpuif_nloop (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - long value; -{ - (*info->fprintf_func) (info->stream, "???"); -} - -static long -parse_gpuif_eop (opcode, operand, mods, pstr, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - char **pstr; - const char **errmsg; -{ - if (strncasecmp (*pstr, "eop", 3) == 0) - { - *pstr += 3; - return 1; - } - *errmsg = "missing `EOP'"; - return 0; -} - -static void -insert_gpuif_eop (opcode, operand, mods, insn, value, errmsg) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - long value; - const char **errmsg; -{ -} - -static long -extract_gpuif_eop (opcode, operand, mods, insn, pinvalid) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - int *pinvalid; -{ - return 0; -} - -static void -print_gpuif_eop (opcode, operand, mods, insn, info, value) - const txvu_opcode *opcode; - const txvu_operand *operand; - int mods; - TXVU_INSN *insn; - disassemble_info *info; - 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 () -{ - state_vu_mnemonic_dest = -1; - state_vu_mnemonic_bc = -1; - state_pke_varlen_p = -1; - state_pke_len = -1; - state_dma_operand_count_p = -1; -} - -/* -Query or set the current type of a DMA length operand, explicit or computed by "as". -The return value is the setting before "action" is applied: - -1=uninitialized, 0=explicit, +1=computed -The value of "action" is interpreted as: - -1=no change, 0=set explicit, +1=set computed -*/ -int -txvu_dma_operand_count( action) -{ - int result = state_dma_operand_count; - - if( action == 0) - state_dma_operand_count = 0; - else if( action > 0) - state_dma_operand_count_p = 1; - - return result; -} - -/* Called by the disassembler before printing an instruction. */ - -void -txvu_opcode_init_print () -{ - state_vu_mnemonic_dest = -1; - state_vu_mnemonic_bc = -1; - state_pke_varlen_p = -1; - state_pke_len = -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 txvu_opcode *upper_opcode_map[26 + 1]; -static txvu_opcode *lower_opcode_map[26 + 1]; - -/* Indexed by insn code. Points to chain of opcodes with same insn code. */ -static txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1]; -static 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]; - } - - /* FIXME: We just hash everything to the same value for the rest. - Quick hack while other things are worked on. */ - - /* 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 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 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 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 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 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 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 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 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 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 txvu_opcode * -gpuif_opcode_lookup_dis (insn) - TXVU_INSN insn; -{ - return &gpuif_opcodes[0]; -} - -/* Misc. utilities. */ - -/* Scan a symbol and return a pointer to one past the end. */ - -static char * -scan_symbol (sym) - char *sym; -{ - while (*sym && issymchar (*sym)) - ++sym; - return sym; -} - -/* Given a keyword, look up its value, or -1 if not found. */ - -static int -lookup_keyword_value (table, name, case_sensitive_p) - const keyword *table; - const char *name; - int case_sensitive_p; -{ - const keyword *p; - - if (case_sensitive_p) - { - for (p = table; p->name; ++p) - if (strcmp (name, p->name) == 0) - return p->value; - } - else - { - for (p = table; p->name; ++p) - if (strcasecmp (name, p->name) == 0) - return p->value; - } - - return -1; -} - -/* Given a keyword's value, look up its name, or NULL if not found. */ - -static const char * -lookup_keyword_name (table, value) - const keyword *table; - int value; -{ - const keyword *p; - - for (p = table; p->name; ++p) - if (value == p->value) - return p->name; - - return NULL; -} |