Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
mpp_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 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <sys/types.h>
00041 #include <unistd.h>
00042 
00043 #include <ar.h>
00044 #if !defined(AR_HDR_SIZE)
00045   /*
00046    * Solaris doesn't define AR_HDR_SIZE.
00047    */
00048 # define AR_HDR_SIZE sizeof(struct ar_hdr)
00049 #endif
00050 
00051 /************************ Cray MPP Intrinsic Simulator *********************/
00052 
00053 /* Simulate MPP library intrinsics if this module is loaded */
00054 
00055 #include "arith.internal.h"
00056 #include "int64.h"
00057 
00058 #if !defined(__mips)
00059 
00060 int ar_rounding_modes = 1<<AR_ROUND_NEAREST;
00061 int ar_underflow_modes = 1<<AR_UNDERFLOW_TO_PLUS_ZERO;
00062 
00063 extern char AR_libmv2[];
00064 extern char AR_version[];
00065 
00066 #define IEEE_FLOAT_32           (UNROUNDED_TYPE(AR_Float_IEEE_NR_32))
00067 #define IEEE_FLOAT_64           (UNROUNDED_TYPE(AR_Float_IEEE_NR_64))
00068 #define IEEE_FLOAT_128          (UNROUNDED_TYPE(AR_Float_IEEE_NR_128))
00069 #define IEEE_COMPLEX_32         (UNROUNDED_TYPE(AR_Complex_IEEE_NR_32))
00070 #define IEEE_COMPLEX_64         (UNROUNDED_TYPE(AR_Complex_IEEE_NR_64))
00071 #define IEEE_COMPLEX_128        (UNROUNDED_TYPE(AR_Complex_IEEE_NR_128))
00072 
00073 #define T3D             10                              /* T3D primary machine type */
00074 #define T3E             12                              /* T3E primary machine type */
00075 
00076 static int ar_sim_version = 0;  /* Version of interface with data file */
00077 static int ar_mach_type = T3D;  /* PMT of arith data file */
00078 
00079 static AR_TYPE integer_64               = AR_Int_64_S;
00080 static AR_TYPE ieee_float_32    = (AR_TYPE) IEEE_FLOAT_32;
00081 static AR_TYPE ieee_float_64    = (AR_TYPE) IEEE_FLOAT_64;
00082 
00083 #define NOINTRIN        1       /* Unknown/unsupported intrinsic name */
00084 #define ARITHERR        2       /* Arithmetic error detected by intrinsic */
00085 #define EXTERROR        3       /* Unsupported external called by intrinsic */
00086 #define SETERRNO        4       /* Set errno = ERANGE */
00087 #define IFACEERR        5       /* Unsupported simulation interface */
00088 #define HOSTEXT         6       /* Call host system external */
00089 #define BADINSTR        7       /* Unsupported instructions in intrinsic */
00090 
00091 #define MPP_STACK_SIZE  2048    /* # words to allocate for stack/heap space */
00092 #define MPP_DSIB_SIZE   6               /* # words to allocate for DSIB space */
00093 #define MPP_MAX_ARGS    8               /* Max number args allowed to any routine */
00094 
00095 static unsigned char*   mpp_intrin=NULL;
00096 static unsigned char*   code=NULL;
00097 static unsigned char*   data=NULL;
00098 static unsigned char*   stack=NULL;
00099 
00100 static int D_roundmode = -1;    /* Dynamic rounding mode */
00101 
00102 static AR_TYPE  D_float_32;
00103 static AR_TYPE  D_float_64;
00104 static AR_TYPE  D_float_128;
00105 static AR_TYPE  D_complex_64;
00106 static AR_TYPE  D_complex_128;
00107 
00108 /* Simulated Alpha integer and floating registers */
00109 
00110 static AR_INT_64        R[32];          /* Integer registers */
00111 static AR_INT_64        F[32];          /* Floating registers */
00112 
00113 #ifdef DEBUG
00114 
00115 /* Disassembly variables */
00116 
00117 int     ar_disasm = 0;          /* Turns on disassembly for debugging */
00118 
00119 static char RN[32][5] = {
00120                         "v0",           /* r0 */        /* return value */
00121                         "t0",           /* r1 */        /* caller saved */
00122                         "t1",           /* r2 */
00123                         "t2",           /* r3 */
00124                         "t3",           /* r4 */
00125                         "t4",           /* r5 */
00126                         "t5",           /* r6 */
00127                         "t6",           /* r7 */
00128                         "t7",           /* r8 */
00129                         "s0",           /* r9 */        /* callee saved */
00130                         "s1",           /* r10 */
00131                         "s2",           /* r11 */
00132                         "s3",           /* r12 */
00133                         "s4",           /* r13 */
00134                         "s5",           /* r14 */
00135                         "fp",           /* r15 */       /* frame pointer */
00136                         "a0",           /* r16 */       /* argument registers */
00137                         "a1",           /* r17 */
00138                         "a2",           /* r18 */
00139                         "a3",           /* r19 */
00140                         "a4",           /* r20 */
00141                         "a5",           /* r21 */
00142                         "t8",           /* r22 */       /* caller saved */
00143                         "t9",           /* r23 */
00144                         "t10",          /* r24 */
00145                         "ci",           /* r25 */       /* call info register */
00146                         "ra",           /* r26 */       /* return address */
00147                         "t11",          /* r27 */       /* caller saved */
00148                         "t12",          /* r28 */
00149                         "t13",          /* r29 */
00150                         "sp",           /* r30 */       /* stack pointer */
00151                         "R31"           /* r31 */       /* wired to zero */
00152 };
00153 
00154 static char FN[32][6] = {
00155                         "fv0",          /* f0 */        /* return value - FP */
00156                         "fv1",          /* f1 */        /* Complex FP ret val */
00157                         "fs0",          /* f2 */        /* callee saved */
00158                         "fs1",          /* f3 */
00159                         "fs2",          /* f4 */
00160                         "fs3",          /* f5 */
00161                         "fs4",          /* f6 */
00162                         "fs5",          /* f7 */
00163                         "fs6",          /* f8 */
00164                         "fs7",          /* f9 */
00165                         "ft0",          /* f10 */       /* caller saved */
00166                         "ft1",          /* f11 */
00167                         "ft2",          /* f12 */
00168                         "ft3",          /* f13 */
00169                         "ft4",          /* f14 */
00170                         "ft5",          /* f15 */
00171                         "fa0",          /* f16 */       /* argument registers */
00172                         "fa1",          /* f17 */
00173                         "fa2",          /* f18 */
00174                         "fa3",          /* f19 */
00175                         "fa4",          /* f20 */
00176                         "fa5",          /* f21 */
00177                         "ft6",          /* f22 */       /* caller saved */
00178                         "ft7",          /* f23 */
00179                         "ft8",          /* f24 */
00180                         "ft9",          /* f25 */
00181                         "ft10",         /* f26 */
00182                         "ft11",         /* f27 */
00183                         "ft12",         /* f28 */
00184                         "ft13",         /* f29 */
00185                         "ft14",         /* f30 */
00186                         "F31"           /* f31 */       /* wired to fp zero */
00187 };
00188 
00189 #define DISASM0(fmt)            if(ar_disasm) fprintf(stderr,fmt)
00190 #define DISASM1(fmt,x)          if(ar_disasm) fprintf(stderr,fmt,x)
00191 #define DISASM2(fmt,x,y)        if(ar_disasm) fprintf(stderr,fmt,x,y)
00192 #define DISASM3(fmt,x,y,z)      if(ar_disasm) fprintf(stderr,fmt,x,y,z)
00193 #define DISASM4(fmt,x,y,z,v)    if(ar_disasm) fprintf(stderr,fmt,x,y,z,v)
00194 #define DISASM5(fmt,x,y,z,v,w)  if(ar_disasm) fprintf(stderr,fmt,x,y,z,v,w)
00195 
00196 #else
00197 
00198 #define DISASM0(fmt)
00199 #define DISASM1(fmt,x)
00200 #define DISASM2(fmt,x,y)
00201 #define DISASM3(fmt,x,y,z)
00202 #define DISASM4(fmt,x,y,z,v)
00203 #define DISASM5(fmt,x,y,z,v,w)
00204 
00205 #endif
00206 
00207 /* Define register names used in simulation interfaces */
00208 
00209 #define v0      0
00210 #define t1      2
00211 #define s0      9
00212 #define fp      15
00213 #define a0      16
00214 #define a1      17
00215 #define a2      18
00216 #define a3      19
00217 #define a4      20
00218 #define a5      21
00219 #define ci      25
00220 #define ret     26
00221 #define sp      30
00222 #define zero    31
00223 
00224 #define fv0     0
00225 #define fv1     1
00226 #define fa0     16
00227 #define fzero   31
00228 
00229 #define MAX_EXT_ADDRS   16              /* Max # of EXT addresses passed */
00230 
00231 static AR_HOST_SINT64   numargs = 0;
00232 
00233 static int      n_external_addresses = 1;       /* Must be > 0 to be non-NULL */
00234 
00235 /*
00236  * Segment identifiers for the mpp.  They are set in open_intrinsics_file.
00237  */
00238 static unsigned code_segment_id;
00239 static unsigned data_segment_id;
00240 static unsigned stack_segment_id;
00241 
00242 /*
00243  * Segment types as defined in the aout_mpp.h include file.
00244  */
00245 typedef enum {
00246         SEGT_DATA = 0,
00247         SEGT_TEXT = 1,          /* Only one segment can have this type  */
00248         SEGT_REGISTERS = 2,
00249         SEGT_STACK = 3,         /* Only one segment can have this type  */
00250         SEGT_EREGISTERS = 4,
00251         SEGT_BESUS = 5
00252 } SegTypes;
00253  
00254 static char*    external_address[MAX_EXT_ADDRS];
00255 static long     external_length[MAX_EXT_ADDRS];
00256 
00257 typedef union {
00258         AR_INT_64 ari64;
00259         long l64;
00260 } i64_union;
00261 
00262 
00263 /*
00264  * Local routines.
00265  */
00266 static int  call_host_external(char* func);
00267 static void     open_intrinsics_file(void);
00268 static void     load_mpp_word(AR_INT_64 *result, long segment, long offset);
00269 static void     store_mpp_word(long segment, long offset, AR_INT_64 *result);
00270 
00271 
00272 int
00273 ar_clear_sim_state(AR_TYPE resulttype)
00274 {
00275 
00276 #ifdef DEBUG
00277         if (getenv("AR_DISASM") != NULL) {
00278                 ar_disasm = 1;
00279         }
00280 #endif
00281 
00282         if(mpp_intrin == NULL)
00283                 open_intrinsics_file();
00284 
00285         if(AR_CLASS(resulttype) == AR_CLASS_FLOAT &&
00286            AR_FLOAT_FORMAT(resulttype) == AR_FLOAT_CRAY)
00287                 ar_internal_error(2018, __FILE__, __LINE__);
00288 
00289         numargs = 0;                            /* Clear # arguments counter */
00290         ZERO64(R[ci]);                          /* Clear call info reg for next time */
00291         n_external_addresses = 1;       /* Forget all external addresses */
00292 
00293         D_roundmode   = ar_float_ieee_round_nearest;    /* Default rounding mode */
00294         D_float_32    = (AR_TYPE) IEEE_FLOAT_32;
00295         D_float_64    = (AR_TYPE) IEEE_FLOAT_64;
00296         D_float_128   = (AR_TYPE) IEEE_FLOAT_128;
00297         D_complex_64  = (AR_TYPE) IEEE_COMPLEX_64;
00298         D_complex_128 = (AR_TYPE) IEEE_COMPLEX_128;
00299 
00300         return AR_STAT_OK;
00301 }
00302 
00303 int
00304 ar_ext_address(AR_INT_64* intaddr, const char* extaddr, int length)
00305 {
00306         if(n_external_addresses == code_segment_id)
00307                 external_address[n_external_addresses++] = NULL;
00308 
00309         if(n_external_addresses == data_segment_id)
00310                 external_address[n_external_addresses++] = NULL;
00311 
00312         if(n_external_addresses == stack_segment_id)
00313                 external_address[n_external_addresses++] = NULL;
00314 
00315         intaddr[0].part1 = intaddr[0].part3 = intaddr[0].part4 = 0;
00316         intaddr[0].part2 = n_external_addresses;
00317 
00318         if(n_external_addresses >= MAX_EXT_ADDRS)
00319                 return AR_STAT_UNDEFINED;
00320 
00321         external_address[n_external_addresses] = (char*)extaddr;
00322         external_length[n_external_addresses++] = length;
00323 
00324         return AR_STAT_OK;
00325 }
00326 
00327 int
00328 ar_pass_arg_address(const ar_data* arg, const AR_TYPE* argtype)
00329 {
00330         int     iarg;
00331         int     arg_offset;
00332         int     arg_value_offset;
00333 
00334         numargs++;
00335         iarg = R[ci].part4>>8;          /* Current R[ci] has arg word index */
00336         R[ci].part4 += (1<<8);          /* Increment number of arguments */
00337 
00338         if(iarg >= MPP_MAX_ARGS)        /* Test for unsupported # of args */
00339                 ar_internal_error(2014, __FILE__, __LINE__);
00340 
00341         /* Call-by-address must 1) copy the value of the argument into
00342          * the address space known to the simulator and 2) store the address
00343          * of this copied value into the argument list.  5*MPP_MAX_ARGS words
00344          * are assumed to exist beyond the base of the stack for this purpose.
00345          * These words emulate the argument setup at the top of a caller's
00346          * stack frame on an MPP system.  The first MPP_MAX_ARGS are used to
00347          * store arguments that are not passed in registers.  Then 4 words are
00348          * available to store the value of each argument.
00349          */
00350 
00351         /*
00352          * Handle special case of a NULL pointer (no value).  If not NULL,
00353          * Compute address of argument value (to be copied in switch below).
00354          */
00355 
00356         if(arg == NULL)
00357                 ZERO64(R[s0]);
00358         else {
00359                 arg_value_offset = (MPP_STACK_SIZE + MPP_MAX_ARGS + (iarg * 4)) * 8;
00360                 R[s0].part1 = 0;
00361                 R[s0].part2 = stack_segment_id;
00362                 R[s0].part3 = (arg_value_offset>>16);
00363                 R[s0].part4 = arg_value_offset&0xffff;
00364         }
00365 
00366         /*
00367          * If argument 1 through 6, store address into argument register.
00368          * Otherwise, store it in the stack extension of the argument list.
00369          */
00370         
00371         if(iarg < 6) {
00372                 memcpy(&R[a0+iarg], &R[s0], 8);
00373                 R[ci].part4++;          /* Increment # of register args */
00374         }
00375         else {
00376                 arg_offset = MPP_STACK_SIZE + iarg;
00377                 store_mpp_word(stack_segment_id, arg_offset, &R[s0]);
00378         }
00379 
00380         /* Define rounding for instructions with dynamic (/D) rounding mode */
00381 
00382         if(AR_CLASS(*argtype) == AR_CLASS_FLOAT) {
00383                 D_roundmode   = ROUND_MODE(*argtype);
00384                 D_float_32    = (AR_TYPE) (IEEE_FLOAT_32    | (D_roundmode<<3));
00385                 D_float_64    = (AR_TYPE) (IEEE_FLOAT_64    | (D_roundmode<<3));
00386                 D_float_128   = (AR_TYPE) (IEEE_FLOAT_128   | (D_roundmode<<3));
00387                 D_complex_64  = (AR_TYPE) (IEEE_COMPLEX_64  | (D_roundmode<<3));
00388                 D_complex_128 = (AR_TYPE) (IEEE_COMPLEX_128 | (D_roundmode<<3));
00389         }
00390 
00391         if(arg == NULL)                 /* If no value, simply return */
00392                 return AR_STAT_OK;
00393 
00394         /* Copy the value of the argument to stack slot reserved for it */
00395 
00396         switch (UNROUNDED_TYPE(*argtype)) {
00397 
00398         case IEEE_FLOAT_32:
00399                 memcpy(&stack[arg_value_offset], (char*)(arg)+4, 4);
00400                 break;
00401 
00402         case IEEE_FLOAT_64:
00403         case IEEE_COMPLEX_32:
00404                 memcpy(&stack[arg_value_offset], (char*)(arg), 8);
00405                 break;
00406 
00407         case IEEE_FLOAT_128:
00408         case IEEE_COMPLEX_64:
00409                 memcpy(&stack[arg_value_offset], (char*)(arg), 16);
00410                 break;
00411 
00412 
00413         case AR_Int_32_S:
00414                 memcpy(&stack[arg_value_offset], (char*)(arg)+4, 4);
00415                 break;
00416 
00417         case IEEE_COMPLEX_128:
00418                 memcpy(&stack[arg_value_offset], (char*)(arg), 32);
00419                 break;
00420 
00421         default:
00422                 switch (*argtype) {
00423 
00424                 case AR_Int_32_S:
00425                         memcpy(&stack[arg_value_offset], (char*)(arg)+4, 4);
00426                         break;
00427 
00428                 case AR_Logical:
00429                         if(arg->ar_i64.part1 || arg->ar_i64.part2 ||
00430                            arg->ar_i64.part3 || arg->ar_i64.part4)
00431                                 memcpy(&stack[arg_value_offset], (char*)&AR_const_true, 8);
00432                         else
00433                                 memcpy(&stack[arg_value_offset], (char*)&AR_const_false, 8);
00434                         break;
00435 
00436                 case AR_Int_46_S:
00437                 case AR_Int_64_S:
00438                         memcpy(&stack[arg_value_offset], (char*)(arg), 8);
00439                         break;
00440 
00441                 default:
00442                         return AR_STAT_INVALID_TYPE;
00443                 }
00444         }
00445 
00446         return AR_STAT_OK;
00447 }
00448 
00449 int
00450 ar_pass_ext_address(AR_INT_64 *extdesc, const char *addr, int nwords)
00451 {
00452         int     iarg;
00453         int     arg_offset;
00454         int     arg_value_offset;
00455 
00456         int     status;
00457 
00458         numargs++;
00459         iarg = R[ci].part4>>8;          /* Current R[ci] has arg word index */
00460         R[ci].part4 += (1<<8);          /* Increment number of arguments */
00461 
00462         if(iarg >= MPP_MAX_ARGS)        /* Test for unsupported # of args */
00463                 ar_internal_error(2014, __FILE__, __LINE__);
00464 
00465         /* Passing an external address must 1) obtain an external address
00466          * descriptor for the address (from ar_ext_address) and 2) store this
00467          * descriptor into the argument list.
00468          */
00469 
00470         /*
00471          * Handle special case of a NULL pointer (no value).  If not NULL,
00472          * Compute address of argument value (to be copied in switch below).
00473          */
00474 
00475         if(addr == NULL)
00476                 ZERO64(R[s0]);
00477         else {
00478                 status = ar_ext_address(&R[s0], addr, nwords);
00479                 if(IS_ERROR_STATUS(status))
00480                         return status;
00481         }
00482 
00483         /*
00484          * If argument 1 through 6, store address into argument register.
00485          * Otherwise, store it in the stack extension of the argument list.
00486          */
00487         
00488         if(iarg < 6) {
00489                 memcpy(&R[a0+iarg], &R[s0], 8);
00490                 R[ci].part4++;          /* Increment # of register args */
00491         }
00492         else {
00493                 arg_offset = MPP_STACK_SIZE + iarg;
00494                 store_mpp_word(stack_segment_id, arg_offset, &R[s0]);
00495         }
00496 
00497         if(extdesc != NULL) {
00498                 R[s0].part4 = 3;        /* Pass back word-to-addr shift count */
00499                 memcpy(extdesc, &R[s0], 8);
00500         }
00501 
00502         return AR_STAT_OK;
00503 }
00504 
00505 int
00506 ar_pass_fcd_address(const char* str, long lenstr)
00507 {
00508         int     iarg;
00509         int     arg_offset;
00510         int     arg_value_offset;
00511 
00512         int     status;
00513 
00514         long    nbits;
00515 
00516         numargs++;
00517         iarg = R[ci].part4>>8;          /* Current R[ci] has arg word index */
00518         R[ci].part4 += (2<<8);          /* Increment number of arg words */
00519 
00520         if(iarg >= MPP_MAX_ARGS)        /* Test for unsupported # of args */
00521                 ar_internal_error(2014, __FILE__, __LINE__);
00522 
00523         if(str == NULL)
00524                 return AR_STAT_UNDEFINED;
00525 
00526         /* Get external address descriptor and store in first fcd word */
00527         nbits = lenstr<<3;
00528         status = ar_ext_address(&R[s0], str, (nbits+63)>>6);
00529         if(IS_ERROR_STATUS(status))
00530                 return status;
00531 
00532         /* If argument 1 through 6, store 1st fcd word into argument register.
00533          * Otherwise, store it in the stack extension of the argument list.
00534          */
00535         
00536         if(iarg < 6) {
00537                 memcpy(&R[a0+iarg], &R[s0], 8);
00538                 R[ci].part4++;          /* Increment # of register args */
00539         }
00540         else {
00541                 arg_offset = MPP_STACK_SIZE + iarg;
00542                 store_mpp_word(stack_segment_id, arg_offset, &R[s0]);
00543         }
00544 
00545         /* Store length in second fcd word */
00546         R[s0].part1 = R[s0].part2 = 0;
00547         if(ar_mach_type == T3D) {
00548                 R[s0].part3 = nbits>>16;                /* Length in bits */
00549                 R[s0].part4 = nbits&0xffff;
00550         }
00551         else {
00552                 R[s0].part3 = lenstr>>16;               /* Length in bytes */
00553                 R[s0].part4 = lenstr&0xffff;
00554         }
00555 
00556         /* If argument 1 through 6, store 2nd fcd word into argument register.
00557          * Otherwise, store it in the stack extension of the argument list.
00558          */
00559         
00560         if((iarg+1) < 6) {
00561                 memcpy(&R[a0+(iarg+1)], &R[s0], 8);
00562                 R[ci].part4++;          /* Increment # of register args */
00563         }
00564         else {
00565                 arg_offset = MPP_STACK_SIZE + (iarg + 1);
00566                 store_mpp_word(stack_segment_id, arg_offset, &R[s0]);
00567         }
00568 
00569         return AR_STAT_OK;
00570 }
00571 
00572 int
00573 ar_pass_arg_value(const ar_data* arg, const AR_TYPE* argtype)
00574 {
00575         int             i;
00576         int             iarg;
00577         int             arg_offset;
00578         AR_IEEE_32      i32;            /* Only used for IEEE_COMPLEX_32 */
00579         int             status;
00580 
00581         numargs++;
00582         iarg = R[ci].part4>>8;          /* Current R[ci] has arg word index */
00583         R[ci].part4 += (1<<8);          /* Increment number of arg words */
00584 
00585         if(iarg >= MPP_MAX_ARGS)        /* Test for unsupported # of args */
00586                 ar_internal_error(2014, __FILE__, __LINE__);
00587 
00588         /* Call-by-value must copy the value of the argument into either an
00589          * argument register or into the stack extension of the argument list.
00590          * The first MPP_MAX_ARGS words beyond the stack base are used as the
00591          * extension of the argument list.  These words emulate the argument
00592          * setup at the top of an MPP caller's stack frame.
00593          */
00594 
00595         if(AR_CLASS(*argtype) == AR_CLASS_FLOAT) {
00596                 D_roundmode   = ROUND_MODE(*argtype);
00597                 D_float_32    = (AR_TYPE) (IEEE_FLOAT_32    | (D_roundmode<<3));
00598                 D_float_64    = (AR_TYPE) (IEEE_FLOAT_64    | (D_roundmode<<3));
00599                 D_float_128   = (AR_TYPE) (IEEE_FLOAT_128   | (D_roundmode<<3));
00600                 D_complex_64  = (AR_TYPE) (IEEE_COMPLEX_64  | (D_roundmode<<3));
00601                 D_complex_128 = (AR_TYPE) (IEEE_COMPLEX_128 | (D_roundmode<<3));
00602         }
00603 
00604         if(arg == NULL)                 /* Test for NULL pointer (no value) */
00605                 return AR_STAT_UNDEFINED;
00606 
00607         /*
00608          * If argument 1 through 6, store value into argument register.
00609          * Otherwise, store it in the stack extension of the argument list.
00610          */
00611 
00612         switch (UNROUNDED_TYPE(*argtype)) {
00613 
00614         case IEEE_FLOAT_32:
00615                 if(iarg >= 6) {
00616                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00617                         return ar_convert_to_float((ar_data*)&stack[arg_offset],
00618                                                                            &ieee_float_64,
00619                                                                            arg, &ieee_float_32);
00620                 }
00621                 if(iarg == 5)
00622                         R[ci].part4 |= 7;
00623                 else
00624                         R[ci].part4 = (R[ci].part4|(1<<(7-iarg))) + 1;
00625                 return ar_convert_to_float((ar_data*)&F[fa0+iarg],
00626                                                                    &ieee_float_64,
00627                                                                    arg, &ieee_float_32);
00628 
00629         case IEEE_FLOAT_64:
00630                 if(iarg >= 6) {
00631                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00632                         memcpy(&stack[arg_offset], arg, 8);
00633                         return AR_STAT_OK;
00634                 }
00635                 if(iarg == 5)
00636                         R[ci].part4 |= 7;
00637                 else
00638                         R[ci].part4 = (R[ci].part4|(1<<(7-iarg))) + 1;
00639                 memcpy(&F[fa0+iarg], arg, 8);
00640                 return AR_STAT_OK;
00641 
00642         case IEEE_FLOAT_128:
00643         case IEEE_COMPLEX_64:
00644                 R[ci].part4 += (1<<8);  /* Increment number of arg words */
00645                 for(i=0; i<2; i++) {
00646                         if((iarg+i) >= 6) {
00647                                 if((iarg+i) >= MPP_MAX_ARGS)
00648                                     ar_internal_error(2014, __FILE__, __LINE__);
00649                                 arg_offset = (MPP_STACK_SIZE + (iarg + i)) * 8;
00650                                 memcpy(&stack[arg_offset], (AR_INT_64*)arg+i, 8);
00651                         }
00652                         else {
00653                                 if((iarg+i) == 5)
00654                                         R[ci].part4 |= 7;
00655                                 else
00656                                         R[ci].part4 = (R[ci].part4|(1<<(7-(iarg+i)))) + 1;
00657                                 memcpy(&F[fa0+(iarg+i)], (AR_INT_64*)arg+i, 8);
00658                         }
00659                 }
00660                 return AR_STAT_OK;
00661 
00662         case IEEE_COMPLEX_32:
00663                 R[ci].part4 += (1<<8);  /* Increment number of arg words */
00664                 status = AR_STAT_OK;
00665                 if(iarg >= (MPP_MAX_ARGS - 1))
00666                         ar_internal_error(2014, __FILE__, __LINE__);
00667 
00668                 i32.sign   = arg->ar_cplx_ieee32.rsign;
00669                 i32.expo   = arg->ar_cplx_ieee32.rexpo;
00670                 i32.coeff0 = arg->ar_cplx_ieee32.rcoeff0;
00671                 i32.coeff1 = arg->ar_cplx_ieee32.rcoeff1;
00672                 if(iarg >= 6) {
00673                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00674                         status |= ar_convert_to_float((ar_data*)&stack[arg_offset],
00675                                                                                   &ieee_float_64,
00676                                                                                   &i32, &ieee_float_32);
00677                 }
00678                 else {
00679                         if(iarg == 5)
00680                                 R[ci].part4 |= 7;
00681                         else
00682                                 R[ci].part4 = (R[ci].part4|(1<<(7-iarg))) + 1;
00683                         status |= ar_convert_to_float((ar_data*)&F[fa0+iarg],
00684                                                                                   &ieee_float_64,
00685                                                                                   &i32, &ieee_float_32);
00686                 }
00687 
00688                 i32.sign   = arg->ar_cplx_ieee32.isign;
00689                 i32.expo   = arg->ar_cplx_ieee32.iexpo;
00690                 i32.coeff0 = arg->ar_cplx_ieee32.icoeff0;
00691                 i32.coeff1 = arg->ar_cplx_ieee32.icoeff1;
00692                 iarg++;
00693                 if(iarg >= 6) {
00694                         if(iarg >= MPP_MAX_ARGS)
00695                             ar_internal_error(2014, __FILE__, __LINE__);
00696                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00697                         status |= ar_convert_to_float((ar_data*)&stack[arg_offset],
00698                                                                                   &ieee_float_64,
00699                                                                                   &i32, &ieee_float_32);
00700                 }
00701                 else {
00702                         if(iarg == 5)
00703                                 R[ci].part4 |= 7;
00704                         else
00705                                 R[ci].part4 = (R[ci].part4|(1<<(7-iarg))) + 1;
00706                         status |= ar_convert_to_float((ar_data*)&F[fa0+iarg],
00707                                                                                   &ieee_float_64,
00708                                                                                   &i32, &ieee_float_32);
00709                 }
00710 
00711                 return status;
00712 
00713         case IEEE_COMPLEX_128:
00714                 R[ci].part4 += (1<<8);  /* Increment number of arg words */
00715                 for(i=0; i<4; i++) {
00716                         if((iarg+i) >= 6) {
00717                                 if((iarg+i) >= MPP_MAX_ARGS)
00718                                     ar_internal_error(2014, __FILE__, __LINE__);
00719                                 arg_offset = (MPP_STACK_SIZE + (iarg + i)) * 8;
00720                                 memcpy(&stack[arg_offset], (AR_INT_64*)arg+i, 8);
00721                         }
00722                         else {
00723                                 if((iarg+i) == 5)
00724                                         R[ci].part4 |= 7;
00725                                 else
00726                                         R[ci].part4 = (R[ci].part4|(1<<(7-(iarg+i)))) + 1;
00727                                 memcpy(&F[fa0+(iarg+i)], (AR_INT_64*)arg+i, 8);
00728                         }
00729                 }
00730                 return AR_STAT_OK;
00731 
00732         default:
00733                 switch (*argtype) {
00734 
00735                 case AR_Int_32_S:
00736                 case AR_Int_46_S:
00737                 case AR_Int_64_S:
00738 
00739                         if(iarg >= 6) {
00740                                 arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00741                                 return ar_convert_to_integral((ar_data*)&stack[arg_offset],
00742                                                                                           &integer_64,
00743                                                                                           arg, argtype);
00744                         }
00745                         R[ci].part4++;
00746                         return ar_convert_to_integral((ar_data*)&R[a0+iarg],
00747                                                                                   &integer_64,
00748                                                                                   arg, argtype);
00749 
00750                 case AR_Logical:
00751                         if(arg->ar_i64.part1 || arg->ar_i64.part2 ||
00752                            arg->ar_i64.part3 || arg->ar_i64.part4)
00753                                 if(iarg >= 6) {
00754                                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00755                                         memcpy(&stack[arg_offset],
00756                                         (char*)&AR_const_true, 8);
00757                                 }
00758                                 else {
00759                                         R[ci].part4++;
00760                                         memcpy(&R[a0+iarg],
00761                                         (char*)&AR_const_true, 8);
00762                                 }
00763                         else
00764                                 if(iarg >= 6) {
00765                                         arg_offset = (MPP_STACK_SIZE + iarg) * 8;
00766                                         memcpy(&stack[arg_offset],
00767                                         (char*)&AR_const_false, 8);
00768                                 }
00769                                 else {
00770                                         R[ci].part4++;
00771                                         memcpy(&R[a0+iarg],
00772                                         (char*)&AR_const_false, 8);
00773                                 }
00774                         break;
00775 
00776                 default:
00777                         return AR_STAT_INVALID_TYPE;
00778                 }
00779         }
00780 }
00781 
00782 
00783 int
00784 ar_put_real_address(AR_INT_64* extdesc)
00785 {
00786         int     segment = extdesc->part2 & 0xff;
00787 
00788         if(segment >= n_external_addresses)
00789                 return AR_STAT_UNDEFINED;
00790 
00791 #if _CRAY
00792         extdesc->part1 = (((long long)external_address[segment]) >> 48) & 0xffff;
00793         extdesc->part2 = (((long long)external_address[segment]) >> 32) & 0xffff;
00794         extdesc->part3 = (((long long)external_address[segment]) >> 16) & 0xffff;
00795         extdesc->part4 =  ((long long)external_address[segment])        & 0xffff;
00796 #else
00797         extdesc->part1 = 0;
00798         extdesc->part2 = 0;
00799         extdesc->part3 = (((long)external_address[segment]) >> 16) & 0xffff;
00800         extdesc->part4 =  ((long)external_address[segment])        & 0xffff;
00801 #endif
00802 
00803         return AR_STAT_OK;      
00804 }
00805 
00806 
00807 int
00808 ar_get_function_value(ar_data *result, AR_TYPE *resulttype)
00809 {
00810         int     status;
00811 
00812         /*
00813          * Return function value in result if register conventions known
00814          * for the result type.  Otherwise, the function value is assumed
00815          * to be returned through memory and the caller must retrieve it.
00816          * Use ar_convert_to_* to set ZERO and NEGATIVE status flags.  Note
00817          * that error flags such as AR_STAT_OVERFLOW are cleared (these
00818          * would have been returned by the intrinsic function simulation
00819          * performed by ar_sim if run-time evaluation would have produced
00820          * them).  So effectively, this routine only returns the bit
00821          * pattern of the result plus zero or negative status.
00822          */
00823 
00824         switch (AR_CLASS(*resulttype)) {
00825 
00826         case AR_CLASS_INT:
00827 
00828                 status = ar_convert_to_integral(result, resulttype,
00829                                   (ar_data*)&R[v0], &integer_64);
00830                 break;
00831 
00832         case AR_CLASS_FLOAT:
00833 
00834                 switch(UNROUNDED_TYPE(*resulttype)) {
00835 
00836                 case IEEE_FLOAT_32:
00837                 case IEEE_FLOAT_64:
00838                         status = ar_convert_to_float(result, resulttype,
00839                                           (ar_data*)&F[fv0], &D_float_64);
00840                         break;
00841 
00842                 case IEEE_FLOAT_128:
00843                         status = ar_convert_to_float(result, resulttype,
00844                                           (ar_data*)&F[fv0], &D_float_128);
00845                         break;
00846 
00847                 case IEEE_COMPLEX_32:
00848                 case IEEE_COMPLEX_64:
00849                         status = ar_convert_to_complex(result, resulttype,
00850                                           (ar_data*)&F[fv0], &D_complex_64);
00851                         break;
00852 
00853                 case IEEE_COMPLEX_128:
00854                         status = ar_convert_to_complex(result, resulttype,
00855                                           (ar_data*)&F[fv0], &D_complex_128);
00856                         break;
00857 
00858                 default:
00859                         return AR_STAT_INVALID_TYPE;
00860                 }
00861                 break;
00862 
00863         default:
00864                 return AR_STAT_INVALID_TYPE;
00865         }
00866         return status &~ AR_ERROR_STATUS;
00867 }
00868 
00869 static int
00870 call_host_external(char* func)
00871 {
00872         int             status = AR_STAT_UNDEFINED;
00873 
00874         if (strncmp(func, "malloc", 6) == 0) {
00875                 long    length;
00876                 char    *ptr1;
00877 
00878                 length = (R[a0].part3<<16) | R[a0].part4;
00879                 ptr1   = malloc(length);
00880                 status = ar_ext_address(&R[v0], (const char*)ptr1, (length+7)>>3);
00881         }
00882 
00883         return status;
00884 }
00885 
00886 int
00887 ar_sim(char* intrinsic)
00888 {
00889         char*   name;
00890         char*   str;
00891 
00892         int     i,n;
00893         int     disp;
00894         int     sign;
00895 
00896         long    pc;
00897         unsigned long p1,p2;
00898         int     op;
00899         int     ra,rb,rc;
00900         int     func;
00901         long    rtc, rtcpc;
00902         i64_union iu64;
00903 
00904         long    offset;
00905         long    value;
00906         int     status;
00907 
00908         AR_INT_64       int64;
00909         AR_INT_64       reg64;
00910 
00911         AR_IEEE_64      *rr, *oa, *ob;
00912 
00913         AR_TYPE         ar_type;
00914 
00915     static AR_HOST_UINT64    SSIB[7] = {
00916                                                                                 /* Various information           */
00917         (((AR_HOST_UINT64) 0x00000002) << 32) |
00918                  ((AR_HOST_UINT64) 0x00080528),
00919 
00920         0,                              /* Saved_R, saved_F              */
00921         0,                              /* Entry point address           */
00922         0,                              /* Language specific information */
00923         0,                              /* Machine specific information  */
00924                                                                                 /* "ARITH" (my name)             */
00925                 (((AR_HOST_UINT64) 0x41524954) << 32) |
00926                  ((AR_HOST_UINT64) 0x48000000),
00927         0                                                               /* Call information word         */
00928         };
00929 
00930         /* Set up initial Alpha stack and register values */
00931 
00932         /*
00933          * The following test verifies that at least one argument
00934          * has been passed via ar_pass_arg_{value|address}.  This in turn
00935          * guarantees that the arith data file has been opened and read into
00936          * memory so that the simulation is ready to begin.
00937          */
00938 
00939         if(R[ci].part4 == 0)
00940                 ar_internal_error(2014, __FILE__, __LINE__);
00941 
00942         /*
00943          * Define a simulated stack and set up a DSIB with the call information
00944          * (CI) word when simulating for a T3E.  For the T3D, the CI word is
00945          * currently in R[ci].  For the T3E, this must be modified somewhat
00946          * and stored in the simulated SSIB.  Additionally, the SSIB index
00947          * of the CI word must be put into R[ci], and simulated SSIB address
00948          * must be stored in the simulated DSIB.  The simulated DSIB goes
00949          * after the MPP_MAX_ARGS*5 words of simulated callee stack space
00950          * in the stack area.
00951          */
00952 
00953         R[sp].part1 = R[fp].part1 = 0;
00954         R[sp].part2 = R[fp].part2 = stack_segment_id;
00955 
00956         R[sp].part3 = (MPP_STACK_SIZE*8)>>16;
00957         R[sp].part4 = (MPP_STACK_SIZE*8)&0xffff;
00958 
00959         if(ar_mach_type == T3D) {
00960                 R[fp].part3 = (MPP_STACK_SIZE*8)>>16;
00961                 R[fp].part4 = (MPP_STACK_SIZE*8)&0xffff;
00962         }
00963         else {
00964         AR_INT_64       SSIB_ia;        /* SSIB internal address */
00965 
00966 #               define T3E_DSIB_LOC    (MPP_STACK_SIZE + (MPP_MAX_ARGS * 5))
00967 
00968                 R[fp].part3 = ((T3E_DSIB_LOC + MPP_DSIB_SIZE) * 8) >> 16;
00969                 R[fp].part4 = ((T3E_DSIB_LOC + MPP_DSIB_SIZE) * 8)  & 0xffff;
00970 
00971                 SSIB[6] = (numargs << 52) |
00972                                   (((AR_HOST_UINT64) (R[ci].part4 >> 8)) << 32) |
00973                                   (R[ci].part4 & 0xff);
00974 
00975                 R[ci].part1 = R[ci].part2 = R[ci].part3 = 0;
00976                 R[ci].part4 = 6;
00977 
00978                 if (ar_ext_address(&SSIB_ia, (char*) &SSIB, (sizeof(SSIB) >> 3)) !=
00979                         AR_STAT_OK) {
00980                         ar_internal_error(2012, __FILE__, __LINE__);
00981                 }
00982                 store_mpp_word(stack_segment_id, (T3E_DSIB_LOC + 2), &SSIB_ia);
00983 
00984 #               undef T3E_DSIB_LOC
00985         }
00986 
00987         ZERO64(R[ret]);                         /* Force R[ret] = 0 */
00988 
00989         ZERO64(R[zero]);                        /* Force R31 = 0 */
00990         ZERO64(F[fzero]);                       /* Force F31 = 0. */
00991 
00992         /*
00993          * At this point all necessary registers (except pc) contain values
00994          * that correspond with being at the entry point of the called function.
00995          */
00996 
00997         /*
00998          * Pass my simulation interface identifier.  The logic within the
00999          * mpp simulation file (arith data file) can then validate and/or
01000          * translate to its interface.  This allows this routine and a
01001          * newer mpp simulation file to still function correctly.  In
01002          * practice, this permits older (archived?) products to still work
01003          * with a newer default arith data file.
01004          */
01005 
01006         R[s0].part1 = R[s0].part2 = R[s0].part3 = 0;
01007         R[s0].part4 = ar_sim_version;           /* Sim interface id */
01008 
01009         /*
01010          * Store LJ'd, zero-filled, uppercase intrinsic name into R[v0]
01011          * as part of the simulation interface with the mpp simulation file
01012          * (arith data file).  The simulation is assumed to begin (at pc=0)
01013          * with a lookup of this name followed by an unconditional branch to
01014          * the associated entry point when found.  The simulation continues
01015          * until either an error condition occurs or the pc becomes 0 again
01016          * corresponding to the 0 forced into the return address register
01017          * (R[ret]) above.
01018          */
01019 
01020         name = (char*)&R[v0];
01021         for(i=0; i<8 && isalnum(intrinsic[i]); i++)
01022           name[i] = toupper(intrinsic[i]);
01023         while(i < 8)
01024           name[i++] = 0;
01025 
01026         pc = 0;
01027         rtcpc = 0;
01028         status = AR_STAT_OK;
01029         while(status == AR_STAT_OK) {
01030 
01031           DISASM1("0x%6.6x\t", pc);
01032           if(pc&4) {
01033 #if _CRAY
01034             p1 = *(((unsigned long*)code)+(pc>>3)) >> 48;
01035             p2 = (*(((unsigned long*)code)+(pc>>3)) >> 32) & 0xffff;
01036 #else
01037             p1 = (code[pc-4]<<8) | code[pc-3];
01038             p2 = (code[pc-2]<<8) | code[pc-1];
01039 #endif
01040           }
01041           else {
01042 #if _CRAY
01043             p1 = (*(((unsigned long*)code)+(pc>>3)) >> 16) & 0xffff;
01044             p2 = *(((unsigned long*)code)+(pc>>3)) & 0xffff;
01045 #else
01046             p1 = (code[pc+4]<<8) | code[pc+5];
01047             p2 = (code[pc+6]<<8) | code[pc+7];
01048 #endif
01049           }
01050           pc += 4;
01051           op = p1>>10;
01052           ra = (p1>>5)&037;
01053           rb = p1&037;
01054           func = (p2>>5)&03777;
01055           rc = p2&037;
01056 
01057           switch(op) {
01058 
01059           case 0x00:
01060                 status = R[v0].part1 | R[v0].part2 | R[v0].part3 | R[v0].part4;
01061                 DISASM2("CALL_PAL(0x%7.7x)\t0x%4.4x\n", p1<<16 | p2, status);
01062                 switch (status) {
01063                 case IFACEERR:          /* Unsupported intrinsic interface */
01064                   ar_internal_error(2014, __FILE__, __LINE__);
01065                   status = AR_STAT_UNDEFINED;
01066                   break;
01067                 case NOINTRIN:          /* Unsupported intrinsic name */
01068                   str=(char*)&R[v0];
01069                   PRINTMSG(0, 2015, Internal, 0, __FILE__, __LINE__, intrinsic, "");
01070                   status = AR_STAT_UNDEFINED;
01071                   break;
01072                 case EXTERROR:          /* Unsupported EXT called by intrinsic */
01073                   ar_internal_error(2012, __FILE__, __LINE__);
01074                 case ARITHERR:          /* Error detected by libm routine */
01075                   status = AR_STAT_UNDEFINED;
01076                   break;
01077                 case SETERRNO:          /* Set errno = ERANGE */
01078                   errno = ERANGE;
01079                   status = AR_STAT_OVERFLOW;
01080                   pc = 0;
01081                   break;
01082                 case HOSTEXT:
01083                   status = call_host_external((char*)&R[t1]);
01084                   pc = ((R[ret].part3<<16)|R[ret].part4) &~ 3;
01085                   break;
01086                 default:
01087                   status = BADINSTR;
01088                 }
01089                 break;
01090 
01091           case 0x19:
01092           case 0x1b:
01093           case 0x1d:
01094           case 0x1e:
01095           case 0x1f:
01096                 status = BADINSTR;
01097                 DISASM2("CALL_PAL(0x%7.7x)\t0x%4.4x\n", p1<<16 | p2, status);
01098                 break;
01099 
01100           case 0x01:
01101           case 0x02:
01102           case 0x03:
01103           case 0x04:
01104           case 0x05:
01105           case 0x06:
01106           case 0x07:
01107           case 0x0a:
01108           case 0x0c:
01109           case 0x0d:
01110           case 0x0e:
01111           case 0x14:
01112           case 0x1c:
01113                 status = BADINSTR;
01114                 DISASM5("%x.%x.%x.%x.%x\n", op, ra, rb, func, rc);
01115                 break;
01116 
01117           case 0x08:
01118                 if(ra != zero) {
01119                   reg64.part4 = p2;
01120                   if(p2>>15)
01121                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
01122                   else
01123                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
01124                   ADD64(R[ra], reg64, R[rb]);
01125                 }
01126                 DISASM5("LDA\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
01127                         RN[ra], p2, RN[rb],
01128                         (R[ra].part1<<16) | R[ra].part2,
01129                         (R[ra].part3<<16) | R[ra].part4);
01130                 break;
01131 
01132           case 0x09:
01133                 if(ra != zero) {
01134                   reg64.part3 = p2;
01135                   reg64.part4 = 0;
01136                   if(p2>>15)
01137                     reg64.part1 = reg64.part2 = 0xffff;
01138                   else
01139                     reg64.part1 = reg64.part2 = 0;
01140                   ADD64(R[ra], reg64, R[rb]);
01141                 }
01142                 DISASM5("LDAH\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
01143                         RN[ra], p2, RN[rb],
01144                         (R[ra].part1<<16) | R[ra].part2,
01145                         (R[ra].part3<<16) | R[ra].part4);
01146                 break;
01147 
01148           case 0x0b:
01149                 if(ra != zero) {
01150                   reg64.part4 = p2;
01151                   if(p2>>15)
01152                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
01153                   else
01154                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
01155                   ADD64(reg64, reg64, R[rb]);
01156                   offset = ((reg64.part3<<16) | reg64.part4) >> 3;
01157                   load_mpp_word(&R[ra], reg64.part2&0xff, offset);
01158                 }
01159                 DISASM5("LDQ_U\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
01160                         RN[ra], p2, RN[rb],
01161                         (R[ra].part1<<16) | R[ra].part2,
01162                         (R[ra].part3<<16) | R[ra].part4);
01163                 break;
01164 
01165           case 0x0f:
01166                 reg64.part4 = p2;
01167                 if(p2>>15)
01168                   reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
01169                 else
01170                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
01171                 ADD64(reg64, reg64, R[rb]);
01172                 offset = ((reg64.part3<<16) | reg64.part4) >> 3;
01173                 store_mpp_word(reg64.part2&0xff, offset, &R[ra]);
01174                 DISASM3("STQ_U\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
01175                 break;
01176 
01177           case 0x10:
01178                 if(func&0x80) {
01179                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
01180                   reg64.part4 = (rb<<3)|(func>>8);
01181                 }
01182                 else
01183                   COPY64(reg64, R[rb]);
01184                 switch(func&0x7f) {
01185                 case 0x00:
01186                         DISASM0("ADDL\t");
01187                         ADD64(R[rc], R[ra], reg64);
01188                         if(R[rc].part3>>15)
01189                           R[rc].part1 = R[rc].part2 = 0xffff;
01190                         else
01191                           R[rc].part1 = R[rc].part2 = 0;
01192                         break;
01193                 case 0x02:
01194                         DISASM0("S4ADDL\t");
01195                         COPY64(int64, R[ra]);
01196                         SHLEFT64N(int64, 2);
01197                         ADD64(R[rc], int64, reg64);
01198                         if(R[rc].part3>>15)
01199                           R[rc].part1 = R[rc].part2 = 0xffff;
01200                         else
01201                           R[rc].part1 = R[rc].part2 = 0;
01202                         break;
01203                 case 0x09:
01204                         DISASM0("SUBL\t");
01205                         NEG64(reg64);
01206                         ADD64(R[rc], R[ra], reg64);
01207                         if(R[rc].part3>>15)
01208                           R[rc].part1 = R[rc].part2 = 0xffff;
01209                         else
01210                           R[rc].part1 = R[rc].part2 = 0;
01211                         break;
01212                 case 0x0b:
01213                         DISASM0("S4SUBL\t");
01214                         COPY64(int64, R[ra]);
01215                         SHLEFT64N(int64, 2);
01216                         NEG64(reg64);
01217                         ADD64(R[rc], int64, reg64);
01218                         if(R[rc].part3>>15)
01219                           R[rc].part1 = R[rc].part2 = 0xffff;
01220                         else
01221                           R[rc].part1 = R[rc].part2 = 0;
01222                         break;
01223                 case 0x0f:
01224                         DISASM0("CMPBGE\t");
01225                         value = 0;
01226                         if((R[ra].part1>>8) >= (reg64.part1>>8))
01227                           value |= 1<<7;
01228                         if((R[ra].part1&0xff) >= (reg64.part1&0xff))
01229                           value |= 1<<6;
01230                         if((R[ra].part2>>8) >= (reg64.part2>>8))
01231                           value |= 1<<5;
01232                         if((R[ra].part2&0xff) >= (reg64.part2&0xff))
01233                           value |= 1<<4;
01234                         if((R[ra].part3>>8) >= (reg64.part3>>8))
01235                           value |= 1<<3;
01236                         if((R[ra].part3&0xff) >= (reg64.part3&0xff))
01237                           value |= 1<<2;
01238                         if((R[ra].part4>>8) >= (reg64.part4>>8))
01239                           value |= 1<<1;
01240                         if((R[ra].part4&0xff) >= (reg64.part4&0xff))
01241                           value |= 1;
01242                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01243                         R[rc].part4 = value;
01244                         break;
01245                 case 0x12:
01246                         DISASM0("S8ADDL\t");
01247                         COPY64(int64, R[ra]);
01248                         SHLEFT64N(int64, 3);
01249                         ADD64(R[rc], int64, reg64);
01250                         if(R[rc].part3>>15)
01251                           R[rc].part1 = R[rc].part2 = 0xffff;
01252                         else
01253                           R[rc].part1 = R[rc].part2 = 0;
01254                         break;
01255                 case 0x1b:
01256                         DISASM0("S8SUBL\t");
01257                         COPY64(int64, R[ra]);
01258                         SHLEFT64N(int64, 3);
01259                         NEG64(reg64);
01260                         ADD64(R[rc], int64, reg64);
01261                         if(R[rc].part3>>15)
01262                           R[rc].part1 = R[rc].part2 = 0xffff;
01263                         else
01264                           R[rc].part1 = R[rc].part2 = 0;
01265                         break;
01266                 case 0x1d:
01267                         DISASM0("CMPULT\t");
01268                         value = 0;
01269                         if(R[ra].part1 < reg64.part1)
01270                                 value = 1;
01271                         else if(R[ra].part1 == reg64.part1)
01272                           if(R[ra].part2 < reg64.part2)
01273                                 value = 1;
01274                           else if(R[ra].part2 == reg64.part2)
01275                             if(R[ra].part3 < reg64.part3)
01276                                 value = 1;
01277                             else if(R[ra].part3 == reg64.part3)
01278                               if(R[ra].part4 < reg64.part4)
01279                                 value = 1;
01280                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01281                         R[rc].part4 = value;
01282                         break;
01283                 case 0x20:
01284                         DISASM0("ADDQ\t");
01285                         ADD64(R[rc], R[ra], reg64);
01286                         break;
01287                 case 0x22:
01288                         DISASM0("S4ADDQ\t");
01289                         COPY64(int64, R[ra]);
01290                         SHLEFT64N(int64, 2);
01291                         ADD64(R[rc], int64, reg64);
01292                         break;
01293                 case 0x29:
01294                         DISASM0("SUBQ\t");
01295                         NEG64(reg64);
01296                         ADD64(R[rc], R[ra], reg64);
01297                         break;
01298                 case 0x2b:
01299                         DISASM0("S4SUBQ\t");
01300                         COPY64(int64, R[ra]);
01301                         SHLEFT64N(int64, 2);
01302                         NEG64(reg64);
01303                         ADD64(R[rc], int64, reg64);
01304                         break;
01305                 case 0x2d:
01306                         DISASM0("CMPEQ\t");
01307                         value = 0;
01308                         if(R[ra].part1 == reg64.part1)
01309                           if(R[ra].part2 == reg64.part2)
01310                             if(R[ra].part3 == reg64.part3)
01311                               if(R[ra].part4 == reg64.part4)
01312                                 value = 1;
01313                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01314                         R[rc].part4 = value;
01315                         break;
01316                 case 0x32:
01317                         DISASM0("S8ADDQ\t");
01318                         COPY64(int64, R[ra]);
01319                         SHLEFT64N(int64, 3);
01320                         ADD64(R[rc], int64, reg64);
01321                         break;
01322                 case 0x3b:
01323                         DISASM0("S8SUBQ\t");
01324                         COPY64(int64, R[ra]);
01325                         SHLEFT64N(int64, 3);
01326                         NEG64(reg64);
01327                         ADD64(R[rc], int64, reg64);
01328                         break;
01329                 case 0x3d:
01330                         DISASM0("CMPULE\t");
01331                         value = 0;
01332                         if(R[ra].part1 < reg64.part1)
01333                                 value = 1;
01334                         else if(R[ra].part1 == reg64.part1)
01335                           if(R[ra].part2 < reg64.part2)
01336                                 value = 1;
01337                           else if(R[ra].part2 == reg64.part2)
01338                             if(R[ra].part3 < reg64.part3)
01339                                 value = 1;
01340                             else if(R[ra].part3 == reg64.part3)
01341                               if(R[ra].part4 <= reg64.part4)
01342                                 value = 1;
01343                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01344                         R[rc].part4 = value;
01345                         break;
01346                 case 0x4d:
01347                         DISASM0("CMPLT\t");
01348                         NEG64(reg64);
01349                         ADD64(reg64, R[ra], reg64);
01350                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01351                         R[rc].part4 = reg64.part1>>15;
01352                         break;
01353                 case 0x6d:
01354                         DISASM0("CMPLE\t");
01355                         NEG64(reg64);
01356                         ADD64(reg64, R[ra], reg64);
01357                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01358                         R[rc].part4 = reg64.part1>>15;
01359                         if(R[rc].part4 == 0)
01360                           if((reg64.part1|reg64.part2|reg64.part3|reg64.part4) == 0)
01361                             R[rc].part4 = 1;
01362                         break;
01363                 default:
01364                         status = BADINSTR;
01365                         DISASM5("%x.%x.%x.%x.%x\n", op, ra, rb, func, rc);
01366                 }
01367                 if(func&0x80) {
01368                     DISASM5("%s,0x%2.2x,%s\t0x%8.8x %8.8x\n",
01369                         RN[ra], (rb<<3)|(func>>8), RN[rc],
01370                         (R[rc].part1<<16) | R[rc].part2,
01371                         (R[rc].part3<<16) | R[rc].part4);
01372                 }
01373                 else {
01374                     DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
01375                         RN[ra], RN[rb], RN[rc],
01376                         (R[rc].part1<<16) | R[rc].part2,
01377                         (R[rc].part3<<16) | R[rc].part4);
01378                 }
01379                 break;
01380 
01381           case 0x11:
01382                 if(func&0x80) {
01383                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
01384                   reg64.part4 = (rb<<3)|(func>>8);
01385                 }
01386                 else
01387                   COPY64(reg64, R[rb]);
01388                 switch(func&0x7f) {
01389                 case 0x00:
01390                         DISASM0("AND\t");
01391                         R[rc].part1 = R[ra].part1&reg64.part1;
01392                         R[rc].part2 = R[ra].part2&reg64.part2;
01393                         R[rc].part3 = R[ra].part3&reg64.part3;
01394                         R[rc].part4 = R[ra].part4&reg64.part4;
01395                         break;
01396                 case 0x08:
01397                         DISASM0("BIC\t");
01398                         R[rc].part1 = R[ra].part1&~reg64.part1;
01399                         R[rc].part2 = R[ra].part2&~reg64.part2;
01400                         R[rc].part3 = R[ra].part3&~reg64.part3;
01401                         R[rc].part4 = R[ra].part4&~reg64.part4;
01402                         break;
01403                 case 0x20:
01404                         DISASM0("BIS\t");
01405                         R[rc].part1 = R[ra].part1|reg64.part1;
01406                         R[rc].part2 = R[ra].part2|reg64.part2;
01407                         R[rc].part3 = R[ra].part3|reg64.part3;
01408                         R[rc].part4 = R[ra].part4|reg64.part4;
01409                         break;
01410                 case 0x14:
01411                         DISASM0("CMOVLBS\t");
01412                         if(R[ra].part4&1)
01413                           COPY64(R[rc], reg64);
01414                         break;
01415                 case 0x16:
01416                         DISASM0("CMOVLBC\t");
01417                         if((R[ra].part4&1) == 0)
01418                           COPY64(R[rc], reg64);
01419                         break;
01420                 case 0x24:
01421                         DISASM0("CMOVEQ\t");
01422                         if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) == 0)
01423                           COPY64(R[rc], reg64);
01424                         break;
01425                 case 0x26:
01426                         DISASM0("CMOVNE\t");
01427                         if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) != 0)
01428                           COPY64(R[rc], reg64);
01429                         break;
01430                 case 0x28:
01431                         DISASM0("ORNOT\t");
01432                         R[rc].part1 = R[ra].part1|~reg64.part1;
01433                         R[rc].part2 = R[ra].part2|~reg64.part2;
01434                         R[rc].part3 = R[ra].part3|~reg64.part3;
01435                         R[rc].part4 = R[ra].part4|~reg64.part4;
01436                         break;
01437                 case 0x40:
01438                         DISASM0("XOR\t");
01439                         R[rc].part1 = R[ra].part1^reg64.part1;
01440                         R[rc].part2 = R[ra].part2^reg64.part2;
01441                         R[rc].part3 = R[ra].part3^reg64.part3;
01442                         R[rc].part4 = R[ra].part4^reg64.part4;
01443                         break;
01444                 case 0x44:
01445                         DISASM0("CMOVLT\t");
01446                         if(R[ra].part1>>15)
01447                           COPY64(R[rc], reg64);
01448                         break;
01449                 case 0x46:
01450                         DISASM0("CMOVGE\t");
01451                         if((R[ra].part1>>15) == 0)
01452                           COPY64(R[rc], reg64);
01453                         break;
01454                 case 0x48:
01455                         DISASM0("EQV\t");
01456                         R[rc].part1 = R[ra].part1^~reg64.part1;
01457                         R[rc].part2 = R[ra].part2^~reg64.part2;
01458                         R[rc].part3 = R[ra].part3^~reg64.part3;
01459                         R[rc].part4 = R[ra].part4^~reg64.part4;
01460                         break;
01461                 case 0x64:
01462                         DISASM0("CMOVLE\t");
01463                         if(R[ra].part1>>15)
01464                           COPY64(R[rc], reg64);
01465                         else if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) == 0)
01466                           COPY64(R[rc], reg64);
01467                         break;
01468                 case 0x66:
01469                         DISASM0("CMOVGT\t");
01470                         if((R[ra].part1>>15) == 0)
01471                           if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) != 0)
01472                             COPY64(R[rc], reg64);
01473                         break;
01474                 default:
01475                         status = BADINSTR;
01476                         DISASM5("%x.%x.%x.%x.%x\n", op, ra, rb, func, rc);
01477                 }
01478                 if(rc == zero)
01479                         ZERO64(R[zero]);
01480                 if(func&0x80) {
01481                     DISASM5("%s,0x%2.2x,%s\t0x%8.8x %8.8x\n",
01482                         RN[ra], (rb<<3)|(func>>8), RN[rc],
01483                         (R[rc].part1<<16) | R[rc].part2,
01484                         (R[rc].part3<<16) | R[rc].part4);
01485                 }
01486                 else {
01487                     DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
01488                         RN[ra], RN[rb], RN[rc],
01489                         (R[rc].part1<<16) | R[rc].part2,
01490                         (R[rc].part3<<16) | R[rc].part4);
01491                 }
01492                 break;
01493 
01494           case 0x12:
01495                 value = (func&0x80) ? ((rb<<3)|(func>>8)) : R[rb].part4;
01496                 switch(func&0x7f) {
01497                 case 0x02:
01498                         DISASM0("MSKBL\t");
01499                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01500                         reg64.part1 = reg64.part2 = reg64.part3 = 0;
01501                         reg64.part4 = 0xff;
01502                         SHLEFT64N(reg64, value<<3);
01503                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01504                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01505                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01506                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01507                         break;
01508                 case 0x06:
01509                         DISASM0("EXTBL\t");
01510                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01511                         if(ra != rc)
01512                           COPY64(R[rc], R[ra]);
01513                         SHRIGHT64N(R[rc], value<<3);
01514                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01515                         R[rc].part4 &= 0xff;
01516                         break;
01517                 case 0x0b:
01518                         DISASM0("INSBL\t");
01519                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01520                         if(ra != rc)
01521                           COPY64(R[rc], R[ra]);
01522                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01523                         R[rc].part4 &= 0xff;
01524                         SHLEFT64N(R[rc], value<<3);
01525                         break;
01526                 case 0x12:
01527                         DISASM0("MSKWL\t");
01528                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01529                         reg64.part1 = reg64.part2 = reg64.part3 = 0;
01530                         reg64.part4 = 0xffff;
01531                         SHLEFT64N(reg64, value<<3);
01532                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01533                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01534                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01535                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01536                         break;
01537                 case 0x16:
01538                         DISASM0("EXTWL\t");
01539                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01540                         if(ra != rc)
01541                           COPY64(R[rc], R[ra]);
01542                         SHRIGHT64N(R[rc], value<<3);
01543                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01544                         break;
01545                 case 0x1b:
01546                         DISASM0("INSWL\t");
01547                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01548                         if(ra != rc)
01549                           COPY64(R[rc], R[ra]);
01550                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01551                         SHLEFT64N(R[rc], value<<3);
01552                         break;
01553                 case 0x22:
01554                         DISASM0("MSKHL\t");
01555                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01556                         reg64.part1 = reg64.part2 = 0;
01557                         reg64.part3 = reg64.part4 = 0xffff;
01558                         SHLEFT64N(reg64, value<<3);
01559                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01560                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01561                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01562                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01563                         break;
01564                 case 0x26:
01565                         DISASM0("EXTLL\t");
01566                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01567                         if(ra != rc)
01568                           COPY64(R[rc], R[ra]);
01569                         SHRIGHT64N(R[rc], value<<3);
01570                         R[rc].part1 = R[rc].part2 = 0;
01571                         break;
01572                 case 0x2b:
01573                         DISASM0("INSLL\t");
01574                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01575                         if(ra != rc)
01576                           COPY64(R[rc], R[ra]);
01577                         R[rc].part1 = R[rc].part2 = 0;
01578                         SHLEFT64N(R[rc], value<<3);
01579                         break;
01580                 case 0x30:
01581                         DISASM0("ZAP\t");
01582                         COPY64(R[rc], R[ra]);
01583                         for(i=0; i<=7; i++)
01584                           if(value&(1<<i))
01585                             memset((char*)(&R[rc])+7-i, 0, 1);
01586                         break;
01587                 case 0x31:
01588                         DISASM0("ZAPNOT\t");
01589                         COPY64(R[rc], R[ra]);
01590                         for(i=0; i<=7; i++)
01591                           if(!(value&(1<<i)))
01592                             memset((char*)(&R[rc])+7-i, 0, 1);
01593                         break;
01594                 case 0x32:
01595                         DISASM0("MSKQL\t");
01596                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01597                         reg64.part1 = reg64.part2 = reg64.part3 = reg64.part4 = 0xffff;
01598                         SHLEFT64N(reg64, value<<3);
01599                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01600                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01601                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01602                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01603                         break;
01604                 case 0x34:
01605                         DISASM0("SRL\t");
01606                         if(ra != rc)
01607                           COPY64(R[rc], R[ra]);
01608                         SHRIGHT64N(R[rc], value&077);
01609                         break;
01610                 case 0x36:
01611                         DISASM0("EXTQL\t");
01612                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01613                         if(ra != rc)
01614                           COPY64(R[rc], R[ra]);
01615                         SHRIGHT64N(R[rc], value<<3);
01616                         break;
01617                 case 0x39:
01618                         DISASM0("SLL\t");
01619                         if(ra != rc)
01620                           COPY64(R[rc], R[ra]);
01621                         SHLEFT64N(R[rc], value&077);
01622                         break;
01623                 case 0x3b:
01624                         DISASM0("INSQL\t");
01625                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01626                         if(ra != rc)
01627                           COPY64(R[rc], R[ra]);
01628                         SHLEFT64N(R[rc], value<<3);
01629                         break;
01630                 case 0x3c:
01631                         DISASM0("SRA\t");
01632                         if(ra != rc)
01633                           COPY64(R[rc], R[ra]);
01634                         if(R[rc].part1>>15) {
01635                           NOT64(R[rc]);
01636                           SHRIGHT64N(R[rc], value&077);
01637                           NOT64(R[rc]);
01638                         }
01639                         else
01640                           SHRIGHT64N(R[rc], value&077);
01641                         break;
01642                 case 0x52:
01643                         DISASM0("MSKWH\t");
01644                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01645                         reg64.part1 = reg64.part2 = reg64.part3 = 0;
01646                         reg64.part4 = 0xffff;
01647                         SHRIGHT64N(reg64, 64-(value<<3));
01648                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01649                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01650                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01651                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01652                         break;
01653                 case 0x57:
01654                         DISASM0("INSWH\t");
01655                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01656                         if(ra != rc)
01657                           COPY64(R[rc], R[ra]);
01658                         R[rc].part1 = R[rc].part2 = R[rc].part3 = 0;
01659                         SHRIGHT64N(R[rc], 64-(value<<3));
01660                         break;
01661                 case 0x5a:
01662                         DISASM0("EXTWH\t");
01663                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01664                         if(ra != rc)
01665                           COPY64(R[rc], R[ra]);
01666                         SHLEFT64N(R[rc], (64-(value<<3))&077);
01667                         R[rc].part2 = R[rc].part3 = R[rc].part4 = 0;
01668                         break;
01669                 case 0x62:
01670                         DISASM0("MSKLH\t");
01671                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01672                         reg64.part1 = reg64.part2 = 0;
01673                         reg64.part3 = reg64.part4 = 0xffff;
01674                         SHRIGHT64N(reg64, 64-(value<<3));
01675                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01676                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01677                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01678                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01679                         break;
01680                 case 0x67:
01681                         DISASM0("INSLH\t");
01682                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01683                         if(ra != rc)
01684                           COPY64(R[rc], R[ra]);
01685                         R[rc].part1 = R[rc].part2 = 0;
01686                         SHRIGHT64N(R[rc], 64-(value<<3));
01687                         break;
01688                 case 0x6a:
01689                         DISASM0("EXTLH\t");
01690                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01691                         if(ra != rc)
01692                           COPY64(R[rc], R[ra]);
01693                         SHLEFT64N(R[rc], (64-(value<<3))&077);
01694                         R[rc].part3 = R[rc].part4 = 0;
01695                         break;
01696                 case 0x72:
01697                         DISASM0("MSKQH\t");
01698                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01699                         reg64.part1 = reg64.part2 = reg64.part3 = reg64.part4 = 0xffff;
01700                         SHRIGHT64N(reg64, 64-(value<<3));
01701                         R[rc].part1 = R[ra].part1 &~ reg64.part1;
01702                         R[rc].part2 = R[ra].part2 &~ reg64.part2;
01703                         R[rc].part3 = R[ra].part3 &~ reg64.part3;
01704                         R[rc].part4 = R[ra].part4 &~ reg64.part4;
01705                         break;
01706                 case 0x77:
01707                         DISASM0("INSQH\t");
01708                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01709                         if(ra != rc)
01710                           COPY64(R[rc], R[ra]);
01711                         SHRIGHT64N(R[rc], 64-(value<<3));
01712                         break;
01713                 case 0x7a:
01714                         DISASM0("EXTQH\t");
01715                         value = (ar_mach_type == T3D) ? (value&0x7) : ((value&0x7)^0x7);
01716                         if(ra != rc)
01717                                 COPY64(R[rc], R[ra]);
01718                         SHLEFT64N(R[rc], (64-(value<<3))&077);
01719                         break;
01720                 default:
01721                         status = BADINSTR;
01722                         DISASM5("%x.%x.%x.%x.%x\n", op, ra, rb, func, rc);
01723                 }
01724                 if(rc == zero)
01725                         ZERO64(R[zero]);
01726                 if(func&0x80) {
01727                     DISASM5("%s,0x%2.2x,%s\t0x%8.8x %8.8x\n",
01728                         RN[ra], (rb<<3)|(func>>8), RN[rc],
01729                         (R[rc].part1<<16) | R[rc].part2,
01730                         (R[rc].part3<<16) | R[rc].part4);
01731                 }
01732                 else {
01733                     DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
01734                         RN[ra], RN[rb], RN[rc],
01735                         (R[rc].part1<<16) | R[rc].part2,
01736                         (R[rc].part3<<16) | R[rc].part4);
01737                 }
01738                 break;
01739 
01740           case 0x13:
01741                 if(func&0x80) {
01742                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
01743                   reg64.part4 = (rb<<3)|(func>>8);
01744                   sign = 0;
01745                 }
01746                 else
01747                   COPY64(reg64, R[rb]);
01748                 COPY64(int64, R[ra]);
01749                 ZERO64(R[rc]);
01750                 switch(func&0x7f) {
01751                 case 0x00:
01752                         DISASM0("MULL\t");
01753                         if(reg64.part1>>15) {
01754                           NEG64(reg64);
01755                           sign = 1;
01756                         }
01757                         else
01758                           sign = 0;
01759                         if(int64.part1>>15) {
01760                           NEG64(int64);
01761                           sign ^= 1;
01762                         }
01763                         reg64.part1 = reg64.part2 = 0;
01764                         int64.part1 = int64.part2 = 0;
01765                         while(reg64.part3|reg64.part4) {
01766                           if(reg64.part4&1)
01767                             ADD64(R[rc],R[rc],int64);
01768                           SHLEFT64(int64);
01769                           SHRIGHT64(reg64);
01770                         }
01771                         R[rc].part1 = R[rc].part2 = 0;
01772                         if(sign)
01773                           NEG64(R[rc]);
01774                         break;
01775                 case 0x20:
01776                         DISASM0("MULQ\t");
01777                         if(reg64.part1>>15) {
01778                           NEG64(reg64);
01779                           sign = 1;
01780                         }
01781                         else
01782                           sign = 0;
01783                         if(int64.part1>>15) {
01784                           NEG64(int64);
01785                           sign ^= 1;
01786                         }
01787                         while(reg64.part1|reg64.part2|reg64.part3|reg64.part4) {
01788                           if(reg64.part4&1)
01789                             ADD64(R[rc],R[rc],int64);
01790                           SHLEFT64(int64);
01791                           SHRIGHT64(reg64);
01792                         }
01793                         if(sign)
01794                           NEG64(R[rc]);
01795                         break;
01796                 case 0x30:
01797                         DISASM0("UMULH\t");
01798                         n = 64;
01799                         while(reg64.part1|reg64.part2|reg64.part3|reg64.part4) {
01800                           if(reg64.part4&1)
01801                             ADD64(R[rc],R[rc],int64);
01802                           SHRIGHT64(R[rc]);
01803                           SHRIGHT64(reg64);
01804                           n--;
01805                         }
01806                         SHRIGHT64N(R[rc], n);
01807                         break;
01808                 default:
01809                         status = BADINSTR;
01810                         DISASM5("%x.%x.%x.%x.%x\n", op, ra, rb, func, rc);
01811                 }
01812                 if(rc == zero)
01813                         ZERO64(R[zero]);
01814                 if(func&0x80) {
01815                     DISASM5("%s,0x%2.2x,%s\t0x%8.8x %8.8x\n",
01816                         RN[ra], (rb<<3)|(func>>8), RN[rc],
01817                         (R[rc].part1<<16) | R[rc].part2,
01818                         (R[rc].part3<<16) | R[rc].part4);
01819                 }
01820                 else {
01821                     DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
01822                         RN[ra], RN[rb], RN[rc],
01823                         (R[rc].part1<<16) | R[rc].part2,
01824                         (R[rc].part3<<16) | R[rc].part4);
01825                 }
01826                 break;
01827 
01828           case 0x15:
01829           case 0x16:
01830                 rr = (AR_IEEE_64*)&F[rc];
01831                 oa = (AR_IEEE_64*)&F[ra];
01832                 ob = (AR_IEEE_64*)&F[rb];
01833                 switch(func) {
01834                 case 0x00:
01835                         DISASM0("ADDS/C\t");
01836                         ar_type = AR_Float_IEEE_ZE_32;
01837                         status = ar_ifadd64(rr, oa, ob, AR_ROUND_ZERO);
01838                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01839                                              (ar_data*)&F[rc], &ieee_float_64);
01840                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01841                                              (ar_data*)&reg64, &ieee_float_32);
01842                         status &= AR_ERROR_STATUS;
01843                         break;
01844                 case 0x01:
01845                         DISASM0("SUBS/C\t");
01846                         ar_type = AR_Float_IEEE_ZE_32;
01847                         status = ar_ifsub64(rr, oa, ob, AR_ROUND_ZERO);
01848                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01849                                              (ar_data*)&F[rc], &ieee_float_64);
01850                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01851                                              (ar_data*)&reg64, &ieee_float_32);
01852                         status &= AR_ERROR_STATUS;
01853                         break;
01854                 case 0x02:
01855                         DISASM0("MULS/C\t");
01856                         ar_type = AR_Float_IEEE_ZE_32;
01857                         status = ar_ifmul64(rr, oa, ob, AR_ROUND_ZERO);
01858                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01859                                              (ar_data*)&F[rc], &ieee_float_64);
01860                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01861                                              (ar_data*)&reg64, &ieee_float_32);
01862                         status &= AR_ERROR_STATUS;
01863                         break;
01864                 case 0x03:
01865                         DISASM0("DIVS/C\t");
01866                         ar_type = AR_Float_IEEE_ZE_32;
01867                         status = ar_ifdiv64(rr, oa, ob, AR_ROUND_ZERO);
01868                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01869                                              (ar_data*)&F[rc], &ieee_float_64);
01870                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01871                                              (ar_data*)&reg64, &ieee_float_32);
01872                         status &= AR_ERROR_STATUS;
01873                         break;
01874                 case 0x20:
01875                         DISASM0("ADDT/C\t");
01876                         status = ar_ifadd64(rr, oa, ob, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01877                         break;
01878                 case 0x21:
01879                         DISASM0("SUBT/C\t");
01880                         status = ar_ifsub64(rr, oa, ob, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01881                         break;
01882                 case 0x22:
01883                         DISASM0("MULT/C\t");
01884                         status = ar_ifmul64(rr, oa, ob, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01885                         break;
01886                 case 0x23:
01887                         DISASM0("DIVT/C\t");
01888                         status = ar_ifdiv64(rr, oa, ob, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01889                         break;
01890                 case 0x2c:
01891                         DISASM0("CVTTS/C\t");
01892                         ar_type = AR_Float_IEEE_ZE_32;
01893                         status  = ar_convert_to_float((ar_data*)&reg64, &ar_type,
01894                                              (ar_data*)&F[rb], &ieee_float_64);
01895                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01896                                              (ar_data*)&reg64, &ieee_float_32);
01897                         status &= AR_ERROR_STATUS;
01898                         break;
01899                 case 0x2f:
01900                         DISASM0("CVTTQ/C\t");
01901                         status = ar_ifix64((AR_INT_64*)rr, ob, 64, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01902                         break;
01903                 case 0x3c:
01904                         DISASM0("CVTQS/C\t");
01905                         ar_type = AR_Float_IEEE_ZE_32;
01906                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, AR_ROUND_ZERO);
01907                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01908                                              (ar_data*)&F[rc], &ieee_float_64);
01909                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01910                                              (ar_data*)&reg64, &ieee_float_32);
01911                         status &= AR_ERROR_STATUS;
01912                         break;
01913                 case 0x3e:
01914                         DISASM0("CVTQT/C\t");
01915                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, AR_ROUND_ZERO)&AR_ERROR_STATUS;
01916                         break;
01917                 case 0x80:
01918                         DISASM0("ADDS\t");
01919                         ar_type = AR_Float_IEEE_NR_32;
01920                         status = ar_ifadd64(rr, oa, ob, AR_ROUND_NEAREST);
01921                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01922                                              (ar_data*)&F[rc], &ieee_float_64);
01923                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01924                                              (ar_data*)&reg64, &ieee_float_32);
01925                         status &= AR_ERROR_STATUS;
01926                         break;
01927                 case 0x81:
01928                         DISASM0("SUBS\t");
01929                         ar_type = AR_Float_IEEE_NR_32;
01930                         status = ar_ifsub64(rr, oa, ob, AR_ROUND_NEAREST);
01931                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01932                                              (ar_data*)&F[rc], &ieee_float_64);
01933                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01934                                              (ar_data*)&reg64, &ieee_float_32);
01935                         status &= AR_ERROR_STATUS;
01936                         break;
01937                 case 0x82:
01938                         DISASM0("MULS\t");
01939                         ar_type = AR_Float_IEEE_NR_32;
01940                         status = ar_ifmul64(rr, oa, ob, AR_ROUND_NEAREST);
01941                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01942                                              (ar_data*)&F[rc], &ieee_float_64);
01943                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01944                                              (ar_data*)&reg64, &ieee_float_32);
01945                         status &= AR_ERROR_STATUS;
01946                         break;
01947                 case 0x83:
01948                         DISASM0("DIVS\t");
01949                         ar_type = AR_Float_IEEE_NR_32;
01950                         status = ar_ifdiv64(rr, oa, ob, AR_ROUND_NEAREST);
01951                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
01952                                              (ar_data*)&F[rc], &ieee_float_64);
01953                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
01954                                              (ar_data*)&reg64, &ieee_float_32);
01955                         status &= AR_ERROR_STATUS;
01956                         break;
01957                 case 0xa0:
01958                         DISASM0("ADDT\t");
01959                         status = ar_ifadd64(rr, oa, ob, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
01960                         break;
01961                 case 0xa1:
01962                         DISASM0("SUBT\t");
01963                         status = ar_ifsub64(rr, oa, ob, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
01964                         break;
01965                 case 0xa2:
01966                         DISASM0("MULT\t");
01967                         status = ar_ifmul64(rr, oa, ob, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
01968                         break;
01969                 case 0xa3:
01970                         DISASM0("DIVT\t");
01971                         status = ar_ifdiv64(rr, oa, ob, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
01972                         break;
01973                 case 0xa5:
01974                         DISASM0("CMPTEQ\t");
01975                         status = ar_ifcmp64((const AR_IEEE_64*)oa, (const AR_IEEE_64*)ob);
01976                         F[rc].part2 = F[rc].part3 = F[rc].part4 = 0;
01977                         if(status & AR_STAT_ZERO)
01978                           F[rc].part1 = 0x4000;
01979                         else
01980                           F[rc].part1 = 0;
01981                         status = AR_STAT_OK;
01982                         break;
01983                 case 0xa6:
01984                         DISASM0("CMPTLT\t");
01985                         status = ar_ifcmp64((const AR_IEEE_64*)oa, (const AR_IEEE_64*)ob);
01986                         F[rc].part2 = F[rc].part3 = F[rc].part4 = 0;
01987                         if(status & AR_STAT_NEGATIVE)
01988                           F[rc].part1 = 0x4000;
01989                         else
01990                           F[rc].part1 = 0;
01991                         status = AR_STAT_OK;
01992                         break;
01993                 case 0xa7:
01994                         DISASM0("CMPTLE\t");
01995                         status = ar_ifcmp64((const AR_IEEE_64*)oa, (const AR_IEEE_64*)ob);
01996                         F[rc].part2 = F[rc].part3 = F[rc].part4 = 0;
01997                         if(status & (AR_STAT_NEGATIVE|AR_STAT_ZERO))
01998                           F[rc].part1 = 0x4000;
01999                         else
02000                           F[rc].part1 = 0;
02001                         status = AR_STAT_OK;
02002                         break;
02003                 case 0xac:
02004                         DISASM0("CVTTS\t");
02005                         ar_type = AR_Float_IEEE_NR_32;
02006                         status  = ar_convert_to_float((ar_data*)&reg64, &ar_type,
02007                                              (ar_data*)&F[rb], &ieee_float_64);
02008                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02009                                              (ar_data*)&reg64, &ieee_float_32);
02010                         status &= AR_ERROR_STATUS;
02011                         break;
02012                 case 0xaf:
02013                         DISASM0("CVTTQ\t");
02014                         status = ar_ifix64((AR_INT_64*)rr, ob, 64, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
02015                         break;
02016                 case 0xbc:
02017                         DISASM0("CVTQS\t");
02018                         ar_type = AR_Float_IEEE_NR_32;
02019                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, AR_ROUND_NEAREST);
02020                         status |= ar_convert_to_float((ar_data*)&reg64, &ar_type,
02021                                              (ar_data*)&F[rc], &ieee_float_64);
02022                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02023                                              (ar_data*)&reg64, &ieee_float_32);
02024                         status &= AR_ERROR_STATUS;
02025                         break;
02026                 case 0xbe:
02027                         DISASM0("CVTQT\t");
02028                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, AR_ROUND_NEAREST)&AR_ERROR_STATUS;
02029                         break;
02030                 case 0xc0:
02031                         DISASM0("ADDS/D\t");
02032                         status = ar_ifadd64(rr, oa, ob, D_roundmode);
02033                         status |= ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02034                                              (ar_data*)&F[rc], &ieee_float_64);
02035                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02036                                              (ar_data*)&reg64, &ieee_float_32);
02037                         status &= AR_ERROR_STATUS;
02038                         break;
02039                 case 0xc1:
02040                         DISASM0("SUBS/D\t");
02041                         status = ar_ifsub64(rr, oa, ob, D_roundmode);
02042                         status |= ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02043                                              (ar_data*)&F[rc], &ieee_float_64);
02044                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02045                                              (ar_data*)&reg64, &ieee_float_32);
02046                         status &= AR_ERROR_STATUS;
02047                         break;
02048                 case 0xc2:
02049                         DISASM0("MULS/D\t");
02050                         status = ar_ifmul64(rr, oa, ob, D_roundmode);
02051                         status |= ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02052                                              (ar_data*)&F[rc], &ieee_float_64);
02053                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02054                                              (ar_data*)&reg64, &ieee_float_32);
02055                         status &= AR_ERROR_STATUS;
02056                         break;
02057                 case 0xc3:
02058                         DISASM0("DIVS/D\t");
02059                         status = ar_ifdiv64(rr, oa, ob, D_roundmode);
02060                         status |= ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02061                                              (ar_data*)&F[rc], &ieee_float_64);
02062                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02063                                              (ar_data*)&reg64, &ieee_float_32);
02064                         status &= AR_ERROR_STATUS;
02065                         break;
02066                 case 0xe0:
02067                         DISASM0("ADDT/D\t");
02068                         status = ar_ifadd64(rr, oa, ob, D_roundmode)&AR_ERROR_STATUS;
02069                         break;
02070                 case 0xe1:
02071                         DISASM0("SUBT/D\t");
02072                         status = ar_ifsub64(rr, oa, ob, D_roundmode)&AR_ERROR_STATUS;
02073                         break;
02074                 case 0xe2:
02075                         DISASM0("MULT/D\t");
02076                         status = ar_ifmul64(rr, oa, ob, D_roundmode)&AR_ERROR_STATUS;
02077                         break;
02078                 case 0xe3:
02079                         DISASM0("DIVT/D\t");
02080                         status = ar_ifdiv64(rr, oa, ob, D_roundmode)&AR_ERROR_STATUS;
02081                         break;
02082                 case 0xec:
02083                         DISASM0("CVTTS/D\t");
02084                         status  = ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02085                                              (ar_data*)&F[rb], &ieee_float_64);
02086                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02087                                              (ar_data*)&reg64, &ieee_float_32);
02088                         status &= AR_ERROR_STATUS;
02089                         break;
02090                 case 0xef:
02091                         DISASM0("CVTTQ/D\t");
02092                         status = ar_ifix64((AR_INT_64*)rr, ob, 64, D_roundmode)&AR_ERROR_STATUS;
02093                         break;
02094                 case 0xfc:
02095                         DISASM0("CVTQS/D\t");
02096                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, D_roundmode);
02097                         status |= ar_convert_to_float((ar_data*)&reg64, &D_float_32,
02098                                              (ar_data*)&F[rc], &ieee_float_64);
02099                         status |= ar_convert_to_float((ar_data*)&F[rc], &ieee_float_64,
02100                                              (ar_data*)&reg64, &ieee_float_32);
02101                         status &= AR_ERROR_STATUS;
02102                         break;
02103                 case 0xfe:
02104                         DISASM0("CVTQT/D\t");
02105                         status = ar_iflt64(rr, (AR_INT_64*)ob, 0, D_roundmode)&AR_ERROR_STATUS;
02106                         break;
02107                 default:
02108                         status = BADINSTR;
02109                         DISASM5("%x.%x.%x.%x.%x", op, ra, rb, func, rc);
02110                 }
02111                 if(rc == fzero)
02112                         ZERO64(F[fzero]);
02113                 DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
02114                         FN[ra], FN[rb], FN[rc],
02115                         (F[rc].part1<<16) | F[rc].part2,
02116                         (F[rc].part3<<16) | F[rc].part4);
02117                 break;
02118 
02119           case 0x17:
02120                 switch(func) {
02121                 case 0x10:
02122                         DISASM0("CVTLQ\t");
02123                         F[rc].part3 = (F[rb].part1&0xc000) |
02124                                       ((F[rb].part1&0x7ff) << 3) |
02125                                       (F[rb].part2 >> 13);
02126                         F[rc].part4 = (F[rb].part2 << 3) |
02127                                       (F[rb].part3 >> 13);
02128                         if(F[rc].part3>>15)
02129                           F[rc].part1 = F[rc].part2 = 0xffff;
02130                         else
02131                           F[rc].part1 = F[rc].part2 = 0;
02132                         break;
02133                 case 0x20:
02134                         DISASM0("CPYS\t");
02135                         sign = F[ra].part1&0x8000;
02136                         COPY64(F[rc], F[rb]);
02137                         if(ra != rb)
02138                           F[rc].part1 = (F[rc].part1&0x7fff) | sign;
02139                         break;
02140                 case 0x21:
02141                         DISASM0("CPYSN\t");
02142                         sign = 0x8000-(F[ra].part1&0x8000);
02143                         COPY64(F[rc], F[rb]);
02144                         F[rc].part1 = (F[rc].part1&0x7fff) | sign;
02145                         break;
02146                 case 0x22:
02147                         DISASM0("CPYSE\t");
02148                         sign = F[ra].part1&0xfff0;
02149                         COPY64(F[rc], F[rb]);
02150                         if(ra != rb)
02151                           F[rc].part1 = (F[rc].part1&0x000f) | sign;
02152                         break;
02153                 case 0x2a:
02154                         DISASM0("FCMOVEQ\t");
02155                         if(((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4) == 0)
02156                           COPY64(F[rc], F[rb]);
02157                         break;
02158                 case 0x2b:
02159                         DISASM0("FCMOVNE\t");
02160                         if(((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4) != 0)
02161                           COPY64(F[rc], F[rb]);
02162                         break;
02163                 case 0x2c:
02164                         DISASM0("FCMOVLT\t");
02165                         if(F[ra].part1&0x8000)
02166                           COPY64(F[rc], F[rb]);
02167                         break;
02168                 case 0x2d:
02169                         DISASM0("FCMOVGE\t");
02170                         if((F[ra].part1&0x8000) == 0)
02171                           COPY64(F[rc], F[rb]);
02172                         break;
02173                 case 0x2e:
02174                         DISASM0("FCMOVLE\t");
02175                         if((F[ra].part1&0x8000) ||
02176                            ((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4) == 0)
02177                           COPY64(F[rc], F[rb]);
02178                         break;
02179                 case 0x2f:
02180                         DISASM0("FCMOVGT\t");
02181                         if((F[ra].part1&0x8000) == 0 &&
02182                            ((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4) != 0)
02183                           COPY64(F[rc], F[rb]);
02184                         break;
02185                 case 0x30:
02186                         DISASM0("CVTQL\t");
02187                         F[rc].part1 = (F[rb].part3 & 0xc000) |
02188                                      ((F[rb].part3 & 0x3fff) >> 3);
02189                         F[rc].part2 = (F[rb].part3 << 13) |
02190                                       (F[rb].part4 >> 3);
02191                         F[rc].part3 = (F[rb].part4 << 13);
02192                         F[rc].part4 = 0;
02193                         break;
02194                 default:
02195                         status = BADINSTR;
02196                         DISASM5("%x.%x.%x.%x.%x", op, ra, rb, func, rc);
02197                 }
02198                 if(rc == fzero)
02199                         ZERO64(F[fzero]);
02200                 DISASM5("%s,%s,%s\t0x%8.8x %8.8x\n",
02201                         FN[ra], FN[rb], FN[rc],
02202                         (F[rc].part1<<16) | F[rc].part2,
02203                         (F[rc].part3<<16) | F[rc].part4);
02204                 break;
02205 
02206           case 0x18:
02207                 switch(p2) {
02208                 case 0x0:
02209                   DISASM0("TRAPB\n");
02210                   break;
02211                 case 0x4:
02212                   DISASM0("MB\n");
02213                   break;
02214                 case 0x8:
02215                   DISASM2("FETCH\t%s,%s\n", RN[ra],RN[rb]);
02216                   break;
02217                 case 0xa:
02218                   DISASM2("FETCH_M\t%s,%s\n", RN[ra],RN[rb]);
02219                   break;
02220                 case 0xc:
02221                   if(rtcpc < pc)
02222                         rtc += (pc-rtcpc);
02223                   else
02224                         rtc += (rtcpc-pc);
02225                   rtcpc = pc;
02226                   iu64.l64 = rtc;
02227                   COPY64(R[ra], iu64.ari64);
02228                   DISASM2("RPCC\t%s\t0x%16x\n", RN[ra], rtc);
02229                   break;
02230                 case 0xe:
02231                   DISASM2("RC\t%s,%s\n", RN[ra], RN[rb]);
02232                   break;
02233                 case 0xf:
02234                   DISASM2("RS\t%s,%s\n", RN[ra], RN[rb]);
02235                   break;
02236                 }
02237                 break;
02238 
02239           case 0x1a:
02240                 switch(func>>9) {
02241                 case 0:
02242                   DISASM2("JMP\t%s,%s\n",RN[ra],RN[rb]);
02243                   break;
02244                 case 1:
02245                   DISASM2("JSR\t%s,%s\n",RN[ra],RN[rb]);
02246                   break;
02247                 case 2:
02248                   DISASM2("RET\t%s,%s\n",RN[ra],RN[rb]);
02249                   break;
02250                 case 3:
02251                   DISASM2("JSR_C\t,%s\n",RN[ra],RN[rb]);
02252                   break;
02253                 }
02254                 if(ra != zero) {
02255                   R[ra].part1 = R[ra].part2 = 0;
02256                   R[ra].part3 = pc>>16;
02257                   R[ra].part4 = pc&0xffff;
02258                 }
02259                 pc = ((R[rb].part3<<16)|R[rb].part4) &~ 3;
02260                 if(pc == 0)             /* Check for end of simulation */
02261                         return(status);
02262                 break;
02263 
02264           case 0x20:
02265                 status = BADINSTR;
02266                 DISASM3("LDF\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02267                 break;
02268 
02269           case 0x21:
02270                 status = BADINSTR;
02271                 DISASM3("LDG\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02272                 break;
02273 
02274           case 0x22:
02275                 if(ra != fzero) {
02276                   reg64.part4 = p2;
02277                   if(p2>>15)
02278                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02279                   else
02280                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
02281                   ADD64(reg64, reg64, R[rb]);
02282                   offset = (reg64.part3<<16) | reg64.part4;
02283                   if(offset & 3)
02284                         status = BADINSTR;
02285                   else {
02286                         load_mpp_word(&reg64, reg64.part2&0xff, offset>>3);
02287                         if(offset & 4) {
02288                                 int64.part3 = reg64.part3;
02289                                 int64.part4 = reg64.part4;
02290                         }
02291                         else {
02292                                 int64.part3 = reg64.part1;
02293                                 int64.part4 = reg64.part2;
02294                         }
02295                   }
02296                   ar_convert_to_float((ar_data*)&F[ra], &ieee_float_64,
02297                            (ar_data*)&int64, &ieee_float_32);
02298                 }
02299                 DISASM5("LDS\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
02300                         FN[ra], p2, RN[rb],
02301                         (F[ra].part1<<16) | F[ra].part2,
02302                         (F[ra].part3<<16) | F[ra].part4);
02303                 break;
02304 
02305           case 0x23:
02306                 if(ra != fzero) {
02307                   reg64.part4 = p2;
02308                   if(p2>>15)
02309                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02310                   else
02311                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
02312                   ADD64(reg64, reg64, R[rb]);
02313                   offset = (reg64.part3<<16) | reg64.part4;
02314                   if(offset & 7)
02315                         status = BADINSTR;
02316                   else
02317                         load_mpp_word(&F[ra], reg64.part2&0xff, offset>>3);
02318                 }
02319                 DISASM5("LDT\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
02320                         FN[ra], p2, RN[rb],
02321                         (F[ra].part1<<16) | F[ra].part2,
02322                         (F[ra].part3<<16) | F[ra].part4);
02323                 break;
02324 
02325           case 0x24:
02326                 status = BADINSTR;
02327                 DISASM3("STF\t%s,0x%4.4x(%s)\n", FN[ra], p2, RN[rb]);
02328                 break;
02329 
02330           case 0x25:
02331                 status = BADINSTR;
02332                 DISASM3("STG\t%s,0x%4.4x(%s)\n", FN[ra], p2, RN[rb]);
02333                 break;
02334 
02335           case 0x26:
02336                 reg64.part4 = p2;
02337                 if(p2>>15)
02338                   reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02339                 else
02340                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
02341                 ADD64(reg64, reg64, R[rb]);
02342                 offset = (reg64.part3<<16) | reg64.part4;
02343                 if(offset & 3)
02344                         status = BADINSTR;
02345                 else {
02346                         n = reg64.part2&0xff;
02347                         load_mpp_word(&reg64, n, offset>>3);
02348                         ar_convert_to_float((ar_data*)&int64, &ieee_float_32,
02349                                    (ar_data*)&F[ra], &ieee_float_64);
02350                         if(offset & 4) {
02351                                 reg64.part3 = int64.part3;
02352                                 reg64.part4 = int64.part4;
02353                         }
02354                         else {
02355                                 reg64.part1 = int64.part3;
02356                                 reg64.part2 = int64.part4;
02357                         }
02358                         store_mpp_word(n, offset>>3, &reg64);
02359                 }
02360                 DISASM3("STS\t%s,0x%4.4x(%s)\n", FN[ra], p2, RN[rb]);
02361                 break;
02362 
02363           case 0x27:
02364                 reg64.part4 = p2;
02365                 if(p2>>15)
02366                   reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02367                 else
02368                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
02369                 ADD64(reg64, reg64, R[rb]);
02370                 offset = (reg64.part3<<16) | reg64.part4;
02371                 if(offset & 7)
02372                         status = BADINSTR;
02373                 else {
02374                         store_mpp_word(reg64.part2&0xff, offset>>3, &F[ra]);
02375                 }
02376                 DISASM3("STT\t%s,0x%4.4x(%s)\n", FN[ra], p2, RN[rb]);
02377                 break;
02378 
02379           case 0x28:
02380                 if(ra != zero) {
02381                   reg64.part4 = p2;
02382                   if(p2>>15)
02383                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02384                   else
02385                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
02386                   ADD64(reg64, reg64, R[rb]);
02387                   offset = (reg64.part3<<16) | reg64.part4;
02388                   if(offset & 3)
02389                         status = BADINSTR;
02390                   else {
02391                         load_mpp_word(&reg64, reg64.part2&0xff, offset>>3);
02392                         if(offset & 4) {
02393                                 R[ra].part3 = reg64.part3;
02394                                 R[ra].part4 = reg64.part4;
02395                         }
02396                         else {
02397                                 R[ra].part3 = reg64.part1;
02398                                 R[ra].part4 = reg64.part2;
02399                         }
02400                   }
02401                   if(R[ra].part3>>15)
02402                     R[ra].part1 = R[ra].part2 = 0xffff;
02403                   else
02404                     R[ra].part1 = R[ra].part2 = 0;
02405                 }
02406                 DISASM5("LDL\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
02407                         RN[ra], p2, RN[rb],
02408                         (R[ra].part1<<16) | R[ra].part2,
02409                         (R[ra].part3<<16) | R[ra].part4);
02410                 break;
02411 
02412           case 0x29:
02413                 if(ra != zero) {
02414                   reg64.part4 = p2;
02415                   if(p2>>15)
02416                     reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02417                   else
02418                     reg64.part1 = reg64.part2 = reg64.part3 = 0;
02419                   ADD64(reg64, reg64, R[rb]);
02420                   offset = (reg64.part3<<16) | reg64.part4;
02421                   if(offset & 7)
02422                         status = BADINSTR;
02423                   else
02424                         load_mpp_word(&R[ra], reg64.part2&0xff, offset>>3);
02425                 }
02426                 DISASM5("LDQ\t%s,0x%4.4x(%s)\t0x%8.8x %8.8x\n",
02427                         RN[ra], p2, RN[rb],
02428                         (R[ra].part1<<16) | R[ra].part2,
02429                         (R[ra].part3<<16) | R[ra].part4);
02430                 break;
02431 
02432           case 0x2a:
02433                 status = BADINSTR;
02434                 DISASM3("LDL_L\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02435                 break;
02436 
02437           case 0x2b:
02438                 status = BADINSTR;
02439                 DISASM3("LDQ_L\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02440                 break;
02441 
02442           case 0x2c:
02443                 reg64.part4 = p2;
02444                 if(p2>>15)
02445                   reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02446                 else
02447                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
02448                 ADD64(reg64, reg64, R[rb]);
02449                 offset = (reg64.part3<<16) | reg64.part4;
02450                 if(offset & 3)
02451                         status = BADINSTR;
02452                 else {
02453                         n = reg64.part2&0xff;
02454                         load_mpp_word(&reg64, n, offset>>3);
02455                         if(offset & 4) {
02456                                 reg64.part3 = R[ra].part3;
02457                                 reg64.part4 = R[ra].part4;
02458                         }
02459                         else {
02460                                 reg64.part1 = R[ra].part3;
02461                                 reg64.part2 = R[ra].part4;
02462                         }
02463                         store_mpp_word(n, offset>>3, &reg64);
02464                 }
02465                 DISASM3("STL\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02466                 break;
02467 
02468           case 0x2d:
02469                 reg64.part4 = p2;
02470                 if(p2>>15)
02471                   reg64.part1 = reg64.part2 = reg64.part3 = 0xffff;
02472                 else
02473                   reg64.part1 = reg64.part2 = reg64.part3 = 0;
02474                 ADD64(reg64, reg64, R[rb]);
02475                 offset = (reg64.part3<<16) | reg64.part4;
02476                 if(offset & 7)
02477                         status = BADINSTR;
02478                 else {
02479                         store_mpp_word(reg64.part2&0xff, offset>>3, &R[ra]);
02480                 }
02481                 DISASM3("STQ\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02482                 break;
02483 
02484           case 0x2e:
02485                 status = BADINSTR;
02486                 DISASM3("STL_C\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02487                 break;
02488 
02489           case 0x2f:
02490                 status = BADINSTR;
02491                 DISASM3("STQ_C\t%s,0x%4.4x(%s)\n", RN[ra], p2, RN[rb]);
02492                 break;
02493 
02494           case 0x30:
02495           case 0x34:
02496                 disp = ((rb<<16)|p2)<<2;
02497                 if(disp>>22)
02498                   disp |= (-1<<23);
02499                 if(ra != zero) {
02500                   R[ra].part1 = R[ra].part2 = 0;
02501                   R[ra].part3 = pc>>16;
02502                   R[ra].part4 = pc&0xffff;
02503                 }
02504                 pc += disp;
02505                 if(op == 0x30) {
02506                         DISASM2("BR\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02507                 }
02508                 else {
02509                         DISASM2("BSR\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02510                 }
02511                 if(pc == 0)             /* Check for end of simulation */
02512                         return(status);
02513                 break;
02514 
02515           case 0x31:
02516                 if(!((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4)) {
02517                   disp = ((rb<<16)|p2)<<2;
02518                   if(disp>>22)
02519                     disp |= (-1<<23);
02520                   pc += disp;
02521                 }
02522                 DISASM2("FBEQ\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02523                 break;
02524 
02525           case 0x32:
02526                 if(F[ra].part1>>15) {
02527                   disp = ((rb<<16)|p2)<<2;
02528                   if(disp>>22)
02529                     disp |= (-1<<23);
02530                   pc += disp;
02531                 }
02532                 DISASM2("FBLT\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02533                 break;
02534 
02535           case 0x33:
02536                 if((F[ra].part1>>15) ||
02537                    (F[ra].part1|F[ra].part2|F[ra].part3|F[ra].part4)==0) {
02538                   disp = ((rb<<16)|p2)<<2;
02539                   if(disp>>22)
02540                     disp |= (-1<<23);
02541                   pc += disp;
02542                 }
02543                 DISASM2("FBLE\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02544                 break;
02545 
02546           case 0x35:
02547                 if((F[ra].part1&0x7fff)|F[ra].part2|F[ra].part3|F[ra].part4) {
02548                   disp = ((rb<<16)|p2)<<2;
02549                   if(disp>>22)
02550                     disp |= (-1<<23);
02551                   pc += disp;
02552                 }
02553                 DISASM2("FBNE\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02554                 break;
02555 
02556           case 0x36:
02557                 if((F[ra].part1>>15) == 0) {
02558                   disp = ((rb<<16)|p2)<<2;
02559                   if(disp>>22)
02560                     disp |= (-1<<23);
02561                   pc += disp;
02562                 }
02563                 DISASM2("FBGE\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02564                 break;
02565 
02566           case 0x37:
02567                 if((F[ra].part1>>15)==0 &&
02568                    (F[ra].part1|F[ra].part2|F[ra].part3|F[ra].part4)!=0) {
02569                   disp = ((rb<<16)|p2)<<2;
02570                   if(disp>>22)
02571                     disp |= (-1<<23);
02572                   pc += disp;
02573                 }
02574                 DISASM2("FBGT\t%s,0x%6.6x\n", FN[ra], (rb<<16)|p2);
02575                 break;
02576 
02577           case 0x38:
02578                 if((R[ra].part4&1) == 0) {
02579                   disp = ((rb<<16)|p2)<<2;
02580                   if(disp>>22)
02581                     disp |= (-1<<23);
02582                   pc += disp;
02583                 }
02584                 DISASM2("BLBC\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02585                 break;
02586 
02587           case 0x39:
02588                 if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) == 0) {
02589                   disp = ((rb<<16)|p2)<<2;
02590                   if(disp>>22)
02591                     disp |= (-1<<23);
02592                   pc += disp;
02593                 }
02594                 DISASM2("BEQ\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02595                 break;
02596 
02597           case 0x3a:
02598                 if(R[ra].part1>>15) {
02599                   disp = ((rb<<16)|p2)<<2;
02600                   if(disp>>22)
02601                     disp |= (-1<<23);
02602                   pc += disp;
02603                 }
02604                 DISASM2("BLT\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02605                 break;
02606 
02607           case 0x3b:
02608                 if((R[ra].part1>>15) ||
02609                    (R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4)==0) {
02610                   disp = ((rb<<16)|p2)<<2;
02611                   if(disp>>22)
02612                     disp |= (-1<<23);
02613                   pc += disp;
02614                 }
02615                 DISASM2("BLE\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02616                 break;
02617 
02618           case 0x3c:
02619                 if(R[ra].part4&1) {
02620                   disp = ((rb<<16)|p2)<<2;
02621                   if(disp>>22)
02622                     disp |= (-1<<23);
02623                   pc += disp;
02624                 }
02625                 DISASM2("BLBS\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02626                 break;
02627 
02628           case 0x3d:
02629                 if((R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4) != 0) {
02630                   disp = ((rb<<16)|p2)<<2;
02631                   if(disp>>22)
02632                     disp |= (-1<<23);
02633                   pc += disp;
02634                 }
02635                 DISASM2("BNE\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02636                 break;
02637 
02638           case 0x3e:
02639                 if((R[ra].part1>>15) == 0) {
02640                   disp = ((rb<<16)|p2)<<2;
02641                   if(disp>>22)
02642                     disp |= (-1<<23);
02643                   pc += disp;
02644                 }
02645                 DISASM2("BGE\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02646                 break;
02647 
02648           case 0x3f:
02649                 if((R[ra].part1>>15)==0 &&
02650                    (R[ra].part1|R[ra].part2|R[ra].part3|R[ra].part4)!=0) {
02651                   disp = ((rb<<16)|p2)<<2;
02652                   if(disp>>22)
02653                     disp |= (-1<<23);
02654                   pc += disp;
02655                 }
02656                 DISASM2("BGT\t%s,0x%6.6x\n", RN[ra], (rb<<16)|p2);
02657                 break;
02658 
02659           default:
02660                 status = BADINSTR;
02661                 break;
02662           }
02663 
02664         }
02665 
02666         if(status == BADINSTR)          /* Unsimulated instruction reached */
02667                 ar_internal_error(2013, __FILE__, __LINE__);
02668 
02669         return status;
02670 }
02671 
02672 #define T3D_AHDR_SIZE   174*8   /* # bytes in T3D a.out file headers */
02673 #define CLD_T3E_AHDR_SIZE       512*8   /* # bytes in T3E a.out file headers */
02674 
02675 #if T3D_AHDR_SIZE < 5*MPP_MAX_ARGS*8
02676 #error Insufficient space for T3D arguments
02677 #elif CLD_T3E_AHDR_SIZE < 5*MPP_MAX_ARGS*8
02678 #error Insufficient space for T3E arguments
02679 #endif
02680 
02681 static int      idf_fd;         /* Intrinsic data file file descriptor */
02682 static long     idf_size;       /* Intrinsic data file size (in bytes) */
02683 static long     text_size;      /* Size of text space loaded into memory */
02684 static long     data_offset;    /* Offset in data file to data section */
02685 
02686 static void
02687 open_intrinsics_file(void)
02688 {
02689         char    fname[FILENAME_MAX + 1];
02690 
02691         int     i;
02692         int     fd;
02693         int hdrsz;
02694         int     v;
02695 
02696         long    offset;
02697 
02698         char*   str;
02699 
02700         /* Find and open intrinsic evaluation data file */
02701 
02702     /* Use the arith data file from the CRAYLIBS path if it is set */
02703 
02704         str=(char*)getenv("CRAYLIBS");
02705         if(str != NULL) {
02706                 strcpy(fname,str);
02707                 v=strlen(fname);
02708                 strcpy(&fname[v],"/arith");
02709                 idf_fd=open(fname, O_RDONLY);
02710         }
02711 
02712     /* Use a default arith data file */
02713 
02714         else {
02715 #if _CRAY
02716                 strcpy(fname,"/opt/ctl/craylibs_m/craylibs_m/arith");
02717                 v = 29;
02718                 idf_fd=open(fname, O_RDONLY);
02719                 if(idf_fd < 0) {
02720                          strcpy(fname,"/mpp/lib/arith");
02721                          v = 8;
02722                          idf_fd=open(fname, O_RDONLY);
02723                 }
02724 #else
02725                 idf_fd = -1;
02726 #endif
02727         }
02728         if(idf_fd < 0)
02729                 ar_internal_error(2009, __FILE__, __LINE__);
02730 
02731         /* Load intrinsic evaluation data file into heap memory */
02732 
02733         idf_size=lseek(idf_fd,0,SEEK_END);
02734         if(idf_size > 0) {
02735                 /*
02736                  * For total space, we need enough for the arith data file
02737                  * minus its header, plus MPP_STACK_SIZE words of stack,
02738                  * plus room for a fake DSIB, plus MPP_MAX_ARGS*5 words
02739                  * of fake callee stack space.   Some of this will end up
02740                  * being wasted, since the header gets thrown away, but
02741                  * that's alright.
02742                  */
02743                 mpp_intrin=(unsigned char*)malloc(idf_size +
02744                                                                                   MPP_STACK_SIZE*8 +
02745                                                                                   6*8 +
02746                                                                                   MPP_MAX_ARGS*5*8);
02747                 if(mpp_intrin == NULL)
02748                         idf_size = -1;
02749                 else {
02750                         lseek(idf_fd,0,SEEK_SET);
02751                         read(idf_fd,mpp_intrin,idf_size);
02752 
02753                         /* Skip over T3D header string if it exists */
02754                         i = (strcmp(mpp_intrin,"#!/mpp/bin/mppexec\n") == 0)? 32 : 0;
02755                         if (i == 0) {
02756                                 /*
02757                                  * Lack of the header string indicates this is a new style
02758                                  * T3E data file (ie. one produced by cld).  mppldr puts
02759                                  * the header string in for T3E object files, cld does not.
02760                                  * The cld T3E headers are different than mppldr T3E headers.
02761                                  * Basically, T3E headers from mppldr, and T3D headers from
02762                                  * cld and mppldr are identical.  So, the header size is
02763                                  * based on this.
02764                                  */
02765                                 hdrsz = CLD_T3E_AHDR_SIZE;
02766                         }
02767                         else {
02768                                 hdrsz = T3D_AHDR_SIZE;
02769                         }
02770 
02771                         /* Determine if this is a valid T3D or a T3E arith data file */
02772                         ar_mach_type = mpp_intrin[i+5];  /* t3x_exec_t.u_mag_t.pmt */
02773 
02774                         /*
02775                          * MPP code, stack, and data segment identifiers from
02776                          * mpp_intrin[i+3].
02777                          */
02778                         if ((ar_mach_type == T3D || ar_mach_type == T3E) &&
02779                                 mpp_intrin[i+6] == 1 && mpp_intrin[i+7] == 07) {
02780                                 /* magic = 0407? */
02781                                 if(ar_mach_type == T3D) {
02782                                         ar_sim_version = 0;
02783                                 }
02784                                 else {
02785                                         ar_sim_version = 1;
02786                                 }
02787                                 i += 64;
02788                                 while(i < hdrsz) {
02789                                         offset = (mpp_intrin[i+36]<<24) | (mpp_intrin[i+37]<<16) |
02790                                                          (mpp_intrin[i+38]<<8)  | (mpp_intrin[i+39]);
02791                                         /*
02792                                          * Get the stack, code, and data segments using the
02793                                          * segment type field of t3x_segment_t struct.
02794                                          */
02795                                         switch (mpp_intrin[i+16] >> 4) {
02796                                         case SEGT_TEXT:
02797                                                 if (code == NULL && mpp_intrin[i+3]) {
02798                                                         code_segment_id = mpp_intrin[i+3];
02799                                                         if (mpp_intrin[i+16] == 0x15 && offset==hdrsz) 
02800                                                                 code = mpp_intrin;
02801                                                         else
02802                                                                 hdrsz = 0;
02803                                                 }
02804                                                 break;
02805 
02806                                         case SEGT_STACK:
02807                                                 if (stack == NULL && mpp_intrin[i+3]) {
02808                                                         stack_segment_id = mpp_intrin[i+3];
02809                                                         text_size = idf_size-hdrsz;
02810                                                         stack = mpp_intrin + (((text_size+7)>>3)<<3);
02811                                                 }
02812                                           break;
02813 
02814                                         case SEGT_DATA:
02815                                                 if (data == NULL && mpp_intrin[i+3]) {
02816                                                         data_segment_id = mpp_intrin[i+3];
02817                                                         if (mpp_intrin[i+16] == 0x06)
02818                                                                 data = mpp_intrin+offset-hdrsz;
02819                                                         else
02820                                                                 hdrsz = 0;
02821                                                 }
02822                                                 break;
02823                                         }
02824 
02825                                         /* add a.out header sizeof info here, ghg! */
02826                                         i += 10*8; /* 10 words in the t3x_segment_t struct */
02827                                 }
02828 
02829                                 /* do copy down of text over a.out header */
02830                                 if (stack != NULL) {
02831                                   memcpy(mpp_intrin, mpp_intrin+hdrsz, text_size);
02832                                 }
02833                         }
02834                 }
02835         }
02836 
02837         close(idf_fd);
02838 
02839         /* Validate intrinsic evaluation data file contents and version info */
02840 
02841         if (code==NULL || data==NULL || stack==NULL)
02842                 ar_internal_error(2010, __FILE__, __LINE__);
02843 
02844         i=text_size-1;
02845         str = (char*)strnstrn(mpp_intrin, text_size,
02846                                                   "@(#)MPP arith/libm_version ", 27);
02847         if(str != NULL)
02848                 strcpy(AR_libmv2, str+14);
02849         else {
02850                 while(idf_size>0 && (text_size-i)<32) {
02851                         if(strncmp(&mpp_intrin[i], "libm_version", 12) == 0) {
02852                                 strncpy(AR_libmv2, &mpp_intrin[i], text_size-i);
02853                                 AR_libmv2[text_size-i] = '\0';
02854                                 if(strncmp(&mpp_intrin[i-13], "MPP arith", 9))
02855                                         idf_size=-1;
02856                                 break;
02857                         }
02858                         if(mpp_intrin[i] == '\n')
02859                                 mpp_intrin[i]='\0';
02860                         i--;
02861                 }
02862         }
02863         if(idf_size<0 || (text_size-i)>=32)
02864                 ar_internal_error(2010, __FILE__, __LINE__);
02865 
02866         /*
02867          * Validate probable libm.a version that will be used for loading.
02868          *
02869          * We gripe about the version number iff we can find libm_version.o
02870          * in an archive, and we can find the version string, and it does
02871          * not match.  If we can't find a libm.a, or if we have any trouble
02872          * traversing it, or we don't find libm_version.o in it, or we don't
02873          * find the version string, then we don't gripe.
02874          */
02875         if (AR_libmv2[2] != 'x' && AR_libmv2[13+2] != 'x') {
02876                 int                             matched;                /* Version number matched?       */
02877                 char                    buf                             /* To check ar(1) file magic str */
02878                                                 [FILENAME_MAX];
02879                 struct ar_hdr   arh;                    /* An ar(1) archive header           */
02880                 off_t                   fd_off;                 /* Offset in archive file        */
02881                 off_t                   fd_fsize;               /* Size of an archive member     */
02882                 off_t                   fd_namelen;             /* Len of an archive member name */
02883                 char               *name_ptr;           /* Ptr to an archive member name */
02884 
02885                 /*
02886                  * Open the libm archive that matches this arith data file.
02887                  */
02888                 strcpy(&fname[v], "/libm.a");
02889                 fd = open(fname, O_RDONLY);
02890                 if (fd < 0) {
02891                         strcpy(&fname[v], "/../libm.a");
02892                         fd = open(fname, O_RDONLY);
02893                 }
02894 
02895                 /*
02896                  * If this is an ar(1) archive, then traverse it, looking
02897                  * for the "libm_version.o" file.
02898                  */
02899                 if (fd >= 0 &&
02900                         read(fd, buf, SARMAG) == SARMAG &&
02901                         strncmp(buf, ARMAG, SARMAG) == 0) {
02902 
02903                         matched = 1;
02904                         fd_off = SARMAG;
02905 
02906                         while (1) {
02907                                 /*
02908                                  * If there are no more archive members, we're done.
02909                                  */
02910                                 if (read(fd, &arh, AR_HDR_SIZE) != AR_HDR_SIZE) {
02911                                         fd_off = 0;
02912                                         break;
02913                                 }
02914 
02915                                 /*
02916                                  * Check this archive filename.  If we've found the
02917                                  * "libm_version.o" file, stop looking; otherwise,
02918                                  * skip this and go on to the next one.
02919                                  */
02920                                 if (strncmp(arh.ar_name, "#1/", 3) != 0) {
02921                                         name_ptr = arh.ar_name;
02922                                 }
02923                                 else {
02924                                         if (sscanf(&arh.ar_name[3], "%d", &fd_namelen) != 1 ||
02925                                                 read(fd, buf, fd_namelen) != fd_namelen) {
02926                                                 fd_off = 0;
02927                                                 break;
02928                                         }
02929                                         name_ptr = buf;
02930                                 }
02931 
02932                                 if (strncmp(name_ptr, "libm_version.o", 14) == 0) {
02933                                         break;
02934                                 }
02935 
02936                                 if (sscanf(arh.ar_size, "%d", &fd_fsize) != 1) {
02937                                         fd_off = 0;
02938                                         break;
02939                                 }
02940 
02941                                 fd_off = (fd_off + AR_HDR_SIZE + fd_fsize + 1) & (~1);
02942                                 if (lseek(idf_fd, fd_off, SEEK_SET) != fd_off) {
02943                                         fd_off = 0;
02944                                         break;
02945                                 }
02946                         }
02947 
02948                         /*
02949                          * If we've found the "libm_version.o" file, then search
02950                          * in it for the version string.  It has to match, or we
02951                          * gripe, but it may be wildcarded with 'x' characters.
02952                          */
02953                         if (fd_off != 0) {
02954                                 if (sscanf(arh.ar_size, "%d", &fd_fsize) != 1) {
02955                                         fd_off = 0;
02956                                 }
02957                         }
02958 
02959                         if (fd_off != 0) {
02960                                 if (strncmp(arh.ar_name, "#1/", 3) == 0) {
02961                                         fd_fsize -= fd_namelen;
02962                                 }
02963 
02964                                 if (fd_fsize > sizeof(buf)) {
02965                                         fd_fsize = sizeof(buf);
02966                                 }
02967 
02968                                 if (read(fd, buf, fd_fsize) == fd_fsize) {
02969                                         str = (char*)strnstrn(buf, (fd_fsize - 9),
02970                                                                                   "@(#)libm_version", 16);
02971                                         if (str != NULL) {
02972                                                 str += 17;
02973                                                 for (i = 0; matched && i < 8; i += 2)
02974                                                   if (str[i] != 'x' &&
02975                                                           AR_libmv2[13 + i] != 'x' &&
02976                                                           str[i] != AR_libmv2[13 + i])
02977                                                           matched = 0;
02978 
02979                                         }
02980                                 }
02981                         }
02982 
02983                         if (!matched) {
02984                                 PRINTMSG(0, 2016, Warning, 0, "MPP", "0", "", "");
02985                         }
02986                 }
02987         }
02988 
02989         ar_state_register.ar_float_format = AR_IEEE_FLOATING_POINT;
02990         ar_state_register.ar_128bit_format = AR_128BIT_EXTENDED_DOUBLE;
02991         ar_state_register.ar_rounding_mode = AR_ROUND_NEAREST;
02992         ar_state_register.ar_underflow_mode = AR_UNDERFLOW_TO_PLUS_ZERO;
02993 }
02994 
02995 static void
02996 load_mpp_word(result, segment, offset)
02997 AR_INT_64*      result;
02998 long            segment;
02999 long            offset;
03000 {
03001 
03002         if (segment == data_segment_id) {
03003                 memcpy(result, data+offset*8, 8);
03004                 return;
03005         }
03006 
03007         else if (segment == stack_segment_id) {
03008                 if(offset < (MPP_STACK_SIZE+MPP_MAX_ARGS*5+6)) {
03009                         memcpy(result, stack+offset*8, 8);
03010                         return;
03011                 }
03012         }
03013 
03014         else {
03015                 if(segment>=0 && segment < n_external_addresses &&
03016                    external_address[segment] != NULL) {
03017                     if(external_length[segment] > offset) {
03018                                 memcpy(result, external_address[segment]+offset*8, 8);
03019                                 return;
03020                     }
03021                     /* Allow up to 8 words of unusable slop to be loaded */
03022                     /* See first vector load in memchr.s where this is needed */
03023                     if(external_length[segment] > (offset-8)) {
03024                                 result->part1 = result->part2 = 0xf0f0;
03025                                 result->part3 = result->part4 = 0xf0f0;
03026                                 return;
03027                     }
03028                 }
03029         }
03030 
03031         ar_internal_error(2012, __FILE__, __LINE__);
03032 }
03033 
03034 static void
03035 store_mpp_word(segment, offset, result)
03036 long            segment;
03037 long            offset;
03038 AR_INT_64*      result;
03039 {
03040 
03041         if (segment == data_segment_id) {
03042                 memcpy(data+offset*8, result, 8);
03043                 return;
03044         }
03045 
03046         else if (segment == stack_segment_id) {
03047                 if(offset < (MPP_STACK_SIZE+MPP_MAX_ARGS*5+6)) {
03048                         memcpy(stack+offset*8, result, 8);
03049                         return;
03050                 }
03051         }
03052 
03053         else {
03054                 if(segment < n_external_addresses &&
03055                    external_address[segment] != NULL) {
03056                     if(external_length[segment] >= offset) {
03057                                 memcpy(external_address[segment]+offset*8, result, 8);
03058                                 return;
03059                     }
03060                     /* Allow ORE (without actual store) iff value matches that
03061                      * returned by load_pvp_word above.
03062                      */
03063                     if(external_length[segment] > (offset-8) &&
03064                        result->part1==0xf0f0 && result->part2==0xf0f0 &&
03065                        result->part3==0xf0f0 && result->part4==0xf0f0) {
03066                         return;
03067                     }
03068                 }
03069         }
03070 
03071         ar_internal_error(2012, __FILE__, __LINE__);
03072 }
03073 
03074 #endif
03075 
03076 static char USMID [] = "\n%Z%%M%        %I%     %G% %U%\n";
03077 static char rcsid [] = "$Id: mpp_sim.c,v 1.1.1.1 2002-05-22 20:06:19 dsystem Exp $";
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines