Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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®64.part1; 01392 R[rc].part2 = R[ra].part2®64.part2; 01393 R[rc].part3 = R[ra].part3®64.part3; 01394 R[rc].part4 = R[ra].part4®64.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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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*)®64, &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(®64, 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(®64, 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, ®64); 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(®64, 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(®64, 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, ®64); 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 $";