Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cray1_sim.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 static const char USMID[] = "@(#)30/cray1_sim.c 30.0    03/18/98 12:06:00";
00036 
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <fcntl.h>
00042 #include <errno.h>
00043 #include <sys/types.h>
00044 #include <unistd.h>
00045 
00046 /************************* Cray Intrinsic Simulator **********************/
00047 
00048 /* Simulate Cray library intrinsics if this module is loaded */
00049 
00050 /* Primary machine types (Triton_IEEE = T90 + ar_float_format == IEEE) */
00051 
00052 #define YMP             7
00053 #define C90             8
00054 #define T3D             10
00055 #define T90             11
00056 #define T3E             12
00057 
00058 #include "arith.internal.h"
00059 #include "int64.h"
00060 
00061 #if !defined(__mips)
00062 
00063 int ar_mach_type = 0;
00064 int ar_rounding_modes = 0;
00065 int ar_underflow_modes = 0;
00066 
00067 extern char AR_libmv2[];
00068 extern char AR_version[];
00069 
00070 #define CRAY_FLOAT_64           (UNROUNDED_TYPE(AR_Float_Cray1_64))
00071 #define CRAY_FLOAT_128          (UNROUNDED_TYPE(AR_Float_Cray1_128))
00072 #define CRAY_COMPLEX_64         (UNROUNDED_TYPE(AR_Complex_Cray1_64))
00073 #define CRAY_COMPLEX_128        (UNROUNDED_TYPE(AR_Complex_Cray1_128))
00074 
00075 #define IEEE_FLOAT_64           (UNROUNDED_TYPE(AR_Float_IEEE_NR_64))
00076 #define IEEE_FLOAT_128          (UNROUNDED_TYPE(AR_Float_IEEE_NR_128))
00077 #define IEEE_COMPLEX_64         (UNROUNDED_TYPE(AR_Complex_IEEE_NR_64))
00078 #define IEEE_COMPLEX_128        (UNROUNDED_TYPE(AR_Complex_IEEE_NR_128))
00079 
00080 static AR_TYPE integer_64_s             = AR_Int_64_S;
00081 static AR_TYPE integer_64_u             = AR_Int_64_U;
00082 static AR_TYPE integer_128_s    = AR_Int_128_S;
00083 static AR_TYPE integer_128_u    = AR_Int_128_U;
00084 
00085 static AR_TYPE cray_float_64    = (AR_TYPE) CRAY_FLOAT_64;
00086 static AR_TYPE cray_float_128   = (AR_TYPE) CRAY_FLOAT_128;
00087 static AR_TYPE cray_complex_64  = (AR_TYPE) CRAY_COMPLEX_64;
00088 static AR_TYPE cray_complex_128 = (AR_TYPE) CRAY_COMPLEX_128;
00089 
00090 static AR_TYPE ieee_float_64    = (AR_TYPE) IEEE_FLOAT_64;
00091 static AR_TYPE ieee_float_128   = (AR_TYPE) IEEE_FLOAT_128;
00092 static AR_TYPE ieee_complex_64  = (AR_TYPE) IEEE_COMPLEX_64;
00093 static AR_TYPE ieee_complex_128 = (AR_TYPE) IEEE_COMPLEX_128;
00094 
00095 #if _CRAY
00096 typedef unsigned long int64;
00097 #else
00098 typedef unsigned long long int64;
00099 #endif
00100 
00101 static int ar_sim_version = 0;          /* Simulation interface version id */
00102 
00103 #define DATA                    0                       /* Implicit data segment identifier */
00104 #define STACK                   1                       /* Stack segment identifier */
00105 
00106 #define STACK_SIZE              20480           /* # words to allocate for stack space */
00107 
00108 #define MAX_ARGS                8                       /* Max # of arguments supported */
00109 #define MAX_EXT_ADDRS   16                      /* Max # of EXT addresses passed */
00110 
00111 static unsigned char*   code=NULL;
00112 static int64*                   stack=NULL;
00113 
00114 /* Define machine register and size variables */
00115 
00116 static int              JSZP;                           /* # parcels in a jump instruction */
00117 static int              VSZ;                            /* Max # words in vector register */
00118 
00119 static int64    AMASK;                          /* A-register size mask */
00120 static int64    ASB;                            /* A-register sign bit mask */
00121 
00122 static int64    A[8];
00123 static int64    S[8];
00124 
00125 static int64    B[64];
00126 static int64    T[64];
00127 
00128 static int              SR0;                            /* Status/mode Register 0 */
00129 
00130 static int              VL;                             /* Current vector length register */
00131 static int64    VM;
00132 static int64    VM1;
00133 static int64*   V;                                      /* V-registers allocated later */
00134 
00135 /* Intrinsic function interface variables */
00136 
00137 static int              numargs;
00138 static int              numargwds;
00139 static int              n_external_addresses;   /* Must be > 0 to be special */
00140 static char*    external_address[MAX_EXT_ADDRS];
00141 static long     external_length[MAX_EXT_ADDRS];
00142 
00143 /* Internal intrinsic-specified modes */
00144 
00145 #define RMMASK                  6                       /* Masks RM[01] bits in SR0 */
00146 
00147 #define INTERRUPT_INV   8
00148 #define INTERRUPT_DIV   16
00149 #define INTERRUPT_OVF   32
00150 #define INTERRUPT_UNF   64
00151 #define INTERRUPT_INX   128
00152 #define INTERRUPT_INP   256
00153 
00154 /* Debugging and disassembly variables */
00155 
00156 #ifdef DEBUG
00157 int ar_disasm    = 0;   /* =1 turns on disassembly output */
00158 int ar_disasm_BT = 0;   /* =1 turns on B/T load display output */
00159 int ar_disasm_V  = 0;   /* =1 turns on vector results display output */
00160 
00161 #define DISASM0(fmt)    if(ar_disasm) fprintf(stderr,fmt); else
00162 #define DISASM1(fmt,u)  if(ar_disasm) fprintf(stderr,fmt,u); else
00163 #define DISASM2(fmt,u,v)  \
00164                         if(ar_disasm) fprintf(stderr,fmt,u,v); else
00165 #define DISASM3(fmt,u,v,w)  \
00166                         if(ar_disasm) fprintf(stderr,fmt,u,v,w); else
00167 #define DISASM4(fmt,u,v,w,x)  \
00168                         if(ar_disasm) fprintf(stderr,fmt,u,v,w,x); else
00169 #define DISASM5(fmt,u,v,w,x,y)  \
00170                         if(ar_disasm) fprintf(stderr,fmt,u,v,w,x,y); else
00171 #define DISASMB(b,c,ft) if (ar_disasm) {                                \
00172                             if (ar_disasm_BT) {                         \
00173                                 for(i=0; i<(c); i++)                    \
00174                                     DISASM2("%s0x%*.*llx\n",            \
00175                                             ((i==0)?ft:"\t\t\t\t\t"),   \
00176                                             BVAL(((b)+i)&077));         \
00177                                 if(i==0)                                \
00178                                     DISASM0("\n");                      \
00179                             } else {                                    \
00180                                 DISASM0("\n");                          \
00181                             }                                           \
00182                         } else
00183 #define DISASMT(t,c,ft) if (ar_disasm) {                                \
00184                             if (ar_disasm_BT) {                         \
00185                                 for(i=0; i<(c); i++)                    \
00186                                     DISASM2("%s0x%16.16llx\n",          \
00187                                             ((i==0)?ft:"\t\t\t\t\t"),   \
00188                                             T[((t)+i)&077]);            \
00189                                 if(i==0)                                \
00190                                     DISASM0("\n");                      \
00191                             } else {                                    \
00192                                 DISASM0("\n");                          \
00193                             }                                           \
00194                         } else
00195 #define DISASMV(v,ft)   if (ar_disasm) {                                \
00196                             if (ar_disasm_V) {                          \
00197                                 for(i=0; i<VL; i++)                     \
00198                                     DISASM2("%s0x%16.16llx\n",          \
00199                                             ((i==0)?ft:"\t\t\t\t\t"),   \
00200                                             V[v*VSZ+i]);                \
00201                                 if(VL==0)                               \
00202                                     DISASM0("\n");                      \
00203                             } else {                                    \
00204                                 DISASM0("\n");                          \
00205                             }                                           \
00206                         } else
00207 
00208 static int a_size;
00209 #define set_a_size(s)   a_size = (s) >> 2
00210 #define AVAL(i)         a_size, a_size, A[i]
00211 #define BVAL(jk)        a_size, a_size, B[jk]
00212 
00213 #else
00214 
00215 #define DISASM0(fmt)
00216 #define DISASM1(fmt,x)
00217 #define DISASM2(fmt,x,y)
00218 #define DISASM3(fmt,x,y,z)
00219 #define DISASM4(fmt,x,y,z,v)
00220 #define DISASM5(fmt,x,y,z,v,w)
00221 #define DISASMB(b,c,ft)
00222 #define DISASMT(t,c,ft)
00223 #define DISASMV(v,ft)
00224 
00225 #define set_a_size(s)
00226 
00227 #endif
00228 
00229 /* Internal prototype function specifications */
00230 
00231 static void     open_arith_file();
00232 static int64    load_pvp_word(long vaddr);
00233 static void     store_pvp_word(long vaddr, int64 word);
00234 
00235 static int      ar_imul64u(int64* result, int64 opnd1, int64 opnd2);
00236 
00237 int
00238 ar_clear_sim_state(AR_TYPE resulttype)
00239 {
00240 
00241 #ifdef DEBUG
00242         if (getenv("AR_DISASM") != NULL) {
00243                 ar_disasm = 1;
00244         }
00245         if (getenv("AR_DISASM_BT") != NULL) {
00246                 ar_disasm_BT = 1;
00247         }
00248         if (getenv("AR_DISASM_V") != NULL) {
00249                 ar_disasm_V = 1;
00250         }
00251 #endif
00252 
00253         /* Load arith data file on first intrinsic called */
00254 
00255         if(code == NULL)
00256                 open_arith_file();
00257 
00258         if(AR_CLASS(resulttype) == AR_CLASS_FLOAT) {
00259                 if((AR_FLOAT_FORMAT(resulttype) == AR_FLOAT_CRAY &&
00260                     ar_state_register.ar_float_format != AR_CRAY_FLOATING_POINT) ||
00261                    (AR_FLOAT_FORMAT(resulttype) == AR_FLOAT_IEEE &&
00262                     ar_state_register.ar_float_format != AR_IEEE_FLOATING_POINT))
00263                         ar_internal_error(2018, __FILE__, __LINE__);
00264         }
00265 
00266         numargwds = numargs = 0;                /* Set up next intrinsic simulation */
00267         n_external_addresses = 1;               /* Forget all external addresses */
00268         return AR_STAT_OK;
00269 }
00270 
00271 int
00272 ar_ext_address(int64* intaddr, const char* extaddr, int length)
00273 {
00274 #if MAX_EXT_ADDRS >= DATA
00275         if(n_external_addresses == DATA)
00276                 external_address[n_external_addresses++] = NULL;
00277 #if MAX_EXT_ADDRS >= STACK
00278         if(n_external_addresses == STACK)
00279                 external_address[n_external_addresses++] = NULL;
00280 #endif
00281 #endif
00282         *intaddr = n_external_addresses<<24;
00283 
00284         if(n_external_addresses >= MAX_EXT_ADDRS)
00285                 return AR_STAT_UNDEFINED;
00286 
00287         external_address[n_external_addresses] = (char*)extaddr;
00288         external_length[n_external_addresses++] = length;
00289 
00290         return AR_STAT_OK;
00291 }
00292 
00293 int
00294 ar_pass_arg_address(const ar_data* arg, const AR_TYPE* argtype)
00295 {
00296         int iarg;
00297         int nbytes;
00298         int arg_offset;
00299         int arg_value_offset;
00300 
00301         iarg = numargwds;
00302         numargs++;
00303         numargwds++;                            /* Increment number of arguments */
00304 
00305         if(iarg >= MAX_ARGS)    /* Test for unsupported # of args */
00306                 ar_internal_error(2014, __FILE__, __LINE__);
00307 
00308         /* Call-by-address must 1) copy the value of the argument into
00309          * the address space known to the simulator and 2) store the address
00310          * of this copied value into the argument list.  5*MAX_ARGS words
00311          * are assumed to exist beyond the base of the stack for this purpose.
00312          * These words emulate the argument setup in a caller's stack frame.
00313          * The first MAX_ARGS are used to store arguments
00314          * (addresses) that are not passed in registers.  Then 4 words are
00315          * available to store the value of each argument.
00316          */
00317 
00318         /*
00319          * Handle special case of a NULL pointer (no value).  If not NULL,
00320          * Compute address of argument value (to be copied in switch below).
00321          */
00322 
00323         if(arg == NULL)
00324                 S[0] = 0;
00325         else {
00326                 arg_value_offset = (STACK_SIZE+1+MAX_ARGS+iarg*4);
00327                 S[0] = (STACK<<24) | arg_value_offset;
00328         }
00329 
00330         /*
00331          * Store argument address in the stack extension of the argument list.
00332          */
00333 
00334         arg_offset = (STACK<<24) | (STACK_SIZE+1+iarg);
00335         store_pvp_word(arg_offset, S[0]);
00336 
00337         if(arg == NULL)                 /* If no value, simply return */
00338                 return AR_STAT_OK;
00339 
00340         /* Copy the value of the argument to stack slot reserved for it */
00341 
00342         switch (UNROUNDED_TYPE(*argtype)) {
00343 
00344         case CRAY_FLOAT_64:
00345         case IEEE_FLOAT_64:
00346                 nbytes = 8;
00347                 break;
00348 
00349         case CRAY_FLOAT_128:
00350         case CRAY_COMPLEX_64:
00351         case IEEE_FLOAT_128:
00352         case IEEE_COMPLEX_64:
00353                 nbytes = 16;
00354                 break;
00355 
00356         case CRAY_COMPLEX_128:
00357         case IEEE_COMPLEX_128:
00358                 nbytes = 32;
00359                 break;
00360 
00361         default:
00362                 switch (*argtype) {
00363 
00364                 case AR_Int_46_S:
00365                 case AR_Int_64_S:
00366                 case AR_Logical:
00367                         nbytes = 8;
00368                         break;
00369 
00370                 default:
00371                         return AR_STAT_INVALID_TYPE;
00372                 }
00373         }
00374 
00375         memcpy((char*)&stack[arg_value_offset], (char*)(arg), nbytes);
00376         return AR_STAT_OK;
00377 }
00378 
00379 int
00380 ar_pass_ext_address(int64 *extdesc, const char *addr, int nwords)
00381 {
00382         int iarg;
00383         int arg_offset;
00384         int arg_value_offset;
00385 
00386         int status;
00387 
00388         iarg = numargwds;
00389         numargs++;
00390         numargwds++;                    /* Increment number of arguments */
00391 
00392         if(iarg >= MAX_ARGS)    /* Test for unsupported # of args */
00393                 ar_internal_error(2014, __FILE__, __LINE__);
00394 
00395         /* Passing an external address must 1) obtain an external address
00396          * descriptor for the address (from ar_ext_address) and 2) store this
00397          * descriptor into the argument list.
00398          */
00399 
00400         /*
00401          * Handle special case of a NULL pointer (no value).  If not NULL,
00402          * Compute address of argument value (to be copied in switch below).
00403          */
00404 
00405         if(addr == NULL)
00406                 S[0] = 0;
00407         else {
00408                 status = ar_ext_address(&S[0], addr, nwords);
00409                 if(IS_ERROR_STATUS(status))
00410                         return status;
00411         }
00412 
00413         if(extdesc != NULL)
00414                 *extdesc = S[0];
00415 
00416         /*
00417          * Store argument address in the stack extension of the argument list.
00418          */
00419 
00420         arg_offset = (STACK<<24) | (STACK_SIZE+1+iarg);
00421         store_pvp_word(arg_offset, S[0]);
00422 
00423         return AR_STAT_OK;
00424 }
00425 
00426 int
00427 ar_pass_fcd_address(const char* str, long lenstr)
00428 {
00429         int iarg;
00430         int arg_offset;
00431         int arg_value_offset;
00432 
00433         int status;
00434 
00435         long    nbits;
00436 
00437         iarg = numargwds;
00438         numargs++;
00439         numargwds++;                    /* Increment number of arguments */
00440 
00441         if(iarg >= MAX_ARGS)    /* Test for unsupported # of args */
00442                 ar_internal_error(2014, __FILE__, __LINE__);
00443 
00444         if(str == NULL)
00445                 return AR_STAT_UNDEFINED;
00446 
00447         /* Store external address descriptor in fcd */
00448         nbits = lenstr<<3;
00449         status = ar_ext_address(&S[0], str, (lenstr+7)>>3);
00450         if(IS_ERROR_STATUS(status))
00451                 return status;
00452 
00453         /*
00454          * Store fcd in the stack extension of the argument list.
00455          */
00456 
00457         arg_offset = (STACK<<24) | (STACK_SIZE+1+iarg);
00458         if(ar_mach_type == T90) {
00459                 /* Store C pointer and bit length in fcd */
00460                 store_pvp_word(arg_offset, S[0]);
00461                 S[0] = nbits;
00462                 numargwds++;
00463                 store_pvp_word(arg_offset+1, S[0]);
00464         }
00465         else {
00466                 /* Store bit offset and item length in fcd */
00467                 S[0] |= (int64)nbits<<32;
00468                 store_pvp_word(arg_offset, S[0]);
00469         }
00470 
00471         return AR_STAT_OK;
00472 }
00473 
00474 int
00475 ar_pass_arg_value(const ar_data* arg, const AR_TYPE* argtype)
00476 {
00477         int iarg;
00478         int nbytes;
00479         int arg_offset;
00480         int status;
00481 
00482         iarg = numargwds;
00483         numargs++;
00484         numargwds++;                    /* Increment number of arguments */
00485 
00486         if(iarg >= MAX_ARGS)    /* Test for unsupported # of args */
00487                 ar_internal_error(2014, __FILE__, __LINE__);
00488 
00489         /* Call-by-value must copy the value of the argument into an
00490          * argument register.
00491          */
00492 
00493         if(arg == NULL)                 /* Test for NULL pointer (no value) */
00494                 return AR_STAT_UNDEFINED;
00495 
00496         switch (UNROUNDED_TYPE(*argtype)) {
00497 
00498         case CRAY_FLOAT_64:
00499         case IEEE_FLOAT_64:
00500                 nbytes =  8;
00501                 break;
00502 
00503         case CRAY_FLOAT_128:
00504         case CRAY_COMPLEX_64:
00505         case IEEE_FLOAT_128:
00506         case IEEE_COMPLEX_64:
00507                 numargwds++;
00508                 nbytes =  16;
00509                 break;
00510 
00511         case CRAY_COMPLEX_128:
00512         case IEEE_COMPLEX_128:
00513                 numargwds += 3;
00514                 nbytes =  32;
00515                 break;
00516 
00517         default:
00518                 switch (*argtype) {
00519 
00520                 case AR_Int_46_S:
00521                 case AR_Int_64_S:
00522                 case AR_Logical:
00523                         nbytes =  8;
00524                         break;
00525 
00526                 default:
00527                         return AR_STAT_INVALID_TYPE;
00528                 }
00529         }
00530 
00531         memcpy(&S[1+iarg], (char*)arg, nbytes);
00532         return AR_STAT_OK;
00533 }
00534 
00535 
00536 int
00537 ar_put_real_address(AR_INT_64* extdesc)
00538 {
00539         int segment = extdesc->part3>>8;
00540 
00541         if(segment >= n_external_addresses)
00542                 return AR_STAT_UNDEFINED;
00543 
00544         extdesc->part3 = ((long)external_address[segment]) >> 16;
00545         extdesc->part4 = ((long)external_address[segment]) & 0xffff;
00546 
00547         return AR_STAT_OK;
00548 }
00549 
00550 
00551 int
00552 ar_get_function_value(ar_data *result, AR_TYPE *resulttype)
00553 {
00554         int status;
00555 
00556         /*
00557          * Return function value in result if register conventions known
00558          * for the result type.  Otherwise, the function value is assumed
00559          * to be returned through memory and the caller must retrieve it.
00560          * Use AR_convert to set ZERO and NEGATIVE status flags.  Note
00561          * that error flags such as AR_STAT_OVERFLOW are cleared (these
00562          * would have been returned by the intrinsic function simulation
00563          * performed by ar_sim if run-time evaluation would have produced
00564          * them).  So effectively, this routine only returns the bit
00565          * pattern of the result plus zero or negative status.
00566          */
00567 
00568         switch (AR_CLASS(*resulttype)) {
00569 
00570         case AR_CLASS_INT:
00571 
00572                 status = ar_convert_to_integral(result, resulttype,
00573                                   (ar_data*)&S[1], resulttype);
00574                 break;
00575 
00576         case AR_CLASS_FLOAT:
00577 
00578                 switch(UNROUNDED_TYPE(*resulttype)) {
00579 
00580                 case CRAY_FLOAT_64:
00581                         status = ar_convert_to_float(result, resulttype,
00582                                           (ar_data*)&S[1], &cray_float_64);
00583                         break;
00584 
00585                 case CRAY_FLOAT_128:
00586                         status = ar_convert_to_float(result, resulttype,
00587                                           (ar_data*)&S[1], &cray_float_128);
00588                         break;
00589 
00590                 case CRAY_COMPLEX_64:
00591                         status = ar_convert_to_complex(result, resulttype,
00592                                           (ar_data*)&S[1], &cray_complex_64);
00593                         break;
00594 
00595                 case CRAY_COMPLEX_128:
00596                         status = ar_convert_to_complex(result, resulttype,
00597                                           (ar_data*)&S[1], &cray_complex_128);
00598                         break;
00599 
00600                 case IEEE_FLOAT_64:
00601                         status = ar_convert_to_float(result, resulttype,
00602                                           (ar_data*)&S[1], &ieee_float_64);
00603                         break;
00604 
00605                 case IEEE_FLOAT_128:
00606                         status = ar_convert_to_float(result, resulttype,
00607                                           (ar_data*)&S[1], &ieee_float_128);
00608                         break;
00609 
00610                 case IEEE_COMPLEX_64:
00611                         status = ar_convert_to_complex(result, resulttype,
00612                                           (ar_data*)&S[1], &ieee_complex_64);
00613                         break;
00614 
00615                 case IEEE_COMPLEX_128:
00616                         status = ar_convert_to_complex(result, resulttype,
00617                                           (ar_data*)&S[1], &ieee_complex_128);
00618                         break;
00619 
00620                 default:
00621                         return AR_STAT_INVALID_TYPE;
00622                 }
00623                 break;
00624 
00625         default:
00626                 return AR_STAT_INVALID_TYPE;
00627         }
00628         return status &~ AR_ERROR_STATUS;
00629 }
00630 
00631 static int
00632 call_host_external(char* func)
00633 {
00634         char*   ptr1, ptr2;
00635 
00636         int status;
00637 
00638         long    length;
00639 
00640         if(strncmp(func, "malloc", 6) == 0) {
00641                 length = S[1];
00642                 ptr1 = malloc(length);
00643                 status = ar_ext_address(&S[1], (const char*)ptr1, (length+7)>>3);
00644                 return status;
00645         }
00646 
00647         return AR_STAT_UNDEFINED;
00648 }
00649 
00650 #define NOINTRIN        1       /* Unknown/unsupported intrinsic name */
00651 #define ARITHERR        2       /* Arithmetic error detected by intrinsic */
00652 #define EXTERROR        3       /* Unsupported external called by intrinsic */
00653 #define SETERRNO        4       /* Set errno = ERANGE */
00654 #define IFACEERR        5       /* Unsupported simulation interface */
00655 #define HOSTEXT         6       /* Call host system external */
00656 #define UNIMPL_INST 7   /* Unimplemented instruction encountered */
00657 #define UNIMPL_PRFX 8   /* Unimplemented prefixed instruction encountered */
00658 
00659 
00660 #if _CRAY
00661 #define getp1(pc) ( (*(((long*)code)+((pc)>>2))>>(48-(((pc)&3)<<4)) & 0xffff) )
00662 #else
00663 #define getp1(pc) ( (((int) code[(pc)*2])<<8) | code[(pc)*2+1] )
00664 #endif
00665 
00666 #define prefix_check(p)    if (p) { status = UNIMPL_PRFX; break; } else
00667         
00668 static int
00669 ar_check_status(int status, AR_IEEE_64* rr)
00670 {
00671         if(!IS_ERROR_STATUS(status))
00672                 return AR_STAT_OK;
00673 
00674         if((status & AR_STAT_OVERFLOW) && (SR0 & (INTERRUPT_OVF|INTERRUPT_DIV)))
00675                 return status;
00676 
00677         if((status & AR_STAT_UNDEFINED) && (SR0 & INTERRUPT_INV))
00678                 if(rr->expo > AR_IEEE64_MAX_EXPO &&
00679                    (rr->coeff0 | rr->coeff1 | rr->coeff2 | rr->coeff3))
00680                         return status;
00681 
00682         return AR_STAT_OK;
00683 }
00684 
00685 int
00686 ar_sim(char* intrinsic)
00687 {
00688         char*   name;
00689         char*   str;
00690 
00691         int i,j,n;
00692         int status;
00693 
00694         int p1;
00695         int op;
00696         int I,J,K;
00697         int JK;
00698         int prefix;
00699 
00700         unsigned long   pc, inst_pc;
00701         AR_HOST_UINT64  wa;
00702         AR_HOST_UINT64  rtc, rtcpc;
00703 
00704         int64 zero;
00705         int64 one;
00706         int64 ones;
00707         int64 sb;
00708         int64 reg64;
00709 
00710         int64   *rr, *oj, *ok;
00711 
00712         int save_trunc_bits;
00713 
00714         AR_COMPARE_TYPE cmpres;
00715 
00716         /* Set up initial Cray stack and register values */
00717 
00718         /*
00719          * The following test verifies that at least one argument
00720          * has been passed via ar_pass_arg_{value|address}.  This in turn
00721          * guarantees that the arith data file has been opened and read into
00722          * memory so that the simulation is ready to begin.
00723          */
00724 
00725         if(numargwds == 0)
00726                 ar_internal_error(2014, __FILE__, __LINE__);
00727 
00728         S[0] = (numargs<<20) | numargwds;
00729         A[6] = (STACK<<24)|STACK_SIZE;          /* Argument list pointer */
00730         store_pvp_word((long)A[6], S[0]);
00731 
00732         VL = 0;
00733         B[000] = 0;             /* Force return address = 0 */
00734         B[066] = (STACK<<24) | 0;       /* Define stack pointers */
00735         B[067] = B[066]+STACK_SIZE;
00736 
00737         /*
00738          * At this point all necessary registers (except pc) contain values
00739          * that correspond with being at the entry point of the called function.
00740          */
00741 
00742         /*
00743          * Pass my simulation interface identifier.  The logic within the
00744          * pvp simulation file (arith data file) can then validate and/or
00745          * translate to its interface.  This allows this routine and a
00746          * newer pvp simulation file to still function correctly.  In
00747          * practice, this permits older (archived?) products to still work
00748          * with a newer default arith data file.
00749          */
00750 
00751         B[065] = ar_sim_version;        /* Specify sim interface id */
00752 
00753         /*
00754          * Store LJ'd, zero-filled, uppercase intrinsic name into S[7]
00755          * as part of the simulation interface with the pvp simulation file
00756          * (arith data file).  The simulation is assumed to begin (at pc=0)
00757          * with a lookup of this name followed by an unconditional branch to
00758          * the associated entry point when found.  The simulation continues
00759          * until either an error condition occurs or the pc becomes 0 again
00760          * corresponding to the 0 forced into the return address register
00761          * B[000]) above.
00762          */
00763 
00764         name = (char*)&S[7];
00765         for(i=0; i<8 && isalnum(intrinsic[i]); i++)
00766                 name[i] = toupper(intrinsic[i]);
00767         while(i < 8)
00768                 name[i++] = 0;
00769 
00770         /* User-specified truncation is not used when emulating library functions */
00771 
00772         save_trunc_bits = ar_state_register.ar_truncate_bits;   /* save trunc bits */
00773         ar_state_register.ar_truncate_bits = 0;
00774         zero = 0;
00775         one  = 1;
00776         ones = ~zero;
00777         sb   = one<<63;
00778 
00779         /*
00780          * Simulate Cray intrinsic function.  Simulation normally ends with
00781          * a J B00 (to word 0) and register S1,... containing the desired
00782          * result.  An ERREXIT (opcode 000) also terminates simulation.  In
00783          * this case if S0 = (NOINTRIN, ARITHERR, EXTERROR, IFACEERR, SETERRNO),
00784          * actions are taken to handle the error condition.
00785          */
00786 
00787         pc = 0;
00788         rtcpc = 0;
00789         prefix = 0;
00790         status = AR_STAT_OK;
00791         SR0 = (INTERRUPT_INV|INTERRUPT_DIV|INTERRUPT_OVF) |
00792                   (ar_state_register.ar_rounding_mode<<1);
00793         while(status == AR_STAT_OK) {
00794 
00795           /* Decode next instruction */
00796           DISASM2("0p%6.6o%c\t", pc>>2, 'a'+(pc&3));
00797           p1 = getp1(pc); pc++;
00798           op = p1>>9;
00799           I  = (p1>>6)&7;
00800           J  = (p1>>3)&7;
00801           K  = p1&7;
00802 
00803           switch(op) {
00804           case 000:
00805                 prefix_check(prefix);
00806                 status = S[0];
00807                 DISASM1("ERR\t\t\t0x%4.4x\n", status);
00808                 switch (status) {
00809                 case IFACEERR:          /* Unsupported simulation interface */
00810                         ar_internal_error(2014, __FILE__, __LINE__);
00811                         status = AR_STAT_UNDEFINED;
00812                         break;
00813                 case NOINTRIN:          /* Unsupported intrinsic name */
00814                         PRINTMSG(0, 2015, Internal, 0, __FILE__, __LINE__, intrinsic, "");
00815                         status = AR_STAT_UNDEFINED;
00816                         break;
00817                 case EXTERROR:          /* Unsupported EXT called by intrinsic */
00818                         if(status == EXTERROR)
00819                           ar_internal_error(2012, __FILE__, __LINE__);
00820                 case ARITHERR:          /* Error detected by libm routine */
00821                         status = AR_STAT_UNDEFINED;
00822                         break;
00823                 case SETERRNO:          /* Set errno = ERANGE */
00824                         errno = ERANGE;
00825                         status = AR_STAT_OVERFLOW;
00826                         pc = 0;
00827                         break;
00828                 case HOSTEXT:
00829                         status = call_host_external((char*)&S[7]);
00830                         pc = B[00];
00831                         break;
00832                 default:
00833                         ar_internal_error(2013, __FILE__, __LINE__);
00834                         status = AR_STAT_UNDEFINED;
00835                 }
00836                 break;
00837 
00838           case 001:
00839                 prefix_check(prefix);
00840                 if(!(I|J|K))
00841                         DISASM0("PASS\n");
00842                 else
00843                         status = UNIMPL_INST;
00844                 break;
00845 
00846           case 002:
00847                 prefix_check(prefix);
00848                 if(I == 0) {                    /* VL Ak */
00849                         if(K == 0)
00850                                 VL = 1;
00851                         else if((A[K]&(VSZ-1)) == 0)
00852                                 VL = VSZ;
00853                         else
00854                                 VL = A[K]&(VSZ-1);
00855                         DISASM2("VL\tA%1o\t\t%d\n", K, VL);
00856                 }
00857                 else if(I <= 2 && K > 0 &&
00858                                 ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
00859                         switch(K) {
00860                         case 1:
00861                                 if(I == 1)
00862                                         SR0 |= INTERRUPT_INV;
00863                                 else
00864                                         SR0 &=~INTERRUPT_INV;
00865                                 break;
00866                         case 2:
00867                                 if(I == 1)
00868                                         SR0 |= INTERRUPT_DIV;
00869                                 else
00870                                         SR0 &=~INTERRUPT_DIV;
00871                                 break;
00872                         case 3:
00873                                 if(I == 1)
00874                                         SR0 |= INTERRUPT_OVF;
00875                                 else
00876                                         SR0 &=~INTERRUPT_OVF;
00877                                 break;
00878                         case 4:
00879                                 if(I == 1)
00880                                         SR0 |= INTERRUPT_UNF;
00881                                 else
00882                                         SR0 &=~INTERRUPT_UNF;
00883                                 break;
00884                         case 5:
00885                                 if(I == 1)
00886                                         SR0 |= INTERRUPT_INX;
00887                                 else
00888                                         SR0 &=~INTERRUPT_INX;
00889                                 break;
00890                         case 6:
00891                                 if(I == 1)
00892                                         SR0 |= INTERRUPT_INP;
00893                                 else
00894                                         SR0 &=~INTERRUPT_INP;
00895                                 break;
00896                         }
00897                         DISASM2("%cFI\t%3.3s\n", 'F'-I, "INVDIVOVFUNFINXINP"+(K-1)*3);
00898                 }
00899                 else                            /* Ignore all others */
00900                         DISASM1("%6.6o\n", p1);
00901                 break;
00902 
00903           case 003:
00904                 prefix_check(prefix);
00905                 if(I == 0) {
00906                         if(K < 4) {             /* VM A/Sj */
00907                                 if(J == 0)
00908                                         VM = 0;
00909                                 else {
00910                                         switch(K) {
00911                                         case 0:
00912                                                 VM = S[J];
00913                                                 break;
00914                                         case 1:
00915                                                 VM1 = S[J];
00916                                                 break;
00917                                         case 2:
00918                                                 VM = A[J];
00919                                                 break;
00920                                         case 3:
00921                                                 VM1 = A[J];
00922                                                 break;
00923                                         }
00924                                 }
00925                                 DISASM4("VM%1o\t%c%1o\t\t0x%16.16llx\n", K&1, (K&2)?'A':'S', J,
00926                                                 ((K&1)?VM1:VM));
00927                         }
00928                         else if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
00929                                 SR0 = (SR0 &~ RMMASK) | ((K<<1) & RMMASK);
00930                                 SR0 ^= ((SR0&04)>>1);           /* Flip rounding mode order */
00931                                 DISASM1("R%1.1sM\n", "NUZD"+(K&3));
00932                         }
00933                 }
00934                 else                            /* Ignore SM insts */
00935                         DISASM1("%6.6o\n", p1);
00936                 break;
00937 
00938           case 004:
00939                 prefix_check(prefix);
00940                 status = UNIMPL_INST;
00941                 break;
00942 
00943           case 005:
00944                 prefix_check(prefix);
00945                 JK = p1&077;
00946                 if(I <= 1) {
00947                         pc = B[JK];
00948                         DISASM3("J\tB%2.2o\t\t0p%6.6o%c\n", JK, pc>>2, 'a'+(pc&3));
00949                         if(pc == 0) {                   /* Check for end of simulation */
00950                                 ar_state_register.ar_truncate_bits = save_trunc_bits;
00951                                 return(status);
00952                         }
00953                 }
00954                 else if((I == 4 && J == 0 && K == 0) ||
00955                                 (I == 5 && (J == 0 || J == 2 || J == 4) && K >= 1 && K <= 7)) {
00956                         prefix = p1;
00957                         DISASM1("%05o\n", prefix);
00958                 }
00959                 else {
00960                         status = UNIMPL_INST;
00961                 }
00962                 break;
00963 
00964           case 006:
00965                 prefix_check(prefix);
00966                 if(JSZP == 3 && I)
00967                         status = UNIMPL_INST;
00968                 else {
00969                         pc = ((p1&0377)<<16) | getp1(pc);
00970                         DISASM2("J\t0p%6.6o%c\n", pc>>2, 'a'+(pc&3));
00971                 }
00972                 break;
00973 
00974           case 007:
00975                 prefix_check(prefix);
00976                 B[00] = pc+JSZP-1;
00977                 pc = ((p1&0377)<<16) | getp1(pc);
00978                 DISASM2("R\t0p%6.6o%c\n", pc>>2, 'a'+(pc&3));
00979                 break;
00980 
00981           case 010:
00982                 prefix_check(prefix);
00983                 inst_pc = ((p1&0377)<<16) | getp1(pc);
00984                 if((A[0]&AMASK) == 0)
00985                         pc = inst_pc;
00986                 else
00987                         pc += JSZP-1;
00988                 DISASM2("JAZ\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
00989                 break;
00990 
00991           case 011:
00992                 prefix_check(prefix);
00993                 inst_pc = ((p1&0377)<<16) | getp1(pc);
00994                 if((A[0]&AMASK) != 0)
00995                         pc = inst_pc;
00996                 else
00997                         pc += JSZP-1;
00998                 DISASM2("JAN\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
00999                 break;
01000 
01001           case 012:
01002                 prefix_check(prefix);
01003                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01004                 if((A[0]&ASB) == 0)
01005                         pc = inst_pc;
01006                 else
01007                         pc += JSZP-1;
01008                 DISASM2("JAP\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01009                 break;
01010 
01011           case 013:
01012                 prefix_check(prefix);
01013                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01014                 if((A[0]&ASB) != 0)
01015                         pc = inst_pc;
01016                 else
01017                         pc += JSZP-1;
01018                 DISASM2("JAM\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01019                 break;
01020 
01021           case 014:
01022                 prefix_check(prefix);
01023                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01024                 if(S[0])
01025                         pc += JSZP-1;
01026                 else
01027                         pc = inst_pc;
01028                 DISASM2("JSZ\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01029                 break;
01030 
01031           case 015:
01032                 prefix_check(prefix);
01033                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01034                 if(S[0])
01035                         pc = inst_pc;
01036                 else
01037                         pc += JSZP-1;
01038                 DISASM2("JSN\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01039                 break;
01040 
01041           case 016:
01042                 prefix_check(prefix);
01043                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01044                 if((S[0]>>63) == 0)
01045                         pc = inst_pc;
01046                 else
01047                         pc += JSZP-1;
01048                 DISASM2("JSP\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01049                 break;
01050 
01051           case 017:
01052                 prefix_check(prefix);
01053                 inst_pc = ((p1&0377)<<16) | getp1(pc);
01054                 if((S[0]>>63) != 0)
01055                         pc = inst_pc;
01056                 else
01057                         pc += JSZP-1;
01058                 DISASM2("JSM\t0p%6.6o%c\n", inst_pc>>2, 'a'+(inst_pc&3));
01059                 break;
01060 
01061           case 020:
01062                 prefix_check(prefix);
01063                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
01064                 if(J == 0) {
01065                         A[I] = wa;
01066                         DISASM3("A%1o\t0x%8.8x\t0x%*.*llx\n", I, wa, AVAL(I));
01067                 }
01068                 else if(J == 2) {
01069                         A[I] = (A[I]&~(int64)0xffffffff) | wa;
01070                         DISASM4("A%1o\tA%1o:0x%8.8x\t0x%*.*llx\n", I, I, wa, AVAL(I));
01071                 }
01072                 else if(J == 4) {
01073                         A[I] = (A[I]&(int64)0xffffffff) | ((int64)wa<<32);
01074                         DISASM4("A%1o\t0x%8.8x:A%1o\t0x%*.*llx\n", I, wa, I, AVAL(I));
01075                 }
01076                 else
01077                         status = UNIMPL_INST;
01078                 break;
01079 
01080           case 021:
01081                 prefix_check(prefix);
01082                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
01083                 A[I] = ~wa;
01084                 DISASM3("A%1o\t#0x%8.8x\t0x%*.*llx\n", I, wa, AVAL(I));
01085                 break;
01086 
01087           case 022:
01088                 prefix_check(prefix);
01089                 A[I] = p1&077;
01090                 DISASM3("A%1o\t0%2.2o\t\t0x%*.*llx\n", I, (long)A[I], AVAL(I));
01091                 break;
01092 
01093           case 023:
01094                 prefix_check(prefix);
01095                 if(K == 0) {
01096                         A[I] = S[J];
01097                         DISASM3("A%1o\tS%1o\t\t0x%*.*llx\n", I, J, AVAL(I));
01098                 }
01099                 else if(K == 1) {
01100                         if(VL == 0)
01101                                 A[I] = VSZ;
01102                         else
01103                                 A[I] = VL;
01104                         DISASM2("A%1o\tVL\t\t%d\n", I, (long)A[I]);
01105                 }
01106                 else
01107                         status = UNIMPL_INST;
01108                 break;
01109 
01110           case 024:
01111                 prefix_check(prefix);
01112                 JK = p1&077;
01113                 A[I] = B[JK];
01114                 DISASM3("A%1o\tB%2.2o\t\t0x%*.*llx\n", I, JK, AVAL(I));
01115                 break;
01116 
01117           case 025:
01118                 prefix_check(prefix);
01119                 JK = p1&077;
01120                 B[JK] = A[I];
01121                 DISASM3("B%2.2o\tA%1o\t\t0x%*.*llx\n", JK, I, BVAL(JK));
01122                 break;
01123 
01124           case 026:
01125                 prefix_check(prefix);
01126                 if(J) {
01127                         if(K&2)
01128                                 reg64 = A[J];
01129                         else
01130                                 reg64 = S[J];
01131                         if(reg64) {
01132                                 for(i=0,n=0; i<64; i++) {
01133                                         if(reg64&1)
01134                                                 n++;
01135                                         reg64 >>= 1;
01136                                 }
01137                                 if(K & 1)
01138                                         n &= 1;
01139                         }
01140                         else
01141                                 n = 0;
01142                 }
01143                 else
01144                         n = 0;
01145                 A[I] = n;
01146                 if(K & 4)
01147                         status = UNIMPL_INST;
01148                 DISASM5("A%1o\t%c%c%1o\t\t%d\n", I, (K&1)?'Q':'P', (K&2)?'A':'S', J, (long)A[I]);
01149                 break;
01150 
01151           case 027:
01152                 prefix_check(prefix);
01153                 if(J) {
01154                         if(K&1)
01155                                 reg64 = A[J];
01156                         else
01157                                 reg64 = S[J];
01158                         if(reg64) {
01159                                 for(n=0; n<64; n++)
01160                                         if(reg64>>(63-n)) break;
01161                         }
01162                         else
01163                                 n = 64;
01164                         DISASM4("A%1o\tZ%c%1o\t\t%d\n", I, (K&1)?'A':'S', J, (long)A[I]);
01165                 }
01166                 else
01167                         n = 64;
01168                 A[I] = n;
01169                 if(K & 6)
01170                         status = UNIMPL_INST;
01171                 break;
01172 
01173           case 030:
01174                 prefix_check(prefix);
01175                 if(J==0 && K==0)
01176                         A[I] = 1;
01177                 else if(J == 0)
01178                         A[I] = A[K];
01179                 else if(K == 0)
01180                         A[I] = (A[J]+1)&AMASK;
01181                 else
01182                         A[I] = (A[J]+A[K])&AMASK;
01183                 DISASM4("A%1o\tA%1o+A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01184                 break;
01185 
01186           case 031:
01187                 prefix_check(prefix);
01188                 if(J==0 && K==0)
01189                         A[I] = AMASK;
01190                 else if(J == 0)
01191                         A[I] = (-A[K])&AMASK;
01192                 else if(K == 0)
01193                         A[I] = (A[J]-1)&AMASK;
01194                 else
01195                         A[I] = (A[J]-A[K])&AMASK;
01196                 DISASM4("A%1o\tA%1o-A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01197                 break;
01198 
01199           case 032:
01200                 prefix_check(prefix);
01201                 if(J == 0)
01202                         A[I] = 0;
01203                 else if(K == 0)
01204                         A[I] = A[J];
01205                 else
01206                         A[I] = (A[J]*A[K])&AMASK;
01207                 DISASM4("A%1o\tA%1o*A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01208                 break;
01209 
01210           case 033:
01211                 prefix_check(prefix);
01212                 status = UNIMPL_INST;
01213                 break;
01214 
01215           case 034:
01216                 prefix_check(prefix);
01217                 JK = p1&077;
01218                 wa = A[0];
01219                 n = A[I];
01220                 for(i=0; i<n; i++)
01221                         B[(JK+i)&077] = load_pvp_word(wa+i) & AMASK;
01222                 DISASM2("B%2.2o,A%1o\t0,A0", JK, I);
01223                 DISASMB(JK, n, "\t\t");
01224                 break;
01225 
01226           case 035:
01227                 prefix_check(prefix);
01228                 JK = p1&077;
01229                 wa = A[0];
01230                 n = A[I];
01231                 for(i=0; i<n; i++)
01232                         store_pvp_word(wa+i, B[(JK+i)&077]);
01233                 DISASM2("0,A0\tB%2.2o,A%1o\n", JK, I);
01234                 break;
01235 
01236           case 036:
01237                 prefix_check(prefix);
01238                 JK = p1&077;
01239                 wa = A[0];
01240                 n = A[I];
01241                 for(i=0; i<n; i++)
01242                         T[(JK+i)&077] = load_pvp_word(wa+i);
01243                 DISASM2("T%2.2o,A%1o\t0,A0", JK, I);
01244                 DISASMT(JK, n, "\t\t");
01245                 break;
01246 
01247           case 037:
01248                 prefix_check(prefix);
01249                 JK = p1&077;
01250                 wa = A[0];
01251                 n = A[I];
01252                 for(i=0; i<n; i++)
01253                         store_pvp_word(wa+i, T[(JK+i)&077]);
01254                 DISASM2("0,A0\tT%2.2o,A%1o\n", JK, I);
01255                 break;
01256 
01257           case 040:
01258                 prefix_check(prefix);
01259                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
01260                 if(J == 0) {
01261                         S[I] = wa;
01262                         DISASM3("S%1o\t0x%8.8x\t0x%16.16llx\n", I, wa, S[I]);
01263                 }
01264                 else if(J == 2) {
01265                         S[I] = (S[I]&~(int64)0xffffffff) | wa;
01266                         DISASM4("S%1o\tS%1o:0x%8.8x\t0x%16.16llx\n", I, I, wa, S[I]);
01267                 }
01268                 else if(J == 4) {
01269                         S[I] = (S[I]&(int64)0xffffffff) | ((int64)wa<<32);
01270                         DISASM4("S%1o\t0x%8.8x:S%1o\t0x%16.16llx\n", I, wa, I, S[I]);
01271                 }
01272                 else
01273                         status = UNIMPL_INST;
01274                 break;
01275 
01276           case 041:
01277                 prefix_check(prefix);
01278                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
01279                 S[I] = (((int64)0xffffffff)<<32) | ~wa;
01280                 DISASM3("S%1o\t#0x%8.8x\t0x%16.16llx\n", I, wa, S[I]);
01281                 break;
01282 
01283           case 042:
01284                 prefix_check(prefix != 0 && prefix != 05400);
01285                 JK = p1&077;
01286                 if (prefix == 0) {
01287                         S[I] = ones>>JK;
01288                         DISASM3("S%1o\t<0%2.2o\t\t0x%16.16llx\n", I, 64-JK, S[I]);
01289                 }
01290                 else {
01291                         A[I] = ones>>JK;
01292                         DISASM3("A%1o\t<0%2.2o\t\t0x%*.*llx\n", I, 64-JK, AVAL(I));
01293                         prefix = 0;
01294                 }
01295                 break;
01296 
01297           case 043:
01298                 prefix_check(prefix != 0 && prefix != 05400);
01299                 JK = p1&077;
01300                 if (prefix == 0) {
01301                         if(JK)
01302                                 S[I] = ones<<(64-JK);
01303                         else
01304                                 S[I] = 0;
01305                         DISASM3("S%1o\t>0%2.2o\t\t0x%16.16llx\n", I, JK, S[I]);
01306                 }
01307                 else {
01308                         if(JK)
01309                                 A[I] = ones<<(64-JK);
01310                         else
01311                                 A[I] = 0;
01312                         DISASM3("A%1o\t>0%2.2o\t\t0x%*.*llx\n", I, JK, AVAL(I));
01313                         prefix = 0;
01314                 }
01315                 break;
01316 
01317           case 044:
01318                 prefix_check(prefix != 0 && prefix != 05400);
01319                 if (prefix == 0) {
01320                         if(J == 0)
01321                                 S[I] = 0;
01322                         else if(K == 0)
01323                                 S[I] = S[J]&sb;
01324                         else
01325                                 S[I] = S[J]&S[K];
01326                         DISASM4("S%1o\tS%1o&S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01327                 }
01328                 else {
01329                         if(J == 0)
01330                                 A[I] = 0;
01331                         else if(K == 0)
01332                                 A[I] = A[J]&one;
01333                         else
01334                                 A[I] = A[J]&A[K];
01335                         DISASM4("A%1o\tA%1o&A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01336                         prefix = 0;
01337                 }
01338                 break;
01339 
01340           case 045:
01341                 prefix_check(prefix != 0 && prefix != 05400);
01342                 if (prefix == 0) {
01343                         if(J == 0)
01344                                 S[I] = 0;
01345                         else if(K == 0)
01346                                 S[I] = S[J]&~sb;
01347                         else
01348                                 S[I] = S[J]&~S[K];
01349                         DISASM4("S%1o\tS%1o&#S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01350                 }
01351                 else {
01352                         if(J == 0)
01353                                 A[I] = 0;
01354                         else if(K == 0)
01355                                 A[I] = A[J]&~one;
01356                         else
01357                                 A[I] = A[J]&~A[K];
01358                         DISASM4("A%1o\tA%1o&#A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01359                         prefix = 0;
01360                 }
01361                 break;
01362 
01363           case 046:
01364                 prefix_check(prefix != 0 && prefix != 05400);
01365                 if (prefix == 0) {
01366                         if(J == 0)
01367                                 if(K == 0)
01368                                         S[I] = sb;
01369                                 else
01370                                         S[I] = S[K];
01371                         else if(K == 0)
01372                                 S[I] = S[J]^sb;
01373                         else
01374                                 S[I] = S[J]^S[K];
01375                         DISASM4("S%1o\tS%1o\\S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01376                 }
01377                 else {
01378                         if(J == 0)
01379                                 if(K == 0)
01380                                         A[I] = one;
01381                                 else
01382                                         A[I] = A[K];
01383                         else if(K == 0)
01384                                 A[I] = A[J]^one;
01385                         else
01386                                 A[I] = A[J]^A[K];
01387                         DISASM4("A%1o\tA%1o\\A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01388                         prefix = 0;
01389                 }
01390                 break;
01391 
01392           case 047:
01393                 prefix_check(prefix != 0 && prefix != 05400);
01394                 if (prefix == 0) {
01395                         if(J == 0)
01396                                 if(K == 0)
01397                                         S[I] = ~sb;
01398                                 else
01399                                         S[I] = ~S[K];
01400                         else if(K == 0)
01401                                 S[I] = ~S[J]^sb;
01402                         else
01403                                 S[I] = ~S[J]^S[K];
01404                         DISASM4("S%1o\t#S%1o\\S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01405                 }
01406                 else {
01407                         if(J == 0)
01408                                 if(K == 0)
01409                                         A[I] = ~one;
01410                                 else
01411                                         A[I] = ~A[K];
01412                         else if(K == 0)
01413                                 A[I] = ~A[J]^one;
01414                         else
01415                                 A[I] = ~A[J]^A[K];
01416                         DISASM4("A%1o\t#A%1o\\A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01417                         prefix = 0;
01418                 }
01419                 break;
01420 
01421           case 050:
01422                 prefix_check(prefix != 0 && prefix != 05400);
01423                 if (prefix == 0) {
01424                         if(J == 0)
01425                                 if(K == 0)
01426                                         S[I] = S[I]&~sb;
01427                                 else
01428                                         S[I] = S[I]&~S[K];
01429                         else if(K == 0)
01430                                 S[I] = (S[J]&sb) | (S[I]&~sb);
01431                         else
01432                                 S[I] = (S[J]&S[K]) | (S[I]&~S[K]);
01433                         DISASM4("S%1o\t|S%1o&S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01434                 }
01435                 else {
01436                         if(J == 0)
01437                                 if(K == 0)
01438                                         A[I] = A[I]&~one;
01439                                 else
01440                                         A[I] = A[I]&~A[K];
01441                         else if(K == 0)
01442                                 A[I] = (A[J]&one) | (A[I]&~one);
01443                         else
01444                                 A[I] = (A[J]&A[K]) | (A[I]&~A[K]);
01445                         DISASM4("A%1o\t|A%1o&A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01446                         prefix = 0;
01447                 }
01448                 break;
01449 
01450           case 051:
01451                 prefix_check(prefix != 0 && prefix != 05400);
01452                 if (prefix == 0) {
01453                         if(J == 0)
01454                                 if(K == 0)
01455                                         S[I] = sb;
01456                                 else
01457                                         S[I] = S[K];
01458                         else if(K == 0)
01459                                 S[I] = S[J]|sb;
01460                         else
01461                                 S[I] = S[J]|S[K];
01462                         DISASM4("S%1o\tS%1o|S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01463                 }
01464                 else {
01465                         if(J == 0)
01466                                 if(K == 0)
01467                                         A[I] = one;
01468                                 else
01469                                         A[I] = A[K];
01470                         else if(K == 0)
01471                                 A[I] = A[J]|one;
01472                         else
01473                                 A[I] = A[J]|A[K];
01474                         DISASM4("A%1o\tA%1o|A%1o\t\t0x%*.*llx\n", I, J, K, AVAL(I));
01475                         prefix = 0;
01476                 }
01477                 break;
01478 
01479           case 052:
01480                 prefix_check(prefix != 0 && prefix != 05400);
01481                 if (prefix == 0) {
01482                         S[0] = S[I] << (p1&077);
01483                         DISASM3("S0\tS%1o<0%2.2o\t\t0x%16.16llx\n", I, p1&077, S[0]);
01484                 }
01485                 else {
01486                         A[0] = A[I] << (p1&077);
01487                         DISASM3("S0\tA%1o<0%2.2o\t\t0x%*.*llx\n", I, p1&077, AVAL(0));
01488                         prefix = 0;
01489                 }
01490                 break;
01491 
01492           case 053:
01493                 prefix_check(prefix != 0 && prefix != 05400);
01494                 if (prefix == 0) {
01495                         if(p1&077)
01496                                 S[0] = S[I] >> (64-(p1&077));
01497                         else
01498                                 S[0] = 0;
01499                         DISASM3("S0\tS%1o>0%2.2o\t\t0x%16.16llx\n", I, 64-(p1&077), S[0]);
01500                 }
01501                 else {
01502                         if(p1&077)
01503                                 A[0] = A[I] >> (64-(p1&077));
01504                         else
01505                                 A[0] = 0;
01506                         DISASM3("S0\tA%1o>0%2.2o\t\t0x%*.*llx\n", I, 64-(p1&077), AVAL(0));
01507                         prefix = 0;
01508                 }
01509                 break;
01510 
01511           case 054:
01512                 prefix_check(prefix != 0 && prefix != 05400);
01513                 if (prefix == 0) {
01514                         S[I] <<= (p1&077);
01515                         DISASM4("S%1o\tS%1o<0%2.2o\t\t0x%16.16llx\n", I, I, p1&077, S[I]);
01516                 }
01517                 else {
01518                         A[I] <<= (p1&077);
01519                         DISASM4("A%1o\tA%1o<0%2.2o\t\t0x%*.*llx\n", I, I, p1&077, AVAL(I));
01520                         prefix = 0;
01521                 }
01522                 break;
01523 
01524           case 055:
01525                 prefix_check(prefix != 0 && prefix != 05400);
01526                 if (prefix == 0) {
01527                         if(p1&077)
01528                                 S[I] >>= (64-(p1&077));
01529                         else
01530                                 S[I] = 0;
01531                         DISASM4("S%1o\tS%1o>0%2.2o\t\t0x%16.16llx\n", I, I, 64-(p1&077),
01532                                         S[I]);
01533                 }
01534                 else {
01535                         if(p1&077)
01536                                 A[I] >>= (64-(p1&077));
01537                         else
01538                                 A[I] = 0;
01539                         DISASM4("A%1o\tA%1o>0%2.2o\t\t0x%*.*llx\n", I, I, 64-(p1&077),
01540                                         AVAL(I));
01541                         prefix = 0;
01542                 }
01543                 break;
01544 
01545           case 056:
01546                 prefix_check(prefix != 0 && prefix != 05400);
01547                 if (prefix == 0) {
01548                         if(J == 0)
01549                                 reg64 = 0;
01550                         else
01551                                 reg64 = S[J];
01552                         if(K == 0)
01553                                 n = 1;
01554                         else {
01555                                 n = A[K];
01556                                 if(n >= 64) {
01557                                         if(n >= 128) {
01558                                                 S[I] = 0;
01559                                                 n = 0;
01560                                         }
01561                                         else {
01562                                                 S[I] = reg64;
01563                                                 reg64 = 0;
01564                                                 n -= 64;
01565                                         }
01566                                 }
01567                         }
01568                         if(n)
01569                                 S[I] = (S[I]<<n) | (reg64>>(64-n));
01570                         DISASM5("S%1o\tS%1o,S%1o<A%1o\t0x%16.16llx\n", I, I, J, K, S[I]);
01571                 }
01572                 else {
01573                         if(J == 0)
01574                                 reg64 = 0;
01575                         else
01576                                 reg64 = A[J];
01577                         if(K == 0)
01578                                 n = 1;
01579                         else {
01580                                 n = A[K];
01581                                 if(n >= 64) {
01582                                         if(n >= 128) {
01583                                                 A[I] = 0;
01584                                                 n = 0;
01585                                         }
01586                                         else {
01587                                                 A[I] = reg64;
01588                                                 reg64 = 0;
01589                                                 n -= 64;
01590                                         }
01591                                 }
01592                         }
01593                         if(n)
01594                                 A[I] = (A[I]<<n) | (reg64>>(64-n));
01595                         DISASM5("A%1o\tA%1o,A%1o<A%1o\t0x%*.*llx\n", I, I, J, K, AVAL(I));
01596                         prefix = 0;
01597                 }
01598                 break;
01599 
01600           case 057:
01601                 prefix_check(prefix != 0 && prefix != 05400);
01602                 if (prefix == 0) {
01603                         if(J == 0)
01604                                 reg64 = 0;
01605                         else
01606                                 reg64 = S[J];
01607                         if(K == 0)
01608                                 n = 1;
01609                         else {
01610                                 n = A[K];
01611                                 if(n >= 64) {
01612                                         if(n >= 128) {
01613                                                 S[I] = 0;
01614                                                 n = 0;
01615                                         }
01616                                         else {
01617                                                 S[I] = reg64;
01618                                                 reg64 = 0;
01619                                                 n -= 64;
01620                                         }
01621                                 }
01622                         }
01623                         if(n)
01624                                 S[I] = (reg64<<(64-n)) | (S[I]>>n);
01625                         DISASM5("S%1o\tS%1o,S%1o>A%1o\t0x%16.16llx\n", I, J, I, K, S[I]);
01626                 }
01627                 else {
01628                         if(J == 0)
01629                                 reg64 = 0;
01630                         else
01631                                 reg64 = A[J];
01632                         if(K == 0)
01633                                 n = 1;
01634                         else {
01635                                 n = A[K];
01636                                 if(n >= 64) {
01637                                         if(n >= 128) {
01638                                                 A[I] = 0;
01639                                                 n = 0;
01640                                         }
01641                                         else {
01642                                                 A[I] = reg64;
01643                                                 reg64 = 0;
01644                                                 n -= 64;
01645                                         }
01646                                 }
01647                         }
01648                         if(n)
01649                                 A[I] = (reg64<<(64-n)) | (A[I]>>n);
01650                         DISASM5("A%1o\tA%1o,A%1o>A%1o\t0x%*.*llx\n", I, J, I, K, AVAL(I));
01651                         prefix = 0;
01652                 }
01653                 break;
01654 
01655           case 060:
01656                 prefix_check(prefix);
01657                 if(J == 0)
01658                         if(K == 0)
01659                                 S[I] = sb;
01660                         else
01661                                 S[I] = S[K];
01662                 else if(K == 0)
01663                         S[I] = S[J] + sb;
01664                 else
01665                         S[I] = S[J] + S[K];
01666                 DISASM4("S%1o\tS%1o+S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01667                 break;
01668 
01669           case 061:
01670                 prefix_check(prefix);
01671                 if(J == 0)
01672                         if(K == 0)
01673                                 S[I] = -sb;
01674                         else
01675                                 S[I] = -S[K];
01676                 else if(K == 0)
01677                         S[I] = S[J] - sb;
01678                 else
01679                         S[I] = S[J] - S[K];
01680                 DISASM4("S%1o\tS%1o-S%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01681                 break;
01682 
01683           case 062:
01684                 prefix_check(prefix);
01685                 if(K == 0)
01686                         ok = &sb;
01687                 else
01688                         ok = &S[K];
01689                 if(J == 0)
01690                         oj = &zero;
01691                 else
01692                         oj = &S[J];
01693                 rr = &S[I];
01694                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
01695                         status = ar_cfadd64((AR_CRAY_64*)rr,
01696                                                                 (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
01697                 else {
01698                         status = ar_ifadd64((AR_IEEE_64*)rr,
01699                                                                 (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
01700                                                                 SR0&RMMASK);
01701                         if(IS_ERROR_STATUS(status))
01702                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
01703                 }
01704                 status &= AR_ERROR_STATUS;
01705                 DISASM4("S%1o\tS%1o+FS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01706                 break;
01707 
01708           case 063:
01709                 prefix_check(prefix);
01710                 if(K == 0)
01711                         ok = &sb;
01712                 else
01713                         ok = &S[K];
01714                 if(J == 0)
01715                         oj = &zero;
01716                 else
01717                         oj = &S[J];
01718                 rr = &S[I];
01719                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
01720                         status = ar_cfsub64((AR_CRAY_64*)rr,
01721                                                                 (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
01722                 else {
01723                         status = ar_ifsub64((AR_IEEE_64*)rr,
01724                                                                 (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
01725                                                                 SR0&RMMASK);
01726                         if(IS_ERROR_STATUS(status))
01727                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
01728                 }
01729                 status &= AR_ERROR_STATUS;
01730                 DISASM4("S%1o\tS%1o-FS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01731                 break;
01732 
01733           case 064:
01734                 prefix_check(prefix);
01735                 if(K == 0)
01736                         ok = &sb;
01737                 else
01738                         ok = &S[K];
01739                 if(J == 0)
01740                         oj = &zero;
01741                 else
01742                         oj = &S[J];
01743                 rr = &S[I];
01744                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
01745                         status = ar_cfmul64((AR_CRAY_64*)rr,
01746                                                                 (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
01747                                                                 AR_UNROUNDED);
01748                 else {
01749                         status = ar_ifmul64((AR_IEEE_64*)rr,
01750                                                                 (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
01751                                                                 SR0&RMMASK);
01752                         if(IS_ERROR_STATUS(status))
01753                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
01754                 }
01755                 status &= AR_ERROR_STATUS;
01756                 DISASM4("S%1o\tS%1o*FS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01757                 break;
01758 
01759           case 065:
01760                 prefix_check(prefix);
01761                 if(K == 0)
01762                         ok = &sb;
01763                 else
01764                         ok = &S[K];
01765                 if(J == 0)
01766                         oj = &zero;
01767                 else
01768                         oj = &S[J];
01769                 rr = &S[I];
01770                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
01771                         status = UNIMPL_INST;
01772                 else {
01773                         /*
01774                          * Yes, it really is "Si Sk/FSj".
01775                          */
01776                         status = ar_ifdiv64((AR_IEEE_64*)rr,
01777                                                                 (AR_IEEE_64*)ok, (AR_IEEE_64*)oj,
01778                                                                 SR0&RMMASK);
01779                         status &= AR_ERROR_STATUS;
01780                         if(status)
01781                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
01782                         DISASM4("S%1o\tS%1o/FS%1o\t\t0x%16.16llx\n", I, K, J, S[I]);
01783                 }
01784                 break;
01785 
01786           case 066:
01787                 prefix_check(prefix != 0 && prefix != 05400);
01788                 if(K == 0)
01789                         ok = &sb;
01790                 else
01791                         ok = &S[K];
01792                 if(J == 0)
01793                         oj = &zero;
01794                 else
01795                         oj = &S[J];
01796                 rr = &S[I];
01797                 if (prefix == 0) {
01798                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01799                                 status = ar_cfmul64((AR_CRAY_64*)rr,
01800                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
01801                                                                         AR_ROUNDED);
01802                                 status &= AR_ERROR_STATUS;
01803                                 DISASM4("S%1o\tS%1o*RS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01804                         }
01805                         else {
01806                                 S[I] = *oj * *ok;
01807                                 DISASM4("S%1o\tS%1o*LS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01808                         }
01809                 }
01810                 else {
01811                         status = ar_imul64u(rr, *oj, *ok);
01812                         DISASM4("S%1o\tS%1o*US%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01813                         prefix = 0;
01814                 }
01815                 break;
01816 
01817           case 067:
01818                 prefix_check(prefix);
01819                 if(K == 0)
01820                         ok = &sb;
01821                 else
01822                         ok = &S[K];
01823                 if(J == 0)
01824                         oj = &zero;
01825                 else
01826                         oj = &S[J];
01827                 rr = &S[I];
01828                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01829                         status = ar_cfmul64((AR_CRAY_64*)rr,
01830                                                                 (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
01831                                                                 AR_RECIPROCAL_ITERATION);
01832                         status &= AR_ERROR_STATUS;
01833                         DISASM4("S%1o\tS%1o*IS%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
01834                 }
01835                 else
01836                         status = UNIMPL_INST;
01837                 break;
01838 
01839           case 070:
01840                 prefix_check(prefix);
01841                 if(J == 0)
01842                         oj = &zero;
01843                 else
01844                         oj = &S[J];
01845                 rr = &S[I];
01846                 switch(K) {
01847                 case 0:
01848                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01849                                 status = ar_c1frecip((AR_CRAY_64*)rr, (AR_CRAY_64*)oj);
01850                                 DISASM3("S%1o\t/HS%1o\t\t0x%16.16llx\n", I, J, S[I]);
01851                         }
01852                         else {
01853                                 status = ar_isqrt64((AR_IEEE_64*)rr,
01854                                                                         (AR_IEEE_64*)oj, SR0&RMMASK);
01855                                 if(IS_ERROR_STATUS(status))
01856                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
01857                                 DISASM3("S%1o\tSQRT,S%1o\t\t0x%16.16llx\n", I, J, S[I]);
01858                         }
01859                         break;
01860                 case 1:
01861                         reg64 = 0;
01862                         for(i=0,j=0; i<VL; i++) {
01863                                 if((VM>>(63-i)) & 1)
01864                                         V[I*VSZ+j++] = reg64;
01865                                 if(J)
01866                                         reg64 += S[J];
01867                         }
01868                         DISASM2("V%1o\tCI,S%1o&VM\n", I, J);
01869                         DISASMV(I, "\t\t");
01870                         break;
01871                 case 2:
01872                         if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
01873                                 status = ar_ifix64((AR_INT_64*)rr, (const AR_IEEE_64*)oj,
01874                                                                    64, AR_ROUND_ZERO);
01875                                 if(IS_ERROR_STATUS(status))
01876                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
01877                                 DISASM3("S%1o\tINT,S%1o\t\t0x%16.16llx\n", I, J, S[I]);
01878                                 break;
01879                         }
01880                 case 3:
01881                         if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
01882                                 status = ar_ifix64((AR_INT_64*)rr, (const AR_IEEE_64*)oj,
01883                                                                    64, AR_ROUND_NEAREST);
01884                                 if(IS_ERROR_STATUS(status))
01885                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
01886                                 DISASM3("S%1o\tRINT,S%1o\t\t0x%16.16llx\n", I, J, S[I]);
01887                                 break;
01888                         }
01889                 case 4:
01890                         if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
01891                                 status = ar_iflt64((AR_IEEE_64*)rr, (const AR_INT_64*)oj,
01892                                                                    0, AR_ROUND_ZERO);
01893                                 if(IS_ERROR_STATUS(status))
01894                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
01895                                 DISASM3("S%1o\tFLT,S%1o\t\t0x%16.16llx\n", I, J, S[I]);
01896                                 break;
01897                         }
01898                 case 5:
01899                 case 6:
01900                 case 7:
01901                         status = UNIMPL_INST;
01902                         break;
01903                 }
01904                 status &= AR_ERROR_STATUS;
01905                 break;
01906 
01907           case 071:
01908                 prefix_check(prefix);
01909                 switch(J) {
01910                 case 0:
01911                         S[I] = A[K];
01912                         DISASM3("S%1o\tA%1o\t\t0x%16.16llx\n", I, K, S[I]);
01913                         break;
01914                 case 1:
01915                 case 2:
01916                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01917                                 if(ar_mach_type == T90)
01918                                         S[I] = A[K];
01919                                 else if(A[K] & ASB)
01920                                         S[I] = (AMASK<<32) | A[K];
01921                                 else
01922                                         S[I] = A[K];
01923                                 if(J == 1)
01924                                         DISASM3("S%1o\t+A%1o\t\t0x%16.16llx\n", I, K, S[I]);
01925                                 else {
01926                                         if(S[I]>>63)
01927                                            S[I] = (S[I]^(ones>>1))+1;
01928                                         S[I] &= ~((int64)0x7fff<<48);
01929                                         S[I] |= ((int64)040060<<48);
01930                                         DISASM3("S%1o\t+FA%1o\t\t0x%16.16llx\n", I, K, S[I]);
01931                                 }
01932                                 break;
01933                         }
01934                 case 3:
01935                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01936                                 S[I] = (int64)0400606<<45;
01937                                 DISASM1("S%1o\t0.6\n", I);
01938                                 break;
01939                         }
01940                 case 4:
01941                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01942                                 S[I] = (int64)0400004<<45;
01943                                 DISASM1("S%1o\t0.4\n", I);
01944                                 break;
01945                         }
01946                 case 5:
01947                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01948                                 S[I] = (int64)0400014<<45;
01949                                 DISASM1("S%1o\t1.\n", I);
01950                                 break;
01951                         }
01952                 case 6:
01953                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01954                                 S[I] = (int64)0400024<<45;
01955                                 DISASM1("S%1o\t2.\n", I);
01956                                 break;
01957                         }
01958                 case 7:
01959                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
01960                                 S[I] = (int64)0400034<<45;
01961                                 DISASM1("S%1o\t4.\n", I);
01962                                 break;
01963                         }
01964                 default:
01965                         status = UNIMPL_INST;
01966                 }
01967                 break;
01968 
01969           case 072:
01970                 prefix_check(prefix);
01971                 if(J == 0 && K == 0) {
01972                         if(rtcpc < pc)
01973                                 rtc += (pc-rtcpc);
01974                         else
01975                                 rtc += (rtcpc-pc);
01976                         rtcpc = pc;
01977                         S[I] = rtc;
01978                         DISASM1("S%1o\tRT\n", I);
01979                 }
01980                 else
01981                         status = UNIMPL_INST;
01982                 break;
01983 
01984           case 073:                             /* Si VM */
01985                 prefix_check(prefix != 0 && prefix != 05400);
01986                 if (prefix == 0) {
01987                         if(K == 0 && J <= 3) {
01988                                 switch(J) {
01989                                 case 0:
01990                                         S[I] = VM;
01991                                         break;
01992                                 case 1:
01993                                         S[I] = VM1;
01994                                         break;
01995                                 case 2:
01996                                         A[I] = VM;
01997                                         break;
01998                                 case 3:
01999                                         A[I] = VM1;
02000                                         break;
02001                                 }
02002                                 DISASM4("%c%1o\tVM%1o\t\t0x%16.16llx\n", (K&2)?'A':'S', I, K&1,
02003                                                 (J<2)?S[I]:A[I]);
02004                         }
02005                         else if (J == 0 && K == 1) {
02006                                 S[I] = SR0 ^ ((SR0&04)>>1);             /* Flip rounding mode order */
02007                                 DISASM3("S%1o\tSR%1o\t\t0x%16.16llx\n", I, J, S[I]);
02008                         }
02009                         else if (J == 0 && K == 5) {
02010                                 SR0 = S[I] ;
02011                                 SR0 ^= ((SR0&04)>>1);                   /* Flip rounding mode order */
02012                                 DISASM3("SR%1o\tS%1o\t\t0x%8.8x\n", J, I, SR0);
02013                         }
02014                         else
02015                                 status = UNIMPL_INST;
02016                 }
02017                 else if(J == 0 && K == 5) {
02018                         SR0 = (SR0 &~ RMMASK) | S[I]&RMMASK;
02019                         SR0 ^= ((SR0&04)>>1);                           /* Flip rounding mode order */
02020                         prefix = 0;
02021                         DISASM1("SETRM\tS%1o\n", I);
02022                 }
02023                 else {
02024                         status = UNIMPL_INST;
02025                         prefix = 0;
02026                 }
02027                 break;
02028 
02029           case 074:
02030                 prefix_check(prefix);
02031                 JK = p1&077;
02032                 S[I] = T[JK];
02033                 DISASM3("S%1o\tT%2.2o\t\t0x%16.16llx\n", I, JK, S[I]);
02034                 break;
02035 
02036           case 075:
02037                 prefix_check(prefix);
02038                 JK = p1&077;
02039                 T[JK] = S[I];
02040                 DISASM3("T%2.2o\tS%1o\t\t0x%16.16llx\n", JK, I, T[JK]);
02041                 break;
02042 
02043           case 076:
02044                 prefix_check(prefix);
02045                 if(K == 0)
02046                         i=1;
02047                 else
02048                         i=A[K];
02049                 S[I] = V[J*VSZ+i];
02050                 DISASM4("S%1o\tV%1o,A%1o\t\t0x%16.16llx\n", I, J, K, S[I]);
02051                 break;
02052 
02053           case 077:
02054                 prefix_check(prefix);
02055                 if(K == 0)
02056                         i=1;
02057                 else
02058                         i=A[K];
02059                 if(J == 0)
02060                         V[I*VSZ+i] = 0;
02061                 else
02062                         V[I*VSZ+i] = S[J];
02063                 DISASM4("V%1o,A%1o\tS%1o\t\t0x%16.16llx\n", I, K, J, V[I*VSZ+i]);
02064                 break;
02065 
02066           case 0100:
02067           case 0101:
02068           case 0102:
02069           case 0103:
02070           case 0104:
02071           case 0105:
02072           case 0106:
02073           case 0107:
02074                 prefix_check(prefix);
02075                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
02076                 if(J & 4) {
02077                   /* Triton and TS-IEEE only */
02078                         wa |= (((AR_HOST_UINT64) getp1(pc)) << 32);
02079                         pc++;
02080                 }
02081                 if(op&07)
02082                         A[I] = load_pvp_word(wa+(long)A[op&07]) & AMASK;
02083                 else
02084                         A[I] = load_pvp_word(wa) & AMASK;
02085                 DISASM4("A%1o\t0x%6.6x,A%1o\t0x%*.*llx\n", I, wa, op&7, AVAL(I));
02086                 break;
02087 
02088           case 0110:
02089           case 0111:
02090           case 0112:
02091           case 0113:
02092           case 0114:
02093           case 0115:
02094           case 0116:
02095           case 0117:
02096                 prefix_check(prefix);
02097                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
02098                 if(J & 4) {
02099                   /* Triton and TS-IEEE only */
02100                         wa |= (((AR_HOST_UINT64) getp1(pc)) << 32);
02101                         pc++;
02102                 }
02103                 if(op&07)
02104                         store_pvp_word(wa+(long)A[op&07], A[I]);
02105                 else
02106                         store_pvp_word(wa, A[I]);
02107                 DISASM3("0x%6.6x,A%1o  A%1o\n", wa, op&7, I);
02108                 break;
02109 
02110           case 0120:
02111           case 0121:
02112           case 0122:
02113           case 0123:
02114           case 0124:
02115           case 0125:
02116           case 0126:
02117           case 0127:
02118                 prefix_check(prefix);
02119                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
02120                 if(J & 4) {
02121                   /* Triton and TS-IEEE only */
02122                         wa |= (((AR_HOST_UINT64) getp1(pc)) << 32);
02123                         pc++;
02124                 }
02125                 if(op&07)
02126                         S[I] = load_pvp_word(wa+(long)A[op&07]);
02127                 else
02128                         S[I] = load_pvp_word(wa);
02129                 DISASM4("S%1o\t0x%6.6x,A%1o\t0x%16.16llx\n", I, wa, op&7, S[I]);
02130                 break;
02131 
02132           case 0130:
02133           case 0131:
02134           case 0132:
02135           case 0133:
02136           case 0134:
02137           case 0135:
02138           case 0136:
02139           case 0137:
02140                 prefix_check(prefix);
02141                 wa = (getp1(pc) | (getp1(pc+1)<<16)); pc += 2;
02142                 if(J & 4) {
02143                   /* Triton and TS-IEEE only */
02144                         wa |= (((AR_HOST_UINT64) getp1(pc)) << 32);
02145                         pc++;
02146                 }
02147                 if(op&07)
02148                         store_pvp_word(wa+(long)A[op&07], S[I]);
02149                 else
02150                         store_pvp_word(wa, S[I]);
02151                 DISASM3("0x%6.6x,A%1o  S%1o\n", wa, op&7, I);
02152                 break;
02153 
02154           case 0140:                            /* Vi Sj&Vk */
02155                 prefix_check(prefix);
02156                 if(J == 0)
02157                         oj = &zero;
02158                 else
02159                         oj = &S[J];
02160                 for(i=0; i<VL; i++)
02161                         V[I*VSZ+i] = *oj & V[K*VSZ+i];
02162                 DISASM3("V%1o\tS%1o&V%1o", I, J, K);
02163                 DISASMV(I, "\t\t");
02164                 break;
02165 
02166           case 0141:                            /* Vi Vj&Vk */
02167                 prefix_check(prefix);
02168                 for(i=0; i<VL; i++)
02169                         V[I*VSZ+i] = V[J*VSZ+i] & V[K*VSZ+i];
02170                 DISASM3("V%1o\tV%1o&V%1o", I, J, K);
02171                 DISASMV(I, "\t\t");
02172                 break;
02173 
02174           case 0142:                            /* Vi Sj!Vk */
02175                 prefix_check(prefix);
02176                 if(J == 0)
02177                         oj = &zero;
02178                 else
02179                         oj = &S[J];
02180                 for(i=0; i<VL; i++)
02181                         V[I*VSZ+i] = *oj | V[K*VSZ+i];
02182                 DISASM3("V%1o\tS%1o|V%1o", I, J, K);
02183                 DISASMV(I, "\t\t");
02184                 break;
02185 
02186           case 0143:                            /* Vi Vj!Vk */
02187                 prefix_check(prefix);
02188                 for(i=0; i<VL; i++)
02189                         V[I*VSZ+i] = V[J*VSZ+i] | V[K*VSZ+i];
02190                 DISASM3("V%1o\tV%1o|V%1o", I, J, K);
02191                 DISASMV(I, "\t\t");
02192                 break;
02193 
02194           case 0144:                            /* Vi Sj\Vk */
02195                 prefix_check(prefix);
02196                 if(J == 0)
02197                         oj = &zero;
02198                 else
02199                         oj = &S[J];
02200                 for(i=0; i<VL; i++)
02201                         V[I*VSZ+i] = *oj ^ V[K*VSZ+i];
02202                 DISASM3("V%1o\tS%1o\\V%1o", I, J, K);
02203                 DISASMV(I, "\t\t");
02204                 break;
02205 
02206           case 0145:                            /* Vi Vj\Vk */
02207                 prefix_check(prefix);
02208                 for(i=0; i<VL; i++)
02209                         V[I*VSZ+i] = V[J*VSZ+i] ^ V[K*VSZ+i];
02210                 DISASM3("V%1o\tV%1o^V%1o", I, J, K);
02211                 DISASMV(I, "\t\t");
02212                 break;
02213 
02214           case 0146:                            /* Vi Sj!Vk&VM */
02215                 prefix_check(prefix);
02216                 if(J == 0)
02217                         oj = &zero;
02218                 else
02219                         oj = &S[J];
02220                 for(i=0; i<VL; i++) {
02221                         if(i < 64)
02222                                 n = (VM>>(63-i)) & 1;
02223                         else
02224                                 n = (VM1>>(127-i)) & 1;
02225                         if(n)
02226                                 V[I*VSZ+i] = *oj;
02227                         else
02228                                 V[I*VSZ+i] = V[K*VSZ+i];
02229                 }
02230                 DISASM3("V%1o\tS%1o!V%1o&VM", I, J, K);
02231                 DISASMV(I, "\t");
02232                 break;
02233 
02234           case 0147:                            /* Vi Vj!Vk&VM */
02235                 prefix_check(prefix);
02236                 for(i=0; i<VL; i++) {
02237                         if(i < 64)
02238                                 n = (VM>>(63-i)) & 1;
02239                         else
02240                                 n = (VM1>>(127-i)) & 1;
02241                         if(n)
02242                                 V[I*VSZ+i] = V[J*VSZ+i];
02243                         else
02244                                 V[I*VSZ+i] = V[K*VSZ+i];
02245                 }
02246                 DISASM3("V%1o\tV%1o!V%1o&VM", I, J, K);
02247                 DISASMV(I, "\t");
02248                 break;
02249 
02250           case 0150:                            /* Vi Vj<Ak */
02251                 prefix_check(prefix != 0 && prefix != 05400);
02252                 if (prefix == 0) {
02253                         if(K == 0) {
02254                                 for(i=0; i<VL; i++)
02255                                         V[I*VSZ+i] = V[J*VSZ+i]<<1;
02256                         }
02257                         else if(A[K] &~ (int64)077) {
02258                                 for(i=0; i<VL; i++)
02259                                         V[I*VSZ+i] = 0;
02260                         }
02261                         else {
02262                                 n = A[K];
02263                                 for(i=0; i<VL; i++)
02264                                         V[I*VSZ+i] = V[J*VSZ+i]<<n;
02265                         }
02266                         DISASM3("V%1o\tV%1o<A%1o", I, J, K);
02267                         DISASMV(I, "\t\t");
02268                 }
02269                 else {
02270                         if(K == 0) {
02271                                 for(i=0; i<VL; i++) {
02272                                         if(V[0*VSZ+i] &~ (int64)077)
02273                                                 V[I*VSZ+i] = 0;
02274                                         else
02275                                                 V[I*VSZ+i] = V[J*VSZ+i]<<V[0*VSZ+i];
02276                                 }
02277                                 DISASM2("V%1o\tV%1o<V0", I, J);
02278                                 DISASMV(I, "\t\t");
02279                         }
02280                         else {
02281                                 if(A[K] &~ (int64)077) {
02282                                         for(i=0; i<VL; i++)
02283                                                 V[I*VSZ+i] = 0;
02284                                 }
02285                                 else {
02286                                         n = A[K];
02287                                         for(i=0; i<VL; i++)
02288                                                 V[I*VSZ+i] = V[J*VSZ+i]<<n;
02289                                 }
02290                                 DISASM3("V%1o\tV%1o<A%1o", I, J, K);
02291                                 DISASMV(I, "\t\t");
02292                         }
02293                         prefix = 0;
02294                 }
02295                 break;
02296 
02297           case 0151:                            /* Vi Vj>Ak */
02298                 prefix_check(prefix != 0 && prefix != 05400);
02299                 if (prefix == 0) {
02300                         if(K == 0) {
02301                                 for(i=0; i<VL; i++)
02302                                         V[I*VSZ+i] = V[J*VSZ+i]>>1;
02303                         }
02304                         else if(A[K] &~ (int64)077) {
02305                                 for(i=0; i<VL; i++)
02306                                         V[I*VSZ+i] = 0;
02307                         }
02308                         else {
02309                                 n = A[K];
02310                                 for(i=0; i<VL; i++)
02311                                         V[I*VSZ+i] = V[J*VSZ+i]>>n;
02312                         }
02313                         DISASM3("V%1o\tV%1o>A%1o", I, J, K);
02314                         DISASMV(I, "\t\t");
02315                 }
02316                 else {
02317                         if(K == 0) {
02318                                 for(i=0; i<VL; i++) {
02319                                         if(V[0*VSZ+i] &~ (int64)077)
02320                                                 V[I*VSZ+i] = 0;
02321                                         else
02322                                                 V[I*VSZ+i] = V[J*VSZ+i]>>V[0*VSZ+i];
02323                                 }
02324                                 DISASM2("V%1o\tV%1o>V0", I, J);
02325                                 DISASMV(I, "\t\t");
02326                         }
02327                         else {
02328                                 n = A[K];
02329                                 if(n &~ (int64)077) {
02330                                         for(i=0; i<VL; i++)
02331                                                 V[I*VSZ+i] = 0;
02332                                 }
02333                                 else {
02334                                         for(i=0; i<VL; i++)
02335                                                 V[I*VSZ+i] = V[J*VSZ+i]>>n;
02336                                 }
02337                                 DISASM3("V%1o\tV%1o>A%1o", I, J, K);
02338                                 DISASMV(I, "\t\t");
02339                         }
02340                         prefix = 0;
02341                 }
02342                 break;
02343 
02344           case 0152:                            /* Vi Vj,Vj<Ak */
02345                 prefix_check(prefix != 0 && prefix != 05400);
02346                 if (prefix == 0) {
02347                         if(K == 0) {
02348                                 for(i=0; i<VL-1; i++)
02349                                         V[I*VSZ+i] = (V[J*VSZ+i]<<1) | (V[J*VSZ+i+1]>>63);
02350                                 V[I*VSZ+VL-1] = V[J*VSZ+VL-1]<<1;
02351                         }
02352                         else if(A[K] &~ (int64)0177) {
02353                                 for(i=0; i<VL; i++)
02354                                         V[I*VSZ+i] = 0;
02355                         }
02356                         else if(A[K] & (int64)0100) {
02357                                 n = A[K]&077;
02358                                 for(i=0; i<VL-1; i++)
02359                                         V[I*VSZ+i] = V[J*VSZ+i+1]<<n;
02360                                 V[I*VSZ+VL-1] = 0;
02361                         }
02362                         else {
02363                                 n = A[K];
02364                                 for(i=0; i<VL-1; i++)
02365                                         V[I*VSZ+i] = (V[J*VSZ+i]<<n) | (V[J*VSZ+i+1]>>(64-n));
02366                                 V[I*VSZ+VL-1] = V[J*VSZ+VL-1]<<n;
02367                         }
02368                         DISASM4("V%1o\tV%1o,V%1o<A%1o", I, J, J, K);
02369                         DISASMV(I, "\t");
02370                 }
02371                 else {
02372                         n = A[K]&077;
02373                         for(i=n; i<VL; i++)
02374                                 V[I*VSZ+i-n] = V[J*VSZ+i];
02375                         DISASM3("V%1o\tV%1o,A%1o", I, J, K);
02376                         DISASMV(I, "\t\t");
02377                         prefix = 0;
02378                 }
02379                 break;
02380 
02381           case 0153:                            /* Vi Vj,Vj>Ak */
02382                 prefix_check(prefix != 0 && prefix != 05400);
02383                 if (prefix == 0) {
02384                         if(K == 0) {
02385                                 for(i=VL-1; i>0; i--)
02386                                         V[I*VSZ+i] = (V[J*VSZ+i]>>1) | (V[J*VSZ+i-1]<<63);
02387                                 V[I*VSZ+0] = V[J*VSZ+0]>>1;
02388                         }
02389                         else if(A[K] &~ (int64)0177) {
02390                                 for(i=0; i<VL; i++)
02391                                         V[I*VSZ+i] = 0;
02392                         }
02393                         else if(A[K] & (int64)0100) {
02394                                 n = A[K]&077;
02395                                 for(i=VL-1; i>0; i--)
02396                                         V[I*VSZ+i] = V[J*VSZ+i-1]>>n;
02397                                 V[I*VSZ+0] = 0;
02398                         }
02399                         else {
02400                                 n = A[K];
02401                                 for(i=VL-1; i>0; i--)
02402                                         V[I*VSZ+i] = (V[J*VSZ+i]>>n) | (V[J*VSZ+i-1]<<(64-n));
02403                                 V[I*VSZ+0] = V[J*VSZ+0]>>n;
02404                         }
02405                         DISASM4("V%1o\tV%1o,V%1o>A%1o", I, J, J, K);
02406                         DISASMV(I, "\t");
02407                 }
02408                 else {
02409                         if (K == 0) {
02410                                 i     = 0;
02411                                 j     = 0;
02412                                 n     = 0;
02413                                 reg64 = 1;
02414                                 for(n=0; n<64; j++, n++, reg64 <<= 1) {
02415                                         if ((reg64 & VM) != 0)
02416                                                 V[I*VSZ+(i++)] = V[J*VSZ+j];
02417                                 }
02418 
02419                                 n     = 0;
02420                                 reg64 = 1;
02421                                 for(n=0; n<64; j++, n++, reg64 <<= 1) {
02422                                         if ((reg64 & VM1) != 0)
02423                                                 V[I*VSZ+(i++)] = V[J*VSZ+j];
02424                                 }
02425 
02426                                 DISASM2("V%1o\tV%1o,[VM]", I, J);
02427                                 DISASMV(I, "\t\t");
02428                         }
02429                         else if (K == 1) {
02430                                 i     = 0;
02431                                 j     = 0;
02432                                 n     = 0;
02433                                 reg64 = 1;
02434                                 for(n=0; n<64; i++, n++, reg64 <<= 1) {
02435                                         if ((reg64 & VM) != 0)
02436                                                 V[I*VSZ+i] = V[J*VSZ+(j++)];
02437                                 }
02438 
02439                                 n     = 0;
02440                                 reg64 = 1;
02441                                 for(n=0; n<64; i++, n++, reg64 <<= 1) {
02442                                         if ((reg64 & VM1) != 0)
02443                                                 V[I*VSZ+i] = V[J*VSZ+(j++)];
02444                                 }
02445 
02446                                 DISASM2("V%1o,[VM]\tV%1o", I, J);
02447                                 DISASMV(I, "\t\t");
02448                         }
02449                         else
02450                                 status = UNIMPL_INST;
02451                         prefix = 0;
02452                 }
02453                 break;
02454 
02455           case 0154:                            /* Vi Sj+Vk */
02456                 prefix_check(prefix);
02457                 if(J == 0)
02458                         oj = &zero;
02459                 else
02460                         oj = &S[J];
02461                 for(i=0; i<VL; i++)
02462                         V[I*VSZ+i] = *oj + V[K*VSZ+i];
02463                 DISASM3("V%1o\tS%1o+V%1o", I, J, K);
02464                 DISASMV(I, "\t\t");
02465                 break;
02466 
02467           case 0155:                            /* Vi Vj+Vk */
02468                 prefix_check(prefix);
02469                 for(i=0; i<VL; i++)
02470                         V[I*VSZ+i] = V[J*VSZ+i] + V[K*VSZ+i];
02471                 DISASM3("V%1o\tV%1o+V%1o", I, J, K);
02472                 DISASMV(I, "\t\t");
02473                 break;
02474 
02475           case 0156:                            /* Vi Sj-Vk */
02476                 prefix_check(prefix);
02477                 if(J == 0)
02478                         oj = &zero;
02479                 else
02480                         oj = &S[J];
02481                 for(i=0; i<VL; i++)
02482                         V[I*VSZ+i] = *oj - V[K*VSZ+i];
02483                 DISASM3("V%1o\tS%1o-V%1o", I, J, K);
02484                 DISASMV(I, "\t\t");
02485                 break;
02486 
02487           case 0157:                            /* Vi Vj-Vk */
02488                 prefix_check(prefix);
02489                 for(i=0; i<VL; i++)
02490                         V[I*VSZ+i] = V[J*VSZ+i] - V[K*VSZ+i];
02491                 DISASM3("V%1o\tV%1o-V%1o", I, J, K);
02492                 DISASMV(I, "\t\t");
02493                 break;
02494 
02495           case 0160:                            /* Vi Sj*FVk */
02496                 prefix_check(prefix);
02497                 if(J == 0)
02498                         oj = &zero;
02499                 else
02500                         oj = &S[J];
02501                 rr = &V[I*VSZ];
02502                 ok = &V[K*VSZ];
02503                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02504                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
02505                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02506                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02507                                                                         AR_UNROUNDED);
02508                         else {
02509                                 status = ar_ifmul64((AR_IEEE_64*)rr,
02510                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
02511                                                                         SR0&RMMASK);
02512                                 if(IS_ERROR_STATUS(status))
02513                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02514                         }
02515                         status &= AR_ERROR_STATUS;
02516                         rr++;
02517                         ok++;
02518                 }
02519                 DISASM3("V%1o\tS%1o*FV%1o", I, J, K);
02520                 DISASMV(I, "\t\t");
02521                 break;
02522 
02523           case 0161:                            /* Vi Vj*FVk */
02524                 prefix_check(prefix);
02525                 rr = &V[I*VSZ];
02526                 oj = &V[J*VSZ];
02527                 ok = &V[K*VSZ];
02528                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02529                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
02530                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02531                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02532                                                                         AR_UNROUNDED);
02533                         else {
02534                                 status = ar_ifmul64((AR_IEEE_64*)rr,
02535                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
02536                                                                         SR0&RMMASK);
02537                                 if(IS_ERROR_STATUS(status))
02538                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02539                         }
02540                         status &= AR_ERROR_STATUS;
02541                         rr++;
02542                         oj++;
02543                         ok++;
02544                 }
02545                 DISASM3("V%1o\tV%1o*FV%1o", I, J, K);
02546                 DISASMV(I, "\t\t");
02547                 break;
02548 
02549           case 0162:
02550                 prefix_check(prefix);
02551                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
02552                         status = UNIMPL_INST;
02553                         break;
02554                 }
02555                 if(J == 0)
02556                         oj = &zero;
02557                 else
02558                         oj = &S[J];
02559                 rr = &V[I*VSZ];
02560                 ok = &V[K*VSZ];
02561                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02562                         status = ar_ifdiv64((AR_IEEE_64*)rr,
02563                                             (AR_IEEE_64*)ok,
02564                                             (AR_IEEE_64*)oj,
02565                                             SR0&RMMASK);
02566                         if(status)
02567                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
02568                         rr++;
02569                         ok++;
02570                 }
02571                 DISASM3("V%1o\tS%1o/FV%1o", I, J, K);
02572                 DISASMV(I, "\t\t");
02573                 break;
02574 
02575           case 0163:
02576                 prefix_check(prefix);
02577                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
02578                         status = UNIMPL_INST;
02579                         break;
02580                 }
02581                 rr = &V[I*VSZ];
02582                 oj = &V[J*VSZ];
02583                 ok = &V[K*VSZ];
02584                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02585                         status = ar_ifdiv64((AR_IEEE_64*)rr,
02586                                             (AR_IEEE_64*)ok,
02587                                             (AR_IEEE_64*)oj,
02588                                             SR0&RMMASK);
02589                         status &= AR_ERROR_STATUS;
02590                         if(status)
02591                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
02592                         rr++;
02593                         oj++;
02594                         ok++;
02595                 }
02596                 DISASM3("V%1o\tV%1o/FV%1o", I, J, K);
02597                 DISASMV(I, "\t\t");
02598                 break;
02599 
02600           case 0164:                            /* Vi Sj*RVk */
02601                 prefix_check(prefix != 0 &&
02602                                          !((prefix >= 05501 && prefix <= 05507) ||
02603                                            (prefix >= 05521 && prefix <= 05527) ||
02604                                            (prefix >= 05541 && prefix <= 05547)));
02605                 if(J == 0)
02606                         oj = &zero;
02607                 else
02608                         oj = &S[J];
02609                 if (prefix == 0) {
02610                         rr = &V[I*VSZ];
02611                         ok = &V[K*VSZ];
02612                         for(i=0; i<VL && status==AR_STAT_OK; i++) {
02613                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02614                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02615                                                                         AR_ROUNDED);
02616                                 status &= AR_ERROR_STATUS;
02617                                 if(status)
02618                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02619                                 rr++;
02620                                 ok++;
02621                         }
02622                         DISASM3("V%1o\tS%1o*RV%1o", I, J, K);
02623                         DISASMV(I, "\t\t");
02624                 }
02625                 else if (prefix >= 05501 && prefix <= 05507) {
02626                         if(K == 0)
02627                                 ok = &sb;
02628                         else
02629                                 ok = &S[K];
02630                         cmpres = AR_compare((AR_DATA*)oj, &ieee_float_64,
02631                                                                 (AR_DATA*)ok, &ieee_float_64);
02632                         switch(prefix) {
02633                         case 05501:
02634                                 S[I] = (cmpres == AR_Compare_EQ) ? ones : zero;
02635                                 break;
02636                         case 05502:
02637                                 S[I] = (cmpres != AR_Compare_EQ) ? ones : zero;
02638                                 break;
02639                         case 05503:
02640                                 S[I] = (cmpres == AR_Compare_GT) ? ones : zero;
02641                                 break;
02642                         case 05504:
02643                                 S[I] = (cmpres == AR_Compare_LT || cmpres == AR_Compare_EQ)
02644                                            ? ones : zero;
02645                                 break;
02646                         case 05505:
02647                                 S[I] = (cmpres == AR_Compare_LT) ? ones : zero;
02648                                 break;
02649                         case 05506:
02650                                 S[I] = (cmpres == AR_Compare_GT || cmpres == AR_Compare_EQ)
02651                                            ? ones : zero;
02652                                 break;
02653                         case 05507:
02654                                 S[I] = (cmpres == AR_Compare_Unord) ? ones : zero;
02655                                 break;
02656                         }
02657                         DISASM5("S%1o\tS%1o,%2.2s,S%1o\t0x%16.16llx\n",
02658                                         I, J, "EQNEGTLELTGEUN"+(((prefix&07)-1)*2), K, S[I]);
02659                         prefix = 0;
02660                 }
02661                 else if (prefix >= 05521 && prefix <= 05527) {
02662                         VM = VM1 = 0;
02663                         for(i=0; i<VL; i++) {
02664                                 cmpres = AR_compare((AR_DATA*)oj, &ieee_float_64,
02665                                                                         (AR_DATA*)&V[K*VSZ+i], &ieee_float_64);
02666                                 switch(prefix) {
02667                                 case 05521:
02668                                         if (cmpres == AR_Compare_EQ) {
02669                                                 if(i < 64)
02670                                                         VM |= ((int64)1<<(63-i));
02671                                                 else
02672                                                         VM1 |= ((int64)1<<(127-i));
02673                                         }
02674                                         break;
02675                                 case 05522:
02676                                         if (cmpres != AR_Compare_EQ) {
02677                                                 if(i < 64)
02678                                                         VM |= ((int64)1<<(63-i));
02679                                                 else
02680                                                         VM1 |= ((int64)1<<(127-i));
02681                                         }
02682                                         break;
02683                                 case 05523:
02684                                         if (cmpres == AR_Compare_GT) {
02685                                                 if(i < 64)
02686                                                         VM |= ((int64)1<<(63-i));
02687                                                 else
02688                                                         VM1 |= ((int64)1<<(127-i));
02689                                         }
02690                                         break;
02691                                 case 05524:
02692                                         if (cmpres == AR_Compare_LT || cmpres == AR_Compare_EQ) {
02693                                                 if(i < 64)
02694                                                         VM |= ((int64)1<<(63-i));
02695                                                 else
02696                                                         VM1 |= ((int64)1<<(127-i));
02697                                         }
02698                                         break;
02699                                 case 05525:
02700                                         if (cmpres == AR_Compare_LT) {
02701                                                 if(i < 64)
02702                                                         VM |= ((int64)1<<(63-i));
02703                                                 else
02704                                                         VM1 |= ((int64)1<<(127-i));
02705                                         }
02706                                         break;
02707                                 case 05526:
02708                                         if (cmpres == AR_Compare_GT || cmpres == AR_Compare_EQ) {
02709                                                 if(i < 64)
02710                                                         VM |= ((int64)1<<(63-i));
02711                                                 else
02712                                                         VM1 |= ((int64)1<<(127-i));
02713                                         }
02714                                         break;
02715                                 case 05527:
02716                                         if (cmpres == AR_Compare_Unord) {
02717                                                 if(i < 64)
02718                                                         VM |= ((int64)1<<(63-i));
02719                                                 else
02720                                                         VM1 |= ((int64)1<<(127-i));
02721                                         }
02722                                         break;
02723                                 }
02724                         }
02725                         DISASM5("VM\tS%1o,%2.2s,V%1o\t0x%16.16llx,0x%16.16llx\n",
02726                                         J, "EQNEGTLELTGEUN"+(((prefix&07)-1)*2), K, VM, VM1);
02727                         prefix = 0;
02728                 }
02729                 else if (prefix >= 05541 && prefix <= 05547) {
02730                         VM = VM1 = 0;
02731                         for(i=0; i<VL; i++) {
02732                                 cmpres = AR_compare((AR_DATA*)&V[J*VSZ+i], &ieee_float_64,
02733                                                                         (AR_DATA*)&V[K*VSZ+i], &ieee_float_64);
02734                                 switch(prefix) {
02735                                 case 05541:
02736                                         if (cmpres == AR_Compare_EQ) {
02737                                                 if(i < 64)
02738                                                         VM |= ((int64)1<<(63-i));
02739                                                 else
02740                                                         VM1 |= ((int64)1<<(127-i));
02741                                         }
02742                                         break;
02743                                 case 05542:
02744                                         if (cmpres != AR_Compare_EQ) {
02745                                                 if(i < 64)
02746                                                         VM |= ((int64)1<<(63-i));
02747                                                 else
02748                                                         VM1 |= ((int64)1<<(127-i));
02749                                         }
02750                                         break;
02751                                 case 05543:
02752                                         if (cmpres == AR_Compare_GT) {
02753                                                 if(i < 64)
02754                                                         VM |= ((int64)1<<(63-i));
02755                                                 else
02756                                                         VM1 |= ((int64)1<<(127-i));
02757                                         }
02758                                         break;
02759                                 case 05544:
02760                                         if (cmpres == AR_Compare_LT || cmpres == AR_Compare_EQ) {
02761                                                 if(i < 64)
02762                                                         VM |= ((int64)1<<(63-i));
02763                                                 else
02764                                                         VM1 |= ((int64)1<<(127-i));
02765                                         }
02766                                         break;
02767                                 case 05545:
02768                                         if (cmpres == AR_Compare_LT) {
02769                                                 if(i < 64)
02770                                                         VM |= ((int64)1<<(63-i));
02771                                                 else
02772                                                         VM1 |= ((int64)1<<(127-i));
02773                                         }
02774                                         break;
02775                                 case 05546:
02776                                         if (cmpres == AR_Compare_GT || cmpres == AR_Compare_EQ) {
02777                                                 if(i < 64)
02778                                                         VM |= ((int64)1<<(63-i));
02779                                                 else
02780                                                         VM1 |= ((int64)1<<(127-i));
02781                                         }
02782                                         break;
02783                                 case 05547:
02784                                         if (cmpres == AR_Compare_Unord) {
02785                                                 if(i < 64)
02786                                                         VM |= ((int64)1<<(63-i));
02787                                                 else
02788                                                         VM1 |= ((int64)1<<(127-i));
02789                                         }
02790                                         break;
02791                                 }
02792                         }
02793                         DISASM5("VM\tV%1o,%2.2s,V%1o\t0x%16.16llx,0x%16.16llx\n",
02794                                         J, "EQNEGTLELTGEUN"+(((prefix&07)-1)*2), K, VM, VM1);
02795                         prefix = 0;
02796                 }
02797                 break;
02798 
02799           case 0165:                            /* Vi Vj*[RLU]Vk */
02800                 prefix_check(prefix != 0 && prefix != 05400);
02801                 if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
02802                         if (prefix == 0) {
02803                                 for(i=0; i<VL; i++)
02804                                         V[I*VSZ+i] = V[J*VSZ+i] * V[K*VSZ+i];
02805                                 DISASM3("V%1o\tV%1o*LV%1o", I, J, K);
02806                         }
02807                         else {
02808                                 rr = &V[I*VSZ];
02809                                 oj = &V[J*VSZ];
02810                                 ok = &V[K*VSZ];
02811                                 for(i=0; status==AR_STAT_OK && i<VL; i++) {
02812                                         status = ar_imul64u(rr, *oj, *ok);
02813                                         rr++;
02814                                         oj++;
02815                                         ok++;
02816                                 }
02817                                 DISASM3("V%1o\tV%1o*UV%1o\n", I, J, K);
02818                                 prefix = 0;
02819                         }
02820                 }
02821                 else {                                  /* Vi Vj*RVk */
02822                         rr = &V[I*VSZ];
02823                         oj = &V[J*VSZ];
02824                         ok = &V[K*VSZ];
02825                         for(i=0; i<VL && status==AR_STAT_OK; i++) {
02826                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02827                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02828                                                                         AR_ROUNDED);
02829                                 status &= AR_ERROR_STATUS;
02830                                 rr++;
02831                                 oj++;
02832                                 ok++;
02833                         }
02834                         DISASM3("V%1o\tV%1o*RV%1o", I, J, K);
02835                 }
02836                 DISASMV(I, "\t\t");
02837                 break;
02838 
02839           case 0166:                            /* Vi Sj*IVk */
02840                 prefix_check(prefix != 0 && prefix != 05400);
02841                 if(J == 0)
02842                         oj = &zero;
02843                 else
02844                         oj = &S[J];
02845                 rr = &V[I*VSZ];
02846                 ok = &V[K*VSZ];
02847                 if(ar_state_register.ar_float_format == AR_IEEE_FLOATING_POINT) {
02848                         if (prefix == 0) {
02849                                 for(i=0; i<VL; i++)
02850                                         V[I*VSZ+i] = *oj * V[K*VSZ+i];
02851                                 DISASM3("V%1o\tS%1o*LV%1o", I, J, K);
02852                         }
02853                         else {
02854                                 for(i=0; status==AR_STAT_OK && i<VL; i++) {
02855                                         status = ar_imul64u(rr, *oj, *ok);
02856                                         rr++;
02857                                         ok++;
02858                                 }
02859                                 DISASM3("V%1o\tS%1o*UV%1o\n", I, J, K);
02860                                 prefix = 0;
02861                         }
02862                 }
02863                 else {
02864                         for(i=0; i<VL && status==AR_STAT_OK; i++) {
02865                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02866                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02867                                                                         AR_RECIPROCAL_ITERATION);
02868                                 status &= AR_ERROR_STATUS;
02869                                 rr++;
02870                                 ok++;
02871                         }
02872                         DISASM3("V%1o\tS%1o*IV%1o", I, J, K);
02873                 }
02874                 DISASMV(I, "\t\t");
02875                 break;
02876 
02877           case 0167:                            /* Vi Vj*IVk */
02878                 prefix_check(prefix);
02879                 rr = &V[I*VSZ];
02880                 oj = &V[J*VSZ];
02881                 if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
02882                         ok = &V[K*VSZ];
02883                         for(i=0; i<VL && status==AR_STAT_OK; i++) {
02884                                 status = ar_cfmul64((AR_CRAY_64*)rr,
02885                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok,
02886                                                                         AR_RECIPROCAL_ITERATION);
02887                                 rr++;
02888                                 oj++;
02889                                 ok++;
02890                         }
02891                         DISASM3("V%1o\tV%1o*RV%1o", I, J, K);
02892                 }
02893                 else if(K <= 2) {
02894                         for(i=0; i<VL && status==AR_STAT_OK; i++) {
02895                                 switch(K) {
02896                                 case 0:
02897                                         status = ar_ifix64((AR_INT_64*)rr, (const AR_IEEE_64*)oj,
02898                                                                            64, AR_ROUND_ZERO);
02899                                         break;
02900                                 case 1:
02901                                         status = ar_ifix64((AR_INT_64*)rr, (const AR_IEEE_64*)oj,
02902                                                                            64, AR_ROUND_NEAREST);
02903                                         break;
02904                                 case 2:
02905                                         status = ar_iflt64((AR_IEEE_64*)rr, (const AR_INT_64*)oj,
02906                                                                            0, AR_ROUND_ZERO);
02907                                         break;
02908                                 }
02909                                 if(IS_ERROR_STATUS(status))
02910                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02911                                 status &= AR_ERROR_STATUS;
02912                                 rr++;
02913                                 oj++;
02914                         }
02915                         DISASM3("V%1o\t%s,V%1o", I, (K==0)?"INT":(K==1)?"RINT":"FLT", J);
02916                 }
02917                 else
02918                         status = UNIMPL_INST;
02919                 DISASMV(I, "\t\t");
02920                 break;
02921 
02922           case 0170:                            /* Vi Sj+FVk */
02923                 prefix_check(prefix);
02924                 if(J == 0)
02925                         oj = &zero;
02926                 else
02927                         oj = &S[J];
02928                 rr = &V[I*VSZ];
02929                 ok = &V[K*VSZ];
02930                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02931                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
02932                                 status = ar_cfadd64((AR_CRAY_64*)rr,
02933                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
02934                         else {
02935                                 status = ar_ifadd64((AR_IEEE_64*)rr,
02936                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
02937                                                                         SR0&RMMASK);
02938                                 if(IS_ERROR_STATUS(status))
02939                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02940                         }
02941                         status &= AR_ERROR_STATUS;
02942                         rr++;
02943                         ok++;
02944                 }
02945                 DISASM3("V%1o\tS%1o+FV%1o", I, J, K);
02946                 DISASMV(I, "\t\t");
02947                 break;
02948 
02949           case 0171:                            /* Vi Vj+FVk */
02950                 prefix_check(prefix);
02951                 rr = &V[I*VSZ];
02952                 oj = &V[J*VSZ];
02953                 ok = &V[K*VSZ];
02954                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02955                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
02956                                 status = ar_cfadd64((AR_CRAY_64*)rr,
02957                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
02958                         else {
02959                                 status = ar_ifadd64((AR_IEEE_64*)rr,
02960                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
02961                                                                         SR0&RMMASK);
02962                                 if(IS_ERROR_STATUS(status))
02963                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02964                         }
02965                         status &= AR_ERROR_STATUS;
02966                         rr++;
02967                         oj++;
02968                         ok++;
02969                 }
02970                 DISASM3("V%1o\tV%1o+FV%1o", I, J, K);
02971                 DISASMV(I, "\t\t");
02972                 break;
02973 
02974           case 0172:                            /* Vi Sj-FVk */
02975                 prefix_check(prefix);
02976                 if(J == 0)
02977                         oj = &zero;
02978                 else
02979                         oj = &S[J];
02980                 rr = &V[I*VSZ];
02981                 ok = &V[K*VSZ];
02982                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
02983                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
02984                                 status = ar_cfsub64((AR_CRAY_64*)rr,
02985                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
02986                         else {
02987                                 status = ar_ifsub64((AR_IEEE_64*)rr,
02988                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
02989                                                                         SR0&RMMASK);
02990                                 if(IS_ERROR_STATUS(status))
02991                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
02992                         }
02993                         status &= AR_ERROR_STATUS;
02994                         rr++;
02995                         ok++;
02996                 }
02997                 DISASM3("V%1o\tS%1o-FV%1o", I, J, K);
02998                 DISASMV(I, "\t\t");
02999                 break;
03000 
03001           case 0173:                            /* Vi Vj-FVk */
03002                 prefix_check(prefix);
03003                 rr = &V[I*VSZ];
03004                 oj = &V[J*VSZ];
03005                 ok = &V[K*VSZ];
03006                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
03007                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT)
03008                                 status = ar_cfsub64((AR_CRAY_64*)rr,
03009                                                                         (AR_CRAY_64*)oj, (AR_CRAY_64*)ok);
03010                         else {
03011                                 status = ar_ifsub64((AR_IEEE_64*)rr,
03012                                                                         (AR_IEEE_64*)oj, (AR_IEEE_64*)ok,
03013                                                                         SR0&RMMASK);
03014                                 if(IS_ERROR_STATUS(status))
03015                                         status = ar_check_status(status, (AR_IEEE_64*)rr);
03016                         }
03017                         status &= AR_ERROR_STATUS;
03018                         rr++;
03019                         oj++;
03020                         ok++;
03021                 }
03022                 DISASM3("V%1o\tV%1o-FV%1o", I, J, K);
03023                 DISASMV(I, "\t\t");
03024                 break;
03025 
03026           case 0174:
03027                 prefix_check(prefix);
03028                 if(K == 0) {                    /* Vi /HVj */
03029                         rr = &V[I*VSZ];
03030                         oj = &V[J*VSZ];
03031                         if(ar_state_register.ar_float_format == AR_CRAY_FLOATING_POINT) {
03032                                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
03033                                         status = ar_c1frecip((AR_CRAY_64*)rr, (AR_CRAY_64*)oj);
03034                                         status &= AR_ERROR_STATUS;
03035                                         rr++;
03036                                         oj++;
03037                                 }
03038                                 DISASM2("V%1o\t/HV%1o", I, J);
03039                         }
03040                         else {
03041                                 for(i=0; i<VL && status==AR_STAT_OK; i++) {
03042                                         status = ar_sqrt((ar_data*)rr, &ieee_float_64,
03043                                                                          (ar_data*)oj, &ieee_float_64);
03044                                         if(IS_ERROR_STATUS(status))
03045                                                 status = ar_check_status(status, (AR_IEEE_64*)rr);
03046                                         status &= AR_ERROR_STATUS;
03047                                         rr++;
03048                                         oj++;
03049                                 }
03050                                 DISASM2("V%1o\tSQRT,V%1o", I, J);
03051                         }
03052                         DISASMV(I, "\t\t");
03053                 }
03054                 else if(K <= 3) {               /* Vi [PQZ]Vj */
03055                         for(i=0; i<VL; i++) {
03056                                 switch(K) {
03057                                 case 1:
03058                                 case 2:
03059                                         for(j=0,n=0; j<64; j++)
03060                                                 if((V[J*VSZ+i]>>j)&1)
03061                                                         n++;
03062                                         if(K == 2)
03063                                                 n &= 1;
03064                                         break;
03065                                 case 3:
03066                                         for(n=0; n<64; n++)
03067                                                 if(V[J*VSZ+i]>>(63-n)) break;
03068                                         break;
03069                                 }
03070                                 V[I*VSZ+i] = n;
03071                         }
03072                         DISASM3("V%1o\t%cV%1o", I, (K==1)?'P':(K==2)?'Q':'Z', J);
03073                         DISASMV(I, "\t\t");
03074                 }
03075                 else
03076                         status = UNIMPL_INST;
03077                 break;
03078 
03079           case 0175:                            /* [Vi,]VM Vj,[ZNPM] */
03080                 prefix_check(prefix);
03081                 VM = VM1 = 0;
03082                 n = 0;
03083                 if(K & 2) {     /* [PM] */
03084                         for(i=0; i<VL; i++) {
03085                                 if((1-(V[J*VSZ+i]>>63)) ^ (K&1)) {
03086                                         if(i < 64)
03087                                                 VM |= ((int64)1<<(63-i));
03088                                         else
03089                                                 VM1 |= ((int64)1<<(127-i));
03090                                         if(K & 4)
03091                                                 V[I*VSZ+n++] = i;
03092                                 }
03093                         }
03094                 }
03095                 else {                  /* Else [ZN] */
03096                         for(i=0; i<VL; i++) {
03097                                 if(!V[J*VSZ+i] ^ (K&1)) {
03098                                         if(i < 64)
03099                                                 VM |= ((int64)1<<(63-i));
03100                                         else
03101                                                 VM1 |= ((int64)1<<(127-i));
03102                                         if(K & 4)
03103                                                 V[I*VSZ+n++] = i;
03104                                 }
03105                         }
03106                 }
03107                 if(K < 4) {
03108                         DISASM3("VM\tV%1o,%1.1s\t\t0x%16.16llx", J, "ZNPM"+(K&03), VM);
03109                         if(VL > 64)
03110                                 DISASM1(" %16.16llx\n", VM1);
03111                         else
03112                                 DISASM0("\n");
03113                 }
03114                 else {
03115                         DISASM3("VM,V%1o\tV%1o,%1.1s", I, J, "ZNPM"+(K&03));
03116                         if(VL > 64)
03117                                 DISASM2("\t\t0x%16.16llx %16.16llx\n", VM, VM1);
03118                         else
03119                                 DISASM1("\t\t0x%16.16llx\n", VM);
03120                         DISASMV(I, "\t\t\t\t\t");
03121                 }
03122                 break;
03123 
03124           case 0176:
03125                 prefix_check(prefix != 0 && prefix != 05400);
03126                 if(prefix == 0 && J == 0) {
03127                         if(K == 0)
03128                                 n = 1;
03129                         else
03130                                 n = A[K];
03131                         for(i=0; i<VL; i++)
03132                                 V[I*VSZ+i] = load_pvp_word((long)A[0]+i*n);
03133                         DISASM2("V%1o\t,A0,A%1o", I, K);
03134                 }
03135                 else if(prefix == 0) {
03136                         for(i=0; i<VL; i++)
03137                                 V[I*VSZ+i] = load_pvp_word((long)(A[0]+V[K*VSZ+i]));
03138                         DISASM2("V%1o\t,A0,V%1o", I, K);
03139                 }
03140                 else {
03141                         for(i=0; i<VL; i++) {
03142                                 V[I*VSZ+i] = load_pvp_word((long)(A[0]+V[K*VSZ+i]));
03143                                 V[J*VSZ+i] = load_pvp_word((long)(A[K]+V[K*VSZ+i]));
03144                         }
03145                         DISASM4("V%1o:V%1o\t,A0:A%1o,V%1o", I, J, K, K);
03146                 }
03147                 DISASMV(I, "\t\t");
03148                 break;
03149 
03150           case 0177:
03151                 prefix_check(prefix);
03152                 if(I == 0) {
03153                         if(K == 0)
03154                                 n = 1;
03155                         else
03156                                 n = A[K];
03157                         for(i=0; i<VL; i++)
03158                                 store_pvp_word((long)A[0]+i*n, V[J*VSZ+i]);
03159                         DISASM2(",A0,A%1o\tV%1o\n", K, J);
03160                 }
03161                 else {
03162                         for(i=0; i<VL; i++)
03163                                 store_pvp_word((long)(A[0]+V[K*VSZ+i]), V[J*VSZ+i]);
03164                         DISASM2(",A0,V%1o\tV%1o\n", K, J);
03165                 }
03166                 break;
03167           }
03168 
03169         }
03170 
03171         ar_state_register.ar_truncate_bits = save_trunc_bits;
03172 
03173         if(status == UNIMPL_INST) {
03174                 DISASM1("%6.6o\n", p1);
03175                 ar_internal_error(2013, __FILE__, __LINE__);
03176                 status = AR_STAT_UNDEFINED;
03177         }
03178         else if(status == UNIMPL_PRFX) {
03179                 DISASM2("%6.6o %6.6o\n", prefix, p1);
03180                 ar_internal_error(2013, __FILE__, __LINE__);
03181                 status = AR_STAT_UNDEFINED;
03182         }
03183 
03184         return(status);
03185 }
03186 
03187 typedef union {
03188         struct {
03189                 unsigned int p1: 32;
03190                 unsigned int p2: 32;
03191         }     ui32;
03192         int64 ui64;
03193 } u;
03194 #define LO32(i)    ((int64) (((u*)&(i))->ui32.p2))
03195 #define HI32(i)    ((int64) (((u*)&(i))->ui32.p1))
03196 
03197 static int
03198 ar_imul64u(int64* result, int64 opnd1, int64 opnd2)
03199 {
03200         int64   reg64, sum64, tmp64;
03201 
03202         /*
03203          * Special case "Si Sj*USk".  Eventually, with 128-bit ints,
03204          * we'll be able to support this directly.  For now, we just
03205          * do it by hand in 32-bit chunks:
03206          *
03207          *          a  b
03208          *       x  c  d
03209          *      --------
03210          *         ad bd
03211          *      ac bc
03212          *      --------
03213          *      ac+ad+bd
03214          *        +bc
03215          */
03216         sum64 = LO32(opnd1) * LO32(opnd2);              /* bd */
03217         reg64 = HI32(opnd1) * LO32(opnd2);              /* ad */
03218         tmp64 = LO32(opnd1) * HI32(opnd2);              /* bc */
03219 
03220         /* Sum from right propagating carry (in high 32 bits of sum64) */
03221         sum64 = LO32(reg64) + LO32(tmp64) + HI32(sum64);
03222         sum64 = HI32(reg64) + HI32(tmp64) + HI32(sum64);
03223         reg64 = HI32(opnd1) * HI32(opnd2);              /* ac */
03224         *result  = reg64 + sum64;
03225 
03226         return AR_STAT_OK;
03227 }
03228 
03229 #define CRAY_AHDR_SIZE  8       /* # words in cray a.out files */
03230 
03231 #define PAGESZ          256             /* # words in data space pages read in */
03232 #define PAGESHFT        8               /* Shift to get page # */
03233 
03234 static int      idf_fd;                 /* Intrinsic data file file descriptor */
03235 static long idf_size;           /* Intrinsic data file size (in bytes) */
03236 static long text_size;          /* Size of text space */
03237 static long data_size;          /* Size of data space */
03238 static long data_offset;        /* Offset to data space */
03239 static int      shared_text=0;  /* =1 for a shared text data file */
03240 static long data_address;       /* Offset in data file to data section */
03241 
03242 static int64** data_page;       /* Memory locations of data pages read in */
03243 static int  ndata_pages;        /* Max # of data space pages */
03244 
03245 static void
03246 open_arith_file()
03247 {
03248         int     fd;
03249         int     i,v;
03250         int     ieee;
03251 
03252         int64   ahdr[CRAY_AHDR_SIZE];
03253         char*   craylibs;
03254         char*   str;
03255         char*   work;
03256 
03257         /* Find and open intrinsic evaluation data file */
03258 
03259         stack=(int64*)malloc((STACK_SIZE+1+5*MAX_ARGS)*8);
03260         craylibs=(char*)getenv("CRAYLIBS");
03261         work = (char*)stack;
03262 
03263         /* Use the arith data file at the CRAYLIBS path if it is set */
03264 
03265         if(craylibs != NULL) {
03266                 strcpy(work, craylibs);
03267                 v=strlen(work);
03268                 strcpy(&work[v],"/arith");
03269                 idf_fd=open(work, O_RDONLY);
03270         }
03271 
03272         /* Check default locations for a (native-only) arith data file */
03273 
03274 #if _CRAY
03275         else {
03276                 strcpy(work, "/opt/ctl/craylibs/craylibs/arith");
03277                 v = 27;
03278                 idf_fd=open(work, O_RDONLY);
03279                 if(idf_fd < 0) {
03280                         strcpy(work, "/lib/arith");
03281                         v = 4;
03282                         idf_fd=open(work, O_RDONLY);
03283                 }
03284         }
03285 #endif
03286         if(idf_fd < 0)
03287                 ar_internal_error(2009, __FILE__, __LINE__);
03288 
03289         /* Load intrinsic evaluation data file into heap memory */
03290 
03291         idf_size=lseek(idf_fd, 0, SEEK_END);
03292         if(idf_size > 8*8) {
03293                 lseek(idf_fd, 0, SEEK_SET);
03294                 read(idf_fd, ahdr, CRAY_AHDR_SIZE*8);
03295                 if((ahdr[0]>>32) == 0 && (ahdr[0]&0xffff) == 0407) {
03296                         ar_mach_type = (ahdr[0]>>16)&0xff;
03297                         ieee = (ahdr[0]>>29)&1;
03298                         shared_text = (ahdr[0]>>31)&1;
03299                         text_size = ahdr[1];
03300                         data_size = ahdr[2];
03301                         /* Check primary machine type */
03302                         if(ar_mach_type >= YMP && ar_mach_type <= T3E) {
03303                                 if(ar_mach_type != 9)
03304                                         code = (unsigned char*)malloc(text_size*8);
03305                                 if(code == NULL)
03306                                         idf_size = -3;          /* Could not malloc text space */
03307                         }
03308                         else
03309                                 idf_size = -2;
03310                 }
03311                 else
03312                         idf_size = -1;                          /* Bad magic */
03313         }
03314         else
03315                 idf_size = 0;
03316 
03317         /* Validate intrinsic evaluation data file contents and version info */
03318 
03319         if(idf_size > 0) {
03320                 data_address = CRAY_AHDR_SIZE+text_size;
03321                 data_offset = (1-shared_text)*text_size;
03322                 read(idf_fd, code, text_size*8);
03323                 str = (char*)strnstrn((char*)code, text_size*8,
03324                           "@(#)PVP arith/libmv2_version ", 29);
03325                 if(str != NULL)
03326                         strcpy(AR_libmv2, str+14);
03327                 else {
03328                         lseek(idf_fd, idf_size-64, SEEK_SET);
03329                         read(idf_fd, stack, 64);
03330                         v=63;
03331                         while(v > 0) {
03332                                 if(strncmp((char*)&stack[v], "libmv2_version", 14) == 0) {
03333                                         strcpy(AR_libmv2, (char*)&stack[v]);
03334                                         if(strncmp((char*)&stack[v-13], "PVP arith", 9))
03335                                                 idf_size=-1;
03336                                         break;
03337                                 }
03338                                 if(stack[v] == '\n')
03339                                         stack[v]='\0';
03340                                 v--;
03341                         }
03342                         if(v <= 0)
03343                                 idf_size = -1;
03344                         v = 0;
03345                 }
03346         }
03347 
03348         if(idf_size < 0)
03349            ar_internal_error(2010, __FILE__, __LINE__);
03350 
03351         /* Validate probable libm.a version that will be used for loading */
03352 
03353         if(v > 0 && AR_libmv2[2] != 'x' && AR_libmv2[15+2] != 'x') {
03354                 strcpy(&work[v], "/libm.a");
03355                 fd=open(work, O_RDONLY);
03356                 if(fd < 0) {
03357                         strcpy(&work[v], "/../libm.a");
03358                         fd=open(work, O_RDONLY);
03359                 }
03360                 if(fd >= 0) {
03361                         read(fd, work, STACK_SIZE*8);
03362                         close(fd);
03363                         for(v=0; v<STACK_SIZE*8-27; v++)
03364                                 if(strncmp((char*)&work[v], "@(#)libmv2_version", 18) == 0) break;
03365                         if(v < STACK_SIZE*8-27) {
03366                                 v+=19;
03367                                 for(i=0; i<8; i+=2)
03368                                         if(work[v+i]!='x' && AR_libmv2[15+i]!='x' &&
03369                                            work[v+i]!=AR_libmv2[15+i])
03370                                                 fd=-2;
03371                         }
03372                         else
03373                                 fd=-3;
03374                 }
03375 
03376                 /* If we are cross-compiling, libm.a need not exist */
03377 
03378                 else {
03379 #if _CRAY
03380 #if _CRAYIEEE
03381                         fd=-ieee;               /* Ok if cross-compiling to Cray FP system */
03382 #else
03383                         fd=1-ieee;              /* Ok if cross-compiling to IEEE FP system */
03384 #endif
03385 #else
03386                         fd=0;                   /* Ok since we are cross-compiling */
03387 #endif
03388                 }
03389                 if(fd < 0)
03390                         PRINTMSG(0, 2016, Logfile_Warning, 0, "YMP/C90", "0", "", "");
03391         }
03392 
03393         /* Define known numerical characteristics of each machine type */
03394 
03395         switch(ar_mach_type) {
03396 
03397         case YMP:
03398         case C90:
03399         case T90:
03400                 if(ar_mach_type == T90 && ieee) {
03401                         ar_state_register.ar_float_format = AR_IEEE_FLOATING_POINT;
03402                         ar_state_register.ar_rounding_mode = AR_ROUND_NEAREST;
03403                         ar_state_register.ar_underflow_mode = AR_UNDERFLOW_TO_PLUS_ZERO;
03404                         ar_state_register.ar_denorms_trap = 0;
03405                         ar_state_register.ar_128bit_format = AR_128BIT_EXTENDED_DOUBLE;
03406                         ar_rounding_modes = (1<<AR_ROUND_NEAREST) |
03407                                                                 (1<<AR_ROUND_ZERO) |
03408                                                                 (1<<AR_ROUND_PLUS_INFINITY) |
03409                                                                 (1<<AR_ROUND_MINUS_INFINITY);
03410                         ar_underflow_modes = 1<<AR_UNDERFLOW_TO_PLUS_ZERO;
03411                 }
03412                 else {
03413                         ar_state_register.ar_float_format = AR_CRAY_FLOATING_POINT;
03414                         ar_state_register.ar_rounding_mode = AR_ROUNDED;
03415                         ar_state_register.ar_underflow_mode = AR_UNDERFLOW_TO_PLUS_ZERO;
03416                         ar_state_register.ar_denorms_trap = 0;
03417                         ar_state_register.ar_128bit_format = AR_128BIT_DOUBLE_DOUBLE;
03418                         ar_rounding_modes = (1<<AR_ROUNDED) | (1<<AR_UNROUNDED);
03419                         ar_underflow_modes = 1<<AR_UNDERFLOW_TO_PLUS_ZERO;
03420                 }
03421                 AMASK = 0xffffffff;
03422                 ASB   = 0x80000000;
03423                 set_a_size(32);
03424                 if(ar_mach_type == YMP) {
03425                         JSZP = 2;
03426                         VSZ = 64;
03427                 }
03428                 else {
03429                         JSZP = 3;
03430                         VSZ = 128;
03431                         if(ar_mach_type == T90) {
03432                                 AMASK  |= (AMASK<<32);
03433                                 ASB   <<= 32;
03434                                 set_a_size(64);
03435                         }
03436                 }
03437                 break;
03438 
03439         case T3D:
03440                 ar_state_register.ar_float_format = AR_IEEE_FLOATING_POINT;
03441                 ar_state_register.ar_rounding_mode = AR_ROUND_NEAREST;
03442                 ar_state_register.ar_underflow_mode = AR_UNDERFLOW_TO_PLUS_ZERO;
03443                 ar_state_register.ar_denorms_trap = 1;
03444                 ar_state_register.ar_128bit_format = AR_128BIT_EXTENDED_DOUBLE;
03445                 ar_rounding_modes = (1<<AR_ROUND_NEAREST);
03446                 ar_underflow_modes = 1<<AR_UNDERFLOW_TO_PLUS_ZERO;
03447                 JSZP = VSZ = 0;
03448                 break;
03449 
03450         case T3E:
03451                 ar_state_register.ar_float_format = AR_IEEE_FLOATING_POINT;
03452                 ar_state_register.ar_rounding_mode = AR_ROUND_NEAREST;
03453                 ar_state_register.ar_underflow_mode = AR_UNDERFLOW_TO_PLUS_ZERO;
03454                 ar_state_register.ar_denorms_trap = 1;
03455                 ar_state_register.ar_128bit_format = AR_128BIT_EXTENDED_DOUBLE;
03456                 ar_rounding_modes = (1<<AR_ROUND_NEAREST) |
03457                                                         (1<<AR_ROUND_ZERO) |
03458                                                         (1<<AR_ROUND_PLUS_INFINITY) |
03459                                                         (1<<AR_ROUND_MINUS_INFINITY);
03460                 ar_underflow_modes = 1<<AR_UNDERFLOW_TO_PLUS_ZERO;
03461                 JSZP = VSZ = 0;
03462                 break;
03463         }
03464 
03465         if(JSZP == 3 && text_size > 0x3fff) {
03466                 /* Current text segment sizes are less than 64K parcels.  Therefore,
03467                  * C90/T90 instructions 006..017 have a zero 3rd parcel which is skipped
03468                  * in the instruction simulation in ar_sim.  When/if the text segment
03469                  * grows to more than 64K parcels, this test will cause a failure
03470                  * and the branch instruction simulation will have to start using the
03471                  * 3rd parcel.
03472                  */
03473                  ar_internal_error(2012, __FILE__, __LINE__);
03474         }
03475 
03476         /* Allocate data space page mapping array */
03477         /* Note: 1 extra page for uninitialized data */
03478 
03479         ndata_pages = ((data_size+PAGESZ-1)>>PAGESHFT)+1;
03480         data_page = (int64**)malloc(ndata_pages*8);
03481         for(i=0; i<ndata_pages; i++)
03482                 data_page[i] = NULL;
03483 
03484         if(VSZ)
03485                 V = (int64*)malloc(VSZ*8*8);    /* Allocate V-register space */
03486 }
03487 
03488 static int64
03489 load_pvp_word(vaddr)
03490 long    vaddr;
03491 {
03492         int     p;
03493         int     n;
03494         long    disk_address;
03495         long    offset = vaddr&0xffffff;
03496         int     segment = (vaddr>>24)&0xff;
03497 
03498         int64   result;
03499 
03500         switch (segment) {
03501 
03502         case DATA:
03503                 offset -= data_offset;
03504                 p = offset>>PAGESHFT;
03505                 if(data_page[p] != NULL)
03506                         return data_page[p][offset&(PAGESZ-1)];
03507 
03508                 /* Check for load before store in uninitialized data space */
03509                 if(p >= (ndata_pages-1))
03510                         ar_internal_error(2012, __FILE__, __LINE__);
03511 
03512                 /* Always allocate a full page for possible stores into uninit'd data */
03513                 data_page[p] = (int64*)malloc(PAGESZ*8);
03514 
03515                 disk_address = (data_address+(offset&~(PAGESZ-1)))*8;
03516                 n = PAGESZ*8;
03517                 if(n > (idf_size-disk_address)) {
03518                         n = idf_size-disk_address;
03519                         memset((char*)(data_page[p])+n, 0xfe, PAGESZ*8-n);
03520                 }
03521                 if(data_page[p] == NULL)
03522                         ar_internal_error(2010, __FILE__, __LINE__);
03523                 lseek(idf_fd, disk_address, SEEK_SET);
03524                 if(read(idf_fd, data_page[p], n) != n)
03525                         ar_internal_error(2010, __FILE__, __LINE__);
03526 
03527                 return data_page[p][offset&(PAGESZ-1)];
03528 
03529         case STACK:
03530                 if(offset < (STACK_SIZE+1+5*MAX_ARGS))
03531                         return stack[offset];
03532                 break;
03533 
03534         default:
03535                 if(segment < n_external_addresses && external_address[segment] != NULL) {
03536                         if(external_length[segment] > offset) {
03537                                 memcpy(&result, external_address[segment]+offset*8, 8);
03538                                 return result;
03539                         }
03540                         /* Allow up to 64 words of unusable slop to be loaded */
03541                         /* See first vector load in memchr.s where this is needed */
03542                         if(external_length[segment] > (offset-64)) {
03543                                 result = 0xf0f1f2f3;
03544                                 return result;
03545                         }
03546                 }
03547 
03548         }
03549 
03550         ar_internal_error(2012, __FILE__, __LINE__);
03551 }
03552 
03553 static void
03554 store_pvp_word(vaddr, result)
03555 long    vaddr;
03556 int64   result;
03557 {
03558         int     p;
03559         long    offset = vaddr&0xffffff;
03560         int     segment = (vaddr>>24)&0xff;
03561 
03562         switch (segment) {
03563 
03564         case DATA:
03565                 offset -= data_offset;
03566                 /* Allow store only beyond the end of initialized data space */
03567                 if(offset < data_size)
03568                         ar_internal_error(2012, __FILE__, __LINE__);
03569 
03570                 p = offset>>PAGESHFT;
03571                 /* If the last initialized data page hasn't been read, do dummy load */
03572                 if(data_page[p] == NULL && p == (ndata_pages-2))
03573                         load_pvp_word((DATA<<24) | (data_offset+(offset&~(PAGESZ-1))));
03574 
03575                 if(data_page[p] != NULL) {
03576                         data_page[p][offset&(PAGESZ-1)] = result;
03577                         return;
03578                 }
03579 
03580                 /* Allow store only into 1st full page of uninitialized data space */
03581                 if(p != (ndata_pages-1))
03582                         ar_internal_error(2012, __FILE__, __LINE__);
03583 
03584                 data_page[p] = (int64*)malloc(PAGESZ*8);
03585                 memset((char*)data_page[p], 0xfe, PAGESZ*8);
03586                 data_page[p][offset&(PAGESZ-1)] = result;
03587                 return;
03588 
03589         case STACK:
03590                 if(offset < (STACK_SIZE+1+5*MAX_ARGS)) {
03591                         stack[offset] = result;
03592                         return;
03593                 }
03594                 break;
03595 
03596         default:
03597                 if(segment < n_external_addresses && external_address[segment] != NULL) {
03598                         if(external_length[segment] > offset) {
03599                                 memcpy(external_address[segment]+offset*8, &result, 8);
03600                                 return;
03601                         }
03602                         /* Allow ORE (without actual store) iff value matches that
03603                          * returned by load_pvp_word above.
03604                          */
03605                         if(external_length[segment] > (offset-64) && result == 0xf0f1f2f3)
03606                                 return;
03607                 }
03608         }
03609 
03610         ar_internal_error(2012, __FILE__, __LINE__);
03611 }
03612 
03613 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines