/* This routine configures the C runtime environemt */ /* */ .file_attr libGroup="crt"; .file_attr libName="libc"; .file_attr libFunc="___lib_setup_environment"; .file_attr FuncName="___lib_setup_environment"; .file_attr libFunc="___lib_setup_runtime_heap"; .file_attr FuncName="___lib_setup_runtime_heap"; .file_attr libFunc="___lib_sure_rti"; .file_attr FuncName="___lib_sure_rti"; .file_attr libFunc="___lib_sure_rts"; .file_attr FuncName="___lib_sure_rts"; .file_attr prefersMem="any"; .file_attr prefersMemNum="50"; .file_attr libFunc="___lib_setup_c"; .file_attr libFunc="__heap_install"; #include "lib_glob.h" /* #include "020_glob.h" */ #include "sig_glob.h" #include "linkports.h" #include "sdl_glob.h" #if defined(__ADSP21020__) || defined(__2106x__) || defined(__2116x__) || defined(__2126x__) || defined(__213xx__) # define SRD1H 0x8 #else # error Check the value of SRD1H for the platform and alter this code. #endif .EXTERN ___lib_stack_space; .EXTERN ___lib_stack_length; .EXTERN ___lib_heap_space; .EXTERN __heaps; .EXTERN __nheaps; .EXTERN ___lib_int_table; /* This used to be EXTERNed ___lib_xrand_seed; */ .EXTERN ___lib_setup_args; .EXTERN ___lib_setup_ctxt; .SEGMENT/CODE Code_Space_Name; .FILE RTL_FILENAME; #ifdef _ADI_SWFA .EXTERN __21160_anomaly_write_location; #endif .GLOBAL ___lib_setup_environment; .GLOBAL ___lib_setup_runtime_heap; ___lib_setup_environment: CALL (PC, ___lib_setup_stacks); CALL (PC, ___lib_setup_ctxt); CALL (PC, ___lib_init_heaps); CALL (PC, ___lib_setup_heaps); #ifndef _ADI_THREADS CALL (PC, ___lib_setup_ints); #endif /* _ADI_THREADS */ CALL (PC, ___lib_setup_exit); JUMP (PC, ___lib_setup_args); /* RTS eliminated */ ___lib_setup_exit: ram_lreg=0; ram_ireg=___lib_exit_table; LCNTR=32, DO zero_exit_table UNTIL LCE; zero_exit_table: rammem(ram_ireg,ram_1)=0; RTS; #ifndef _ADI_THREADS ___lib_setup_ints: R2=1; /* Mask defaults */ R4=___lib_sure_rti; /* Default interrupt handler */ R1=___lib_sure_rts; /* Default functions */ ram_ireg=___lib_int_table; #if defined(__ADSP21020__) || defined(__2106x__) LCNTR=___SIG_LAST_HARDWARE_INT+1, DO default_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; default_int_table: MODIFY(ram_ireg,siga_size); #elif defined(__2116x__) // for setting up the 2116x table need to treat the link // port interrupts specially. Also, for the hardware // interrupts after the link port interrupts, need to // account for the shift in number LCNTR=FIRST_LINK_PORT, DO low_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; low_int_table: MODIFY(ram_ireg,siga_size); R0=0xffffffff; LCNTR=SIG_EP0I-SIG_LP0I, DO liprt_int_table UNTIL LCE; // R0=NOT R2, ram_lreg=dm_0; // R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; liprt_int_table: MODIFY(ram_ireg,siga_size); r2=LSHIFT R2 BY 1; // account for LPISUM LCNTR=___SIG_LAST_HARDWARE_INT-LAST_LINK_PORT, DO high_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; high_int_table: MODIFY(ram_ireg,siga_size); #elif defined(__2126x__) || defined(__213xx__) // for setting up the 2136x table need to treat the link port interrupts // specially. Also, for the hardware interrupts between and after the link // port interrupts, need to account for the shift in number LCNTR=FIRST_START_LINK_PORT, DO low_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; low_int_table: MODIFY(ram_ireg,siga_size); R0=0xffffffff; LCNTR=FIRST_END_LINK_PORT-FIRST_START_LINK_PORT+1, DO low_liprt_int_table UNTIL LCE; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; low_liprt_int_table: MODIFY(ram_ireg,siga_size); LCNTR=LAST_START_LINK_PORT-FIRST_END_LINK_PORT-1, DO med_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; med_int_table: MODIFY(ram_ireg,siga_size); R0=0xffffffff; LCNTR=LAST_END_LINK_PORT-LAST_START_LINK_PORT+1, DO high_liprt_int_table UNTIL LCE; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; high_liprt_int_table: MODIFY(ram_ireg,siga_size); LCNTR=___SIG_LAST_HARDWARE_INT-LAST_END_LINK_PORT, DO high_int_table UNTIL LCE; R0=NOT R2, ram_lreg=dm_0; R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; high_int_table: MODIFY(ram_ireg,siga_size); #endif /* !__2116x__ && !__2126x__ && !__213xx__ */ R1=SIG_IGN; R0=0xffffffff; LCNTR=___SIG_LAST_INTERRUPT - ___SIG_LAST_HARDWARE_INT, DO sw_int_table UNTIL LCE; // R0=NOT R2, ram_lreg=dm_0; // R2=LSHIFT R2 BY 1; rammem(defl_mask,ram_ireg)=R0; rammem(next_mask,ram_ireg)=R0; rammem(curr_func,ram_ireg)=R1; rammem(next_func,ram_ireg)=R1; rammem(defl_func,ram_ireg)=R1; rammem(defl_disp,ram_ireg)=R4; // for s/w ints this should neve be called sw_int_table: MODIFY(ram_ireg,siga_size); RTS; #endif /* _ADI_THREADS */ /* * In this section, * PX=PM(...); Rn=PX2; * is used rather than * Rn=PM(...); * because on the 2106x, the two instructions may * access different memory locations depending on * the IMDW bit settings. The PX form is guaranteed * to use 48-bit addressing; the Rn form may not. */ ___lib_setup_stacks: PX=PM(___lib_stack_space); R0=PX2; PX=PM(___lib_stack_length); R2=PX2; #if defined(__2116x__) || defined(__2126x__) || defined(__213xx__) /* R0 now has stack start, R2 has stack length */ /* Goal here is that stack start + stack length should be even */ R2 = R2 + R0 ; BTST R2 BY 0 ; if SZ R2 = R2 - 1 ; R2 = R2 - R0 ; PX2 = R2 ; PM(___lib_stack_length) = PX ; #ifdef _ADI_SWFA PM(__21160_anomaly_write_location)=r0; PM(__21160_anomaly_write_location)=r0; #endif /* _ADI_SWFA */ #endif R1=R0+R2, B7=R0; R1=R1-1, L7=R2; I7=R1; bit set MODE1 SRD1H; // Enable secondary DAG1 B6=B7; // Primary DAG, done in latency slot B7=R0; B6=B7; L7=R2; bit clr MODE1 SRD1H; // Enable primary DAG1 L6=L7; // Secondary DAG, done in latency slot RTS (DB); I6=I7; L6=L7; /* typedef struct { char *seg_; char *heap; unsigned long userid; char *base; size_t length; } heapinfo; Reset the __heaps to zero and reset the number of run-time installed heaps. */ #define MAXHEAPS 4 /* The maximum number of run-time initialised heaps. */ #define HEAPS_ELEMENTS 5 /* The number of elements matching the number of elements * declared for static heaps in seg_init.asm. */ ___lib_init_heaps: pm_ptr = __heaps; px = 0; r0 = HEAPS_ELEMENTS * MAXHEAPS; lcntr = r0, DO .P1L1 UNTIL LCE; pm(pm_ptr, pm_1) = px; /* __heaps[i] = 0; */ .P1L1: nop; #if defined(__21160_GLITCH) pm_ptr = __nheaps; rts(db); pm(pm_ptr, pm_0) = px; /* __nheaps = 0; */ nop; #else rts(db); pm_ptr = __nheaps; pm(pm_ptr, pm_0) = px; /* __nheaps = 0; */ #endif .___lib_init_heaps.end: ___lib_setup_runtime_heap: #if defined(__21160_GLITCH) pm_lnt = 0; jump(pc, loop_thru_heaps + 1)(db); px=pm(0, pm_ptr); nop; #else jump(pc, loop_thru_heaps + 1)(db); pm_lnt = 0; px=pm(0, pm_ptr); #endif .___lib_setup_runtime_heap.end: ___lib_setup_heaps: pm_ptr = ___lib_heap_space; pm_lnt = 0; loop_thru_heaps: /* Check that we have a valid heap */ #if defined(__21160_GLITCH) nop; #endif PX=PM(0, pm_ptr); R0=PX2; R0=PASS R0, dm_lnt=dm_0; IF EQ RTS (DB); #if defined(__2116x__) || defined(__2126x__) || defined(__213xx__) /* The purpose of this code here is to check that the user has aligned the heap properly. If he has not done so, this code does align automatically. First get the heap start */ PX = PM(3, pm_ptr) ; R0 = PX2 ; /* Now get the heap length */ PX = PM(4, pm_ptr) ; R1 = PX2 ; /* compute the sum of these two which will give the end of heap. The requirement is that the end of the heap must be at an even address that would ensure that mallocs always gives a double word aligned address. */ R1 = R1 + R0 ; /* Now validate if R1 is at an odd address or not */ BTST R1 BY 0 ; if NOT SZ R1 = R1 - 1 ; R1 = R1 - R0 ; PX2 = R1 ; PM(4, pm_ptr) = PX ; #ifdef _ADI_SWFA pm(__21160_anomaly_write_location)=r0; pm(__21160_anomaly_write_location)=r1; #endif /* _ADI_SWFA */ #endif PX = PM(1, pm_ptr); R0 = PX1; #if !defined(__2116x__) && !defined(__2126x__) && !defined(__213xx__) R0=LSHIFT R0 by 16; /* sign extend short value */ #endif /* ! __2116x__ && !__2126x__ && !__213xx__ */ PX = PM(4, pm_ptr); R1 = PASS R0, R0=PX2; IF GT JUMP (PC, pm_heap) (DB); PX = PM(3, pm_ptr); R1=PX2; dm_ptr = R1; MODIFY(pm_ptr, 5); R2=3; R1=R1+R2; R2=2; R0=R0-R2, R2=pm_ptr; DM(dm_ptr, dm_1)= 0; DM(dm_ptr, dm_1) = R1; DM(dm_ptr, dm_1) = R1; /* Dummy write */ R0=R0-1,DM(dm_ptr, dm_1) = R0; R0=R0-1; /* Leave space for a control block at the end... */ JUMP (PC, loop_thru_heaps) (DB); DM(dm_ptr, dm_1) = 0; DM(dm_ptr, dm_0) = R0; pm_heap: MODIFY(pm_ptr, 5); R2=pm_ptr; R3=3; R1=R1+R3, pm_ptr = R1; R3=5; R0=R0-R3; PM(pm_ptr, pm_1) = 0; /* Writing does not need to change */ PM(pm_ptr, pm_1) = R1; /* because stacks/heaps are 32bits */ PM(pm_ptr, pm_1) = R1; /* Dummy write */ R0=R0-1,PM(pm_ptr, pm_1) = R0; PM(pm_ptr, pm_1) = 0; R0=R0-1; /* Leave space for a control block at the end... */ #ifdef _ADI_SWFA PM(pm_ptr, pm_0) = R0; pm_ptr = R2; JUMP (PC, loop_thru_heaps) (DB); PM(__21160_anomaly_write_location)=r0; PM(__21160_anomaly_write_location)=r0; #else JUMP (PC, loop_thru_heaps) (DB); PM(pm_ptr, pm_0) = R0; pm_ptr = R2; #endif /* _ADI_SWFA */ .GLOBAL ___lib_sure_rts; ___lib_sure_rts: nop; // Need to ensure 2 non-reads FETCH_RETURN // Always a return for ints nop; RETURN (DB); RESTORE_STACK RESTORE_FRAME #ifndef _ADI_THREADS .GLOBAL ___lib_sure_rti; // a default for interrupt handler -- in normal circumstances will // not be used; will be called from out of z3_int_determiner so // need to restore i13, i15, and re-enable interrupts and cache ___lib_sure_rti: BIT SET MODE1 0x1000; /* Re-enable interrupts */ get(I2,2); /* restore from RTH */ get(R1,3); /* restore from RTH */ get(R2,4); /* restore from RTH */ #if defined(__2116x__) || defined(__2126x__) || defined(__213xx__) pop sts; #endif /* __2116x__ || __2126x__ || __213xx__ */ RTI(DB); /* Return from interrupt */ get(I13,1); /* Get ret addr, rest from RTH */ alter(4); /* Clean the stack */ .___lib_sure_rti.end: #endif /* _ADI_THREADS */ .___lib_sure_rts.end: .___lib_setup_environment.end: .ENDSEG; .SEGMENT/RAM_SPACE Ram_Space_Name; .GLOBAL ___lib_exit_table; .VAR ___lib_exit_table[MAX_REGISTERED_FUNCTIONS] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; .ENDSEG;