This is macros.h in view mode; [Download] [Up]
/* * PCN Abstract Machine Emulator * Authors: Steve Tuecke and Ian Foster * Argonne National Laboratory * * Please see the DISCLAIMER file in the top level directory of the * distribution regarding the provisions under which this software * is distributed. * * macros.h - Macros for accessing various structures, etc. */ /* * Some general purpose macros */ #if !defined(MAX) #define MAX(A,B) (((A) > (B)) ? (A) : (B)) #define MIN(A,B) (((A) < (B)) ? (A) : (B)) #endif /* * Some cell handling macros... */ #define IsRef(C) ((*((u_int_t *) (C)) & 3) == 0) #define IsType(C,Tag) (((data_header_t *)(C))->tag == (Tag)) #define IsUndef(C) (((data_header_t *)(C))->tag == UNDEF_TAG) #define IsRref(C) (((data_header_t *)(C))->tag == RREF_TAG) #define IsTuple(C) (((data_header_t *)(C))->tag == TUPLE_TAG) #define IsInt(C) (((data_header_t *)(C))->tag == INT_TAG) #define IsString(C) (((data_header_t *)(C))->tag == STRING_TAG) #define IsDouble(C) (((data_header_t *)(C))->tag == DOUBLE_TAG) #define IsTrailer(C) (((data_header_t *)(C))->tag == TRAILER_TAG) #define IsProcRecord(C) (((data_header_t *)(C))->tag ==PROC_RECORD_TAG) #define IsValueNote(C) (((data_header_t *)(C))->tag == VALUE_NOTE_TAG) #define IsStream(C) (((data_header_t *) (C))->tag == STREAM_TAG) #define IsUnknown(C) (IsUndef(C) || IsRref(C)) #define SuspensionsAt(C) (((undef_t *)(C))->suspensions != 0) #define DHCellTag(C) ((data_header_t *)(C))->tag #define DHCellMark(C) ((data_header_t *)(C))->mark #define DHCellSize(C) ((data_header_t *)(C))->size #define IsMarked(Ptr) (((data_header_t *)(Ptr))->mark) #define RrefNotRead(C) \ (((rref_t *)(C))->value_return_irt == RREF_NOT_READ_IRT) /* * Stuff for dealing with variable suspension queues */ #define LOW_PART_PTR_BITS 12 #define LOW_PART_PTR_MASK 0xFFF #define GetHighPart(Ptr) (((u_int_t)(Ptr)) >> LOW_PART_PTR_BITS) #define GetLowPart(Ptr) (((u_int_t)(Ptr)) & LOW_PART_PTR_MASK) /* * SuspendedProcs() * * Macro for retrieving the pointer to a suspension queue that is * hung off an undef or rref. 'C' is assumed to be a pointer * to an undef or rref. */ #define SuspendedProcs(C) \ ((proc_record_t *) (IsUndef(C) \ ? ( (((undef_t *)(C))->high_part_ptr << LOW_PART_PTR_BITS) \ | ((undef_t *)(C))->low_part_ptr ) \ : ( (((rref_t *)(C))->high_part_ptr << LOW_PART_PTR_BITS) \ | ((rref_t *)(C))->low_part_ptr ) ) ) /* * SetSuspendedProcs() * * Macro for setting the pointer in undef or rref 'C' to the * suspension queue pointed to by 'Proc'. */ #define SetSuspendedProcs(C, Proc) \ { \ if (IsUndef(C)) \ { \ ((undef_t *)(C))->high_part_ptr = GetHighPart(Proc); \ ((undef_t *)(C))->low_part_ptr = GetLowPart(Proc); \ ((undef_t *)(C))->suspensions = 1; \ } \ else /* IsRref(C) */ \ { \ ((rref_t *)(C))->high_part_ptr = GetHighPart(Proc); \ ((rref_t *)(C))->low_part_ptr = GetLowPart(Proc); \ ((rref_t *)(C))->suspensions = 1; \ } \ } /* * Stuff to deal with double word alignment */ #ifdef PCN_ALIGN_DOUBLES #if CELL_SIZE == 4 #define DOUBLE_WORD_MASK 0x07 #define DOUBLE_WORD_SIZE 8 #define DoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 0) #define OddWordDoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 4) #else /* CELL_SIZE == 8 */ #define DOUBLE_WORD_MASK 0x0f #define DOUBLE_WORD_SIZE 16 #define DoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 0) #define OddWordDoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 8) #endif #define PCN_ALIGN_DOUBLES_PAD 1 /* * If alignment of doubles is required, then we might need to align all * data structures on an odd word. (This is so that after the * header word, doubles will end up double word aligned.) */ #define AlignDoubleOnOddWord(Type, Ptr, Pad) \ { \ for (Pad = 0; \ !OddWordDoubleAligned(Ptr); \ Pad++, \ Ptr = Type (((char *) (Ptr)) + 1)) \ ; \ } #define AlignDoubleOnEvenWord(Type, Ptr, Pad) \ { \ for (Pad = 0; \ !DoubleAligned(Ptr); \ Pad++, \ Ptr = Type (((char *) (Ptr)) + 1)) \ ; \ } #else /* PCN_ALIGN_DOUBLES */ #define AlignDoubleOnOddWord(Type, Ptr, Pad) #define AlignDoubleOnEvenWord(Type, Ptr, Pad) #define PCN_ALIGN_DOUBLES_PAD 0 #endif /* PCN_ALIGN_DOUBLES */ /* * Macros to compute sizes of the various data structures, with * and without the trailer cell. * * StringSizeToCells() is in src/include/pcn_structs.h */ #define RrefSizeWithTrailer() RrefSize #define RrefSizeWithoutTrailer() (RrefSizeWithTrailer() - 1) #define UndefSizeWithTrailer() UndefSize #define UndefSizeWithoutTrailer() (UndefSizeWithTrailer() - 1) #define DoubleSizeWithoutTrailer(N) (1 + CELLS_PER_DOUBLE*(N)) #define DoubleSizeWithTrailer(N) (DoubleSizeWithoutTrailer(N) + 1) #define EmptyListSizeWithoutTrailer() 1 #ifdef PCN_ALIGN_DOUBLES #define EmptyListSizeWithTrailer() 2 #define TupleSizeWithoutTrailer(N) (1 + (N) + ((N)%2)) #define TupleSizeWithTrailer(N) (TupleSizeWithoutTrailer(N) + 1) #define IntSizeWithoutTrailer(N) (1 + (N) + ((N)%2)) #define StringSizeWithoutTrailer(N) (1 + StringSizeToCells(N) \ + (StringSizeToCells(N)%2)) #else /* PCN_ALIGN_DOUBLES */ #define EmptyListSizeWithTrailer() 1 #define TupleSizeWithoutTrailer(N) (1 + (N)) #define TupleSizeWithTrailer(N) (N == 0 ? (1) : \ (TupleSizeWithoutTrailer(N) + 1)) #define IntSizeWithoutTrailer(N) (1 + (N)) #define StringSizeWithoutTrailer(N) (1 + StringSizeToCells(N)) #endif /* PCN_ALIGN_DOUBLES */ #define IntSizeWithTrailer(N) (IntSizeWithoutTrailer(N) + 1) #define StringSizeWithTrailer(N) (StringSizeWithoutTrailer(N) + 1) /* * Dereference() * * Fill New with the dereferenced cell_t* of Old. */ #define Dereference(Type, Old, New) \ /* \ cell_t *Old; \ Type New; \ */ \ { \ New = Type (Old); \ while(IsRef(New)) \ New = Type (*((cell_t *) (New))); \ } /* * Garbage collection handling macros */ #define NeedToGC() (_p_heap_ptr >= _p_heap_gc_top) #define NeedToGCWithSize(Size) \ ( ((_p_heap_ptr + (Size)) > _p_heap_hard_top) /* normal case */ \ || ((_p_heap_ptr + (Size)) < _p_heap_ptr) ) /* wraparound case */ #define DoGC() _p_collect_garbage(_p_gc_slack) #define DoGCWithSize(Size) _p_collect_garbage(Size) #define TryGC() if (NeedToGC()) DoGC(); #define TryGCWithSize(Size) \ { \ int_t __TryGCWithSize_Size = (Size); \ if (NeedToGCWithSize(__TryGCWithSize_Size)) \ { \ DoGCWithSize(__TryGCWithSize_Size); \ } \ } #define CalcHeapTops() \ { \ _p_heap_hard_top = _p_heap_cancel_top - CANCEL_SIZE; \ _p_heap_gc_top = _p_heap_hard_top - _p_gc_slack; \ } #define PushGCReference(TheGCRef) \ _p_gc_ref_stack[_p_gc_ref_stack_top++] = (TheGCRef); #define PopGCReference(NumToPop) _p_gc_ref_stack_top -= (NumToPop); /* * Macros used mostly by the garbage pcollector, but occasionally by * debugging code as well... */ #define OnHeap(Ptr) ((_p_heap_bottom <= (Ptr)) && ((Ptr) <= _p_heap_hard_top)) #define OffHeap(Ptr) (((Ptr) < _p_heap_bottom) || (_p_heap_hard_top < (Ptr))) #if CELL_SIZE == 8 #define PTR_REVERSED_MASK 0xFFFFFFFFFFFFFFFD #else #define PTR_REVERSED_MASK 0xFFFFFFFD #endif #define ClearReversed(Ptr) ((cell_t *) (((u_int_t) (Ptr)) & PTR_REVERSED_MASK)) #define SetReversed(Ptr) ((cell_t *) (((u_int_t) (Ptr)) | 2)) #define IsReversed(Ptr) ((*((u_int_t *) (Ptr)) & 3) == 2) #define IsGCRef(Ptr) ((*((u_int_t) (Ptr)) & 1) == 0) #define ReversePointer(SOURCE, TARGET) \ { \ *((cell_t **) (SOURCE)) = *((cell_t **) (TARGET)); \ *((cell_t **) (TARGET)) = SetReversed(SOURCE); \ } /* * Message handling macros */ #ifdef PARALLEL #if ASYNC_MSG == 1 #define TryMSG() if (_p_multiprocessing && _p_msg_avail) \ _p_process_messages(RCV_NOBLOCK); #define TryMSGNoSkip() TryMSG() #else /* ASYNC_MSG */ #define TryMSG() \ if (_p_multiprocessing && _p_msg_skip-- <= 0) \ { \ _p_process_messages(RCV_NOBLOCK); \ _p_msg_skip = MSG_SKIP_POLL; \ } #define TryMSGNoSkip() \ if (_p_multiprocessing) _p_process_messages(RCV_NOBLOCK); #endif /* ASYNC_MSG */ #else /* PARALLEL */ #define TryMSG() #define TryMSGNoSkip() #endif /* PARALLEL */ /* * HeaderCell() * * Build a header cell */ #define HeaderCell(C,Tag,Size) \ { \ ((data_header_t *) (C))->tag = (Tag); \ ((data_header_t *) (C))->mark = 0; \ ((data_header_t *) (C))->size = (Size); \ } #define TrailerCell(C,Offset) HeaderCell(C,TRAILER_TAG,Offset) /* * BuildUndef() * * Build an Undef on the heap and place a reference to it (with * a Ref tag) into the passed cell. * * GC_ALERT: This macro may induce garbage collection */ #define BuildUndefNoGC(Type, C) \ /* \ Type C; \ */ \ { \ C = Type _p_heap_ptr; \ ((undef_t *) (_p_heap_ptr))->tag = UNDEF_TAG; \ ((undef_t *) (_p_heap_ptr))->mark = 0; \ ((undef_t *) (_p_heap_ptr))->suspensions = 0; \ ((undef_t *) (_p_heap_ptr))->trailer_tag = UNDEF_TRAILER_TAG; \ _p_heap_ptr += UndefSizeWithTrailer(); \ } #define BuildUndef(Type, C) \ /* \ Type C; \ */ \ { \ TryGCWithSize(UndefSizeWithTrailer()); \ BuildUndefNoGC(Type, C); \ } /* * BuildRref() * * Build a remote reference on the heap using the passwd Weight, * Location, and Node. Place a reference to it (with a remote * reference tag) into the passed cell. * * GC_ALERT: This macro may induce garbage collection */ #define BuildRref(Type, C, Weight, Location, Node) \ /* \ Type C; \ u_int_t Weight; \ u_int_t Location; \ u_int_t Node; \ */ \ { \ TryGCWithSize(RrefSizeWithTrailer()); \ HeaderCell(_p_heap_ptr, RREF_TAG, 0); \ C = Type _p_heap_ptr; \ ((rref_t *) (_p_heap_ptr))->tag = RREF_TAG; \ ((rref_t *) (_p_heap_ptr))->mark = 0; \ ((rref_t *) (_p_heap_ptr))->suspensions = 0; \ ((rref_t *) (_p_heap_ptr))->node = (Node); \ ((rref_t *) (_p_heap_ptr))->location = (Location); \ ((rref_t *) (_p_heap_ptr))->weight = (Weight); \ ((rref_t *) (_p_heap_ptr))->value_return_irt = RREF_NOT_READ_IRT; \ ((rref_t *) (_p_heap_ptr))->trailer_tag = RREF_TRAILER_TAG; \ _p_heap_ptr += RrefSizeWithTrailer(); \ } /* * BuildString() * * Build an string on the heap and place a pointer to it * into the passed cell pointer. The length should *not* * include the null termination. (Thus, strlen() will give the * correct length.) * * GC_ALERT: This macro may induce garbage collection */ #define BuildString(Type, C, Str, Len) \ /* \ Type C; \ char_t *Str; \ int_t Len; \ */ \ { \ int_t __BuildString_Len = (Len) + 1; \ int_t __BuildString_Size = StringSizeWithoutTrailer(__BuildString_Len); \ TryGCWithSize(StringSizeWithTrailer(__BuildString_Len)); \ HeaderCell(_p_heap_ptr, STRING_TAG, __BuildString_Len); \ C = Type _p_heap_ptr; \ memcpy((_p_heap_ptr + 1), Str, __BuildString_Len); \ _p_heap_ptr += __BuildString_Size; \ TrailerCell(_p_heap_ptr, __BuildString_Size); \ _p_heap_ptr++; \ } /* * BuildInt() * * Build an integer on the heap and place a pointer to it * into the passed cell pointer. * * GC_ALERT: This macro may induce garbage collection */ #define BuildInt(Type, C, Int) \ /* \ Type C; \ int_t Int; \ */ \ { \ int_t __BuildInt_Size = IntSizeWithoutTrailer(1); \ TryGCWithSize(IntSizeWithTrailer(1)); \ HeaderCell(_p_heap_ptr, INT_TAG, 1); \ C = Type _p_heap_ptr; \ *((int_t *) (_p_heap_ptr + 1)) = (Int); \ _p_heap_ptr += __BuildInt_Size; \ TrailerCell(_p_heap_ptr, __BuildInt_Size); \ _p_heap_ptr++; \ } /* * BuildDouble() * * Build an double on the heap and place a pointer to it * into the passed cell pointer. * * GC_ALERT: This macro may induce garbage collection */ #define BuildDouble(Type, C, D) \ /* \ Type C; \ double_t D; \ */ \ { \ int_t __BuildDouble_Size = DoubleSizeWithoutTrailer(1); \ TryGCWithSize(DoubleSizeWithTrailer(1)); \ HeaderCell(_p_heap_ptr, DOUBLE_TAG, 1); \ C = Type _p_heap_ptr; \ *((double_t *) (_p_heap_ptr + 1)) = (D); \ _p_heap_ptr += __BuildDouble_Size; \ TrailerCell(_p_heap_ptr, __BuildDouble_Size); \ _p_heap_ptr++; \ } /* * BuildTuple() * * Build a tuple on the heap and place a * pointer to it into the passed cell pointer. * Does not put anything into the tuple's arguments. * Rather, _p_structure_ptr is set to the first argument, and * can be used to fill in the tuple. * * GC_ALERT: This macro may induce garbage collection */ #ifdef PCN_ALIGN_DOUBLES #define BuildTupleTrailer(Arity) \ TrailerCell(_p_heap_ptr, __BuildTuple_Size); \ _p_heap_ptr++; #else /* PCN_ALIGN_DOUBLES */ #define BuildTupleTrailer(Arity) \ if ((Arity) > 0) \ { \ TrailerCell(_p_heap_ptr, __BuildTuple_Size); \ _p_heap_ptr++; \ } #endif /* PCN_ALIGN_DOUBLES */ #define BuildTuple(Type, C, Arity) \ /* \ Type C; \ int_t Arity; \ */ \ { \ int_t __BuildTuple_Size = TupleSizeWithoutTrailer(Arity); \ TryGCWithSize(TupleSizeWithTrailer(Arity)); \ HeaderCell(_p_heap_ptr, TUPLE_TAG, Arity); \ C = Type _p_heap_ptr; \ _p_structure_start_ptr = _p_heap_ptr; \ _p_structure_ptr = (_p_heap_ptr + 1); \ _p_heap_ptr += __BuildTuple_Size; \ BuildTupleTrailer(Arity); \ } /* * BuildEmptyList() * * Build an empty list (a tuple with arity 0) on the heap and place a * pointer to it into the passed cell (pointer). * * GC_ALERT: This macro may induce garbage collection */ #ifdef PCN_ALIGN_DOUBLES #define BuildEmptyList(Type, C) \ /* \ Type C; \ */ \ { \ TryGCWithSize(EmptyListSizeWithTrailer()); \ HeaderCell(_p_heap_ptr, TUPLE_TAG, 0); \ C = Type _p_heap_ptr++; \ TrailerCell(_p_heap_ptr, 1); \ _p_heap_ptr++; \ } #else /* PCN_ALIGN_DOUBLES */ #define BuildEmptyList(Type, C) \ /* \ Type C; \ */ \ { \ TryGCWithSize(EmptyListSizeWithTrailer()); \ HeaderCell(_p_heap_ptr, TUPLE_TAG, 0); \ C = Type _p_heap_ptr++; \ } #endif /* PCN_ALIGN_DOUBLES */ #ifdef PDB #define PDB_EnqueueProcess(Proc) _pdb_enqueue_process(Proc) #define PDB_DequeueProcess(Proc) _pdb_dequeue_process(Proc) #else /* PDB */ #define PDB_EnqueueProcess(Proc) #define PDB_DequeueProcess(Proc) #endif /* PDB */ /* * EnqueueProcess() * * Enqueue the passed process (Proc) onto the passed queue (QF,QB). */ #define EnqueueProcess(Proc, QF, QB) \ /* \ proc_record_t *Proc, *QF, *QB; \ */ \ { \ if (QF == (proc_record_t *) NULL) \ { \ QF = QB = Proc; \ (Proc)->next = (proc_record_t *) NULL; \ } \ else \ { \ (Proc)->next = (proc_record_t *) NULL; \ (QB)->next = Proc; \ QB = Proc; \ } \ } /* * EnqueueProcessAtFront() * * Enqueue the passed process (Proc) onto the front of the * passed queue (QF,QB). */ #define EnqueueProcessAtFront(Proc, QF, QB) \ /* \ proc_record_t *Proc, *QF, *QB; \ */ \ { \ if (QF == (proc_record_t *) NULL) \ { \ QF = QB = Proc; \ (Proc)->next = (proc_record_t *) NULL; \ } \ else \ { \ (Proc)->next = (proc_record_t *) QF; \ QF = Proc; \ } \ } /* * DequeueProcess() * * Dequeue the first process from the passed queue (QF,QB), and place * it in the passed process (Proc). */ #define DequeueProcess(Proc, QF, QB) \ /* \ proc_record_t *Proc, *QF, *QB; \ */ \ { \ Proc = QF; \ if (QF == QB) \ QF = QB = (proc_record_t *) NULL; \ else \ QF = (QF)->next; \ } /* * AppendProcessQueue() * * Append queue 2 (Q2F,Q2B) to the end of queue 1 (Q1F,Q1B). */ #define AppendProcessQueue(Q1F, Q1B, Q2F, Q2B) \ /* \ proc_record_t *Q1F, *Q1B, *Q2F, *Q2B; \ */ \ { \ if (Q1F == (proc_record_t *) NULL) \ { \ Q1F = Q2F; \ Q1B = Q2B; \ } \ else \ { \ (Q1B)->next = Q2F; \ Q1B = Q2B; \ } \ Q2F = Q2B = (proc_record_t *) NULL; \ } #define ProcessQueueIsEmpty(QF, QB) QF == (proc_record_t *) NULL /* * EnqueueSuspension() * * Enqueue the passed process onto the suspension queue for the * passed variable (Undef or Rref). * * Suspension queues are circular queues, to facilitate easy appending * to the active queue. */ #define EnqueueSuspension(Proc, C) \ /* \ proc_record_t *Proc; \ cell_t *Cp; \ */ \ { \ if (SuspensionsAt(C)) \ { \ proc_record_t *__CP = SuspendedProcs(C); \ (Proc)->next = (__CP)->next; \ (__CP)->next = Proc; \ } \ else \ { \ SetSuspendedProcs(C, Proc); \ (Proc)->next = Proc; \ } \ } #define IncrementCounter(Offset, I) *((int_t *) (Offset)) += (I); #define Fail() \ { \ program_counter = failure_label; \ break; \ } /* * SuspendOn() * * Note: SuspendOn is meant to break out of the emulator's switch. * Therefore, SuspendOn should never be used inside a loop in the * emulator. */ #ifdef PARALLEL #define SuspendOn(C) \ /* \ cell_t *C; \ */ \ { \ if ( IsRref(C) && RrefNotRead(C)) \ _p_send_read(C); \ if (_p_suspension_var == (cell_t *) NULL) \ _p_suspension_var = C; \ else if (_p_suspension_var != C) \ _p_suspension_var = (cell_t *) -1; \ program_counter = failure_label; \ break; \ } #else /* PARALLEL */ /* \ cell_t *C; \ */ \ #define SuspendOn(C) \ { \ if (_p_suspension_var == (cell_t *) NULL) \ _p_suspension_var = C; \ else if (_p_suspension_var != C) \ _p_suspension_var = (cell_t *) -1; \ program_counter = failure_label; \ break; \ } #endif /* PARALLEL */ /* * DerefAndCheckSusp() * * Dereference the Old pointer, and suspend * if it dereferences to an Unknown. */ #define DerefAndCheckSusp(Type, Old, New) \ /* \ cell_t *Old; \ Type New; \ */ \ { \ Dereference(Type, Old, New); \ if (IsUnknown(New)) \ { \ SuspendOn(New); \ } \ } /* * Arith() * * Macro for doing arithmatic operations. Supply your favorite operator. * It builds room on the heap for the result. * This is meant to be used by emulate.c. */ #define Arith(Op) \ { \ cp1 = _p_a_reg[instr->I_ARITH_LSRC_R]; \ cp2 = _p_a_reg[instr->I_ARITH_RSRC_R]; \ if (IsInt(cp1) && IsInt(cp2)) \ { \ i1 = *((int_t *) (cp1 + 1)); \ i2 = *((int_t *) (cp2 + 1)); \ BuildInt((cell_t *), _p_a_reg[instr->I_ARITH_DEST_R], (i1 Op i2)); \ } \ else \ { \ if (IsDouble(cp1)) \ d1 = *((double_t *) (cp1 + 1)); \ else if (IsInt(cp1)) \ d1 = (double_t) *((int_t *) (cp1 + 1)); \ else \ { \ d1 = 1.0; \ fprintf(_p_stdout, \ "(%lu,%lu) Warning: arithmetic operation on non-numeric value in %s:%s\n", \ (unsigned long) _p_my_id, (unsigned long) _p_reduction, \ _p_current_proc->proc->module_name, \ _p_current_proc->proc->proc_name); \ } \ if (IsDouble(cp2)) \ d2 = *((double_t *) (cp2 + 1)); \ else if (IsInt(cp2)) \ d2 = (double_t) *((int_t *) (cp2 + 1)); \ else \ { \ d2 = 1.0; \ fprintf(_p_stdout, \ "(%lu,%lu) Warning: arithmetic operation on non-numeric value in %s:%s\n", \ (unsigned long) _p_my_id, (unsigned long) _p_reduction, \ _p_current_proc->proc->module_name, \ _p_current_proc->proc->proc_name); \ } \ BuildDouble((cell_t *), _p_a_reg[instr->I_ARITH_DEST_R], \ (double_t) (d1 Op d2)); \ } \ } /* * Compare() * * Macro for doing comparison operations. Supply your favorite operator. * It causes a Fail() if the comparison is false. * This is meant to be used by emulate.c. */ #define Compare(Op) \ { \ DerefAndCheckSusp((cell_t *), _p_a_reg[instr->I_COMPARE_LSRC_R], cp1); \ DerefAndCheckSusp((cell_t *), _p_a_reg[instr->I_COMPARE_RSRC_R], cp2); \ _p_a_reg[instr->I_COMPARE_LSRC_R] = cp1; \ _p_a_reg[instr->I_COMPARE_RSRC_R] = cp2; \ if (IsInt(cp1) && IsInt(cp2)) \ { \ if (!(*((int_t *) (cp1 + 1)) Op *((int_t *) (cp2 + 1)))) \ { \ Fail(); \ } \ } \ else if (IsDouble(cp1) && IsDouble(cp2)) \ { \ if (!(*((double_t *) (cp1 + 1)) Op *((double_t *) (cp2 + 1)))) \ { \ Fail(); \ } \ } \ else if (IsInt(cp1) && IsDouble(cp2)) \ { \ if (!(*((int_t *) (cp1 + 1)) Op *((double_t *) (cp2 + 1)))) \ { \ Fail(); \ } \ } \ else if (IsDouble(cp1) && IsInt(cp2)) \ { \ if (!(*((double_t *) (cp1 + 1)) Op *((int_t *) (cp2 + 1)))) \ { \ Fail(); \ } \ } \ else \ { \ fprintf(_p_stdout, \ "(%lu,%lu) Warning: comparison operation on non-numeric value in %s:%s\n", \ (unsigned long) _p_my_id, (unsigned long) _p_reduction, \ _p_current_proc->proc->module_name, \ _p_current_proc->proc->proc_name); \ Fail(); \ } \ } /* Arguments for foreign function calls */ #define F_REG_1 _p_f_reg[0] #define F_REG_2 F_REG_1,_p_f_reg[1] #define F_REG_4 F_REG_2,_p_f_reg[2],_p_f_reg[3] #define F_REG_8 F_REG_4,_p_f_reg[4],_p_f_reg[5],_p_f_reg[6],_p_f_reg[7] #define F_REG_16 F_REG_8,_p_f_reg[8],_p_f_reg[9],_p_f_reg[10],\ _p_f_reg[11],_p_f_reg[12],_p_f_reg[13],_p_f_reg[14],_p_f_reg[15] #define F_REG_32 F_REG_16,_p_f_reg[16],_p_f_reg[17],_p_f_reg[18],\ _p_f_reg[19],_p_f_reg[20],_p_f_reg[21],_p_f_reg[22],_p_f_reg[23],\ _p_f_reg[24],_p_f_reg[25],_p_f_reg[26],_p_f_reg[27],_p_f_reg[28],\ _p_f_reg[29],_p_f_reg[30],_p_f_reg[31] #define F_REG_64 F_REG_32,_p_f_reg[32],_p_f_reg[33],_p_f_reg[34],\ _p_f_reg[35],_p_f_reg[36],_p_f_reg[37],_p_f_reg[38],_p_f_reg[39],\ _p_f_reg[40],_p_f_reg[41],_p_f_reg[42],_p_f_reg[43],_p_f_reg[44],\ _p_f_reg[45],_p_f_reg[46],_p_f_reg[47],_p_f_reg[48],_p_f_reg[49],\ _p_f_reg[50],_p_f_reg[51],_p_f_reg[52],_p_f_reg[53],_p_f_reg[54],\ _p_f_reg[55],_p_f_reg[56],_p_f_reg[57],_p_f_reg[58],_p_f_reg[59],\ _p_f_reg[60],_p_f_reg[61],_p_f_reg[62],_p_f_reg[63] #define IrtIndex(I) (((irt_t *) (I)) - _p_irt) #define IrtAddress(N) (_p_irt + (N)) #ifdef DEBUG #define GlobalDebug(Level) \ ((_p_global_dl >= (Level)) && (_p_reduction >= _p_start_em_debug)) #define EmDebug(Level) \ ((_p_em_dl >= (Level)) && (_p_reduction >= _p_start_em_debug)) #define GCDebug(Level) \ ((_p_gc_dl >= (Level)) && (_p_reduction >= _p_start_em_debug)) #define ParDebug(Level) \ ((_p_par_dl >= (Level)) && (_p_reduction >= _p_start_em_debug)) #endif /* DEBUG */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.