.file_attr libGroup="crt"; .file_attr libName="libc"; .file_attr libFunc="____errno"; .file_attr FuncName="____errno"; .file_attr libFunc="___lib_get_context_rec"; .file_attr FuncName="___lib_get_context_rec"; .file_attr libFunc="___lib_get_errno_addr"; .file_attr FuncName="___lib_get_errno_addr"; .file_attr libFunc="___lib_setup_ctxt"; .file_attr FuncName="___lib_setup_ctxt"; .file_attr libFunc="__get_tlv_data"; .file_attr FuncName="__get_tlv_data"; .file_attr prefersMem="internal"; .file_attr prefersMemNum="30"; .file_attr libGroup="stdlib.h"; .file_attr libFunc="rand"; .file_attr libFunc="strtod"; .file_attr libFunc="strtodf"; .file_attr libFunc="_strtodf"; .file_attr libFunc="___strtodfDD"; .file_attr libFunc="___strtodfDP"; .file_attr libFunc="___strtodfPD"; .file_attr libFunc="___strtodfPP"; .file_attr libFunc="strtol"; .file_attr libFunc="_strtol"; .file_attr libFunc="___strtolDD"; .file_attr libFunc="___strtolDP"; .file_attr libFunc="___strtolPD"; .file_attr libFunc="___strtolPP"; .file_attr libFunc="strtoul"; .file_attr libFunc="_strtoul"; .file_attr libFunc="___strtoulDD"; .file_attr libFunc="___strtoulDP"; .file_attr libFunc="___strtoulPD"; .file_attr libFunc="___strtoulPP"; .file_attr libFunc="_rand"; .file_attr libFunc="srand"; .file_attr libFunc="_srand"; .file_attr libGroup="string.h"; .file_attr libFunc="strtok"; .file_attr libFunc="_strtok"; .file_attr libFunc="___strtokDD"; .file_attr libFunc="___strtokDP"; .file_attr libFunc="___strtokPD"; .file_attr libFunc="___strtokPP"; .file_attr libGroup="math.h"; .file_attr libFunc="acos"; .file_attr libFunc="acosf"; .file_attr libFunc="_acosf"; .file_attr libFunc="asin"; .file_attr libFunc="asinf"; .file_attr libFunc="_asinf"; .file_attr libFunc="frexp"; .file_attr libFunc="_frexp"; .file_attr libFunc="_frexpf"; .file_attr libFunc="___frexpfD"; .file_attr libFunc="log"; .file_attr libFunc="_log"; .file_attr libFunc="logd"; .file_attr libFunc="_logd"; .file_attr libFunc="log10"; .file_attr libFunc="_log10"; .file_attr libFunc="log10d"; .file_attr libFunc="_log10d"; .file_attr libFunc="cosh"; .file_attr libFunc="coshf"; .file_attr libFunc="_coshf"; .file_attr libFunc="sinh"; .file_attr libFunc="sinhf"; .file_attr libFunc="_sinhf"; .file_attr libFunc="sqrt"; .file_attr libFunc="sqrtf"; .file_attr libFunc="_sqrtf"; .file_attr libFunc="pow"; .file_attr libFunc="powf"; .file_attr libFunc="_powf"; .file_attr libGroup="crt"; .file_attr libFunc="___lib_setup_environment"; #include "lib_glob.h" #include .SEGMENT/SPACE Data_Space_Name; .VAR _errno[ctxt_record_size] = 0, 1, 0, 0, 0, 0; /* errno is defined as a vector that contains the static data of ** the C run-time library. The vector represents a struct of the ** following form: ** ** int errno ** int rand_seed ** int *strtok__start_of_string ** int strtok_memory_type ** char *asctime_string ** struct tm *ptr ** ** This structure corresponds to the type struct _tlv_dat that is ** defined in the header file xtlv.h; the last two 'struct' members ** are only used by thread-safe versions of the time.h functions. */ #ifdef _ADI_THREADS #ifndef kUNALLOCATED #define kUNALLOCATED INT_MIN // VDK_kTLSUnallocated #endif .VAR libc_context_slot = kUNALLOCATED; #else .GLOBAL _errno; #endif .ENDSEG; .SEGMENT/CODE Code_Space_Name; .FILE RTL_FILENAME; .GLOBAL ___lib_get_context_rec; .GLOBAL ___lib_get_errno_addr; .EXTERN _AllocateThreadSlotEx__3VDKFPiPFPv_v; .EXTERN _GetThreadSlotValue__3VDKFi; .EXTERN _SetThreadSlotValue__3VDKFiPv; .GLOBAL ___lib_setup_ctxt; ___lib_setup_ctxt: I4=_errno; init_ctxt: /* * Need to do all context initialisations here, * I4 should contain the address of the context record. */ L4 = 0; #ifdef __21160_GLITCH nop; #endif rammem(I4, ram_1)=0; /* errno */ rammem(I4, ram_1)=1; /* rand_seed */ RTS (DB); rammem(I4, ram_1)=0; /* start_of_string */ rammem(I4, ram_1)=0; /* memory_type */ ___lib_setup_ctxt.end: /* * The function ____errno is called by a C-written, thread-safe function to * acquire the address of this current thread's copy of errno. What the * function actually does is to return the address of a structure that * contains the static memory of the C run-time library, and because the * first member of this structure is errno it also returns the address of * of this threads's copy of errno. * * __get_tlv_data is a alias for ____errno and will therefore be used as * a more meaningful name by functions that require access to the other * members of the structure. */ .GLOBAL ____errno; .GLOBAL __get_tlv_data; __get_tlv_data: ____errno: CALL (PC,___lib_get_context_rec); FETCH_RETURN R0=I4; RETURN (DB); RESTORE_STACK RESTORE_FRAME .__get_tlv_data.end: .____errno.end: /* * The function ___lib_get_context_rec is used to lookup (and possibly * allocate) the structure which holds the per-thread state for the C * library. ___lib_get_errno_addr is provided as an alias for the function. * * In order to minimise the overhead involved in calling them from * other assembly language functions, this function is *not* C-callable * and instead uses the hardware CALL and RTS instructions. * * ____errno is a wrapper function for ___lib_get_errno_addr which * *is* C/C++ callable. * * The function *does* call C/C++ functions, so any or all of the * usual scratch registers may be modified by the call. * * The per-thread context block consists of 6 words, laid out like this: * errno * rand_seed * strtok start of string * strtok memory type * ptr to string for asctime() * ptr to structure for a broken-down time (struct tm) * * and the address of this structure is returned via I4 */ ___lib_get_context_rec: ___lib_get_errno_addr: #ifndef _ADI_THREADS I4=_errno; RTS; #else .EXTERN _malloc; .EXTERN __del_tlv_data; /* __del_tlv_data is a function that is invoked by VDK when a ** thread is terminated - the purpose of the function is to ** enable tidy-up processing, such as freeing heap space. ** ** the function is defined in xtlv.c */ /* Save off the scratch registers */ put(R0); put(R1); put(R2); put(R3); /* preserved */ put(R4); put(R8); put(R12); put(I12); put(I12); /* placeholder */ R3=ramvar(libc_context_slot); R8=kUNALLOCATED; COMP(R3,R8); IF NE JUMP(PC, have_slot) (DB); CALLER_HOLD(R2) /* R2=I6 */ CALLER_SWAP /* I6=I7 */ R4=libc_context_slot; R8=__del_tlv_data; RTLCALL (PC, _AllocateThreadSlotEx__3VDKFPiPFPv_v) (DB); /* JUMP */ SAVE_OLD_FRAME(R2) /* DM(I7,M7)=R2 */ SAVE_RET_ADDR /* DM(I7,M7)=PC */ /* Test bool return from AllocateThreadSlot() */ R0=PASS R0; IF EQ JUMP (PC, fallback); CALLER_HOLD(R2) /* R2=I6 */ CALLER_SWAP /* I6=I7 */ have_slot: RTLCALL (PC, _GetThreadSlotValue__3VDKFi) (DB); /* JUMP */ R4=PASS R3, SAVE_OLD_FRAME(R2) /* DM(I7,M7)=R2 */ SAVE_RET_ADDR /* DM(I7,M7)=PC */ /* See if we got the record back */ R0=PASS R0, I4 = R0; IF NE JUMP (PC, restore_state); /* * The slot value was zero (NULL) so we * need to allocate a (ctxt_record_size)-word * block to hold errno for this thread. In the * multi-threaded libs (i.e. here) we are * guaranteed that malloc() will only ever allocate * from the system heap. */ R4=ctxt_record_size; /* argument to malloc() */ CALLER_HOLD(R2) /* R2=I6 */ CALLER_SWAP /* I6=I7 */ RTLCALL (PC, _malloc) (DB); /* JUMP */ SAVE_OLD_FRAME(R2) /* DM(I7,M7)=R2 */ SAVE_RET_ADDR /* DM(I7,M7)=PC */ /* Test for NULL return from _heap_malloc() */ R0=PASS R0; IF EQ JUMP (PC, fallback); /* * Initialise the new context record. */ I4=R0; CALL (PC, init_ctxt); /* trashes I4 */ /* * Now we need to store the pointer to the context record * in the libc context slot for this thread. */ R8=PASS R0, R3=R0; /* Arg 1, struct pointer (save) */ R4=ramvar(libc_context_slot); /* Arg 0 */ CALLER_HOLD(R2) /* R2=I6 */ CALLER_SWAP /* I6=I7 */ RTLCALL (PC, _SetThreadSlotValue__3VDKFiPv) (DB); /* JUMP */ SAVE_OLD_FRAME(R2) /* DM(I7,M7)=R2 */ SAVE_RET_ADDR /* DM(I7,M7)=PC */ I4=R3; /* return the record address in I4 */ restore_state: get(I12,2); get(R12,3); get(R8,4); get(R4,5); get(R3,6); get(R2,7); get(R1,8); RTS (DB); get(R0,9); /* restore R0, saved on entry */ alter(9); /* pop stack */ fallback: I4=_errno; JUMP (PC, restore_state); .___lib_get_errno_addr.end: .___lib_get_context_rec.end: #endif .ENDSEG;