string asis macro lea &r,&a lwz &r,&a{TC}(RTOC) endm ; MACOSX set 1 USE_TEMPORARY_MEMORY set 1 CHECK_STACK_OVERFLOWS set 0 MODULE_NAMES set 1 d0: set r24 d1: set r25 d2: set r26 d3: set r27 d4: set r28 d5: set r29 d6: set r30 d7: set r31 a0: set r23 a1: set r22 a2: set r21 a3: set r20 a4: set r19 a5: set r18 a6: set r17 o0: set r3 o1: set r4 o2: set r5 o3: set r6 o4: set r7 o5: set r8 g2: set r9 g3: set r10 g0: set r11 g1: set r12 int_reg set r16 char_reg set r15 real_reg set r14 bool_reg set r13 export init_profiler export profile_r export profile_l export profile_l2 export profile_n export profile_n2 export profile_s export profile_s2 export profile_t export profile_ti export write_profile_information export write_profile_stack if USE_TEMPORARY_MEMORY import .TempNewHandle import .TempHLock import .TempHUnlock import .TempDisposeHandle else import .NewPtr endif import __STRING__ import writeFC import writeFI import print_error import stack_size import .er_print_string import .er_print_char if CHECK_STACK_OVERFLOWS import .Debugger endif FunctionProfile: record next: ds.l 1 name: ds.l 1 endr csect .profile_t profile_ti: lea r5,profile_globals b profile_t_ profile_t: mflr r12 lea r5,profile_globals mtctr r12 mtlr r0 profile_t_: lwz r6,Globals.stack_pointer(r5) lwzu r4,-4(r6) stw r6,Globals.stack_pointer(r5) bctr csect .profile_r profile_r: lea r5,profile_globals lwz r6,Globals.stack_pointer(r5) lwzu r4,-4(r6) stw r6,Globals.stack_pointer(r5) blr csect .profile_l profile_l: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) addi r6,r6,4 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr csect .profile_l2 profile_l2: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) stw r4,4(r6) addi r6,r6,8 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr csect .profile_n profile_n: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) addi r6,r6,4 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr csect .profile_n2 profile_n2: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) stw r4,4(r6) addi r6,r6,8 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr csect .profile_s2 profile_s2: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) stw r4,4(r6) addi r6,r6,8 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr csect .profile_s profile_s: mflr r12 lea r5,profile_globals lwz r4,0(r3) mtctr r12 cmpwi 0,r4,0 beql allocate_function_profile_record lwz r6,Globals.stack_pointer(r5) stw r4,0(r6) addi r6,r6,4 if CHECK_STACK_OVERFLOWS lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif mtlr r0 bctr allocate_function_profile_record: lwz r6,Globals.n_free_records_in_block(r5) lwz r4,Globals.last_allocated_block(r5) cmpwi 0,r6,0 bne+ no_alloc stw r0,-4(sp) stw r3,-8(sp) stw r9,-12(sp) stw r10,-16(sp) mfctr r11 stw r11,-20(sp) mflr r12 stw r12,-24(sp) if USE_TEMPORARY_MEMORY li r3,(512*FunctionProfile)+4 else li r3,512*FunctionProfile endif if MACOSX mr g0,sp ori sp,sp,28 stwu g0,-(64+32+28)(sp) else stwu sp,-(64+32)(sp) endif if USE_TEMPORARY_MEMORY bl allocate_temp_memory_handle else bl .NewPtr nop endif if MACOSX lwz sp,0(sp) else addi sp,sp,64+32 endif and. r4,r3,r3 lwz r12,-24(sp) lwz r11,-20(sp) mtlr r12 lwz r10,-16(sp) mtctr r11 lwz r9,-12(sp) lwz r3,-8(sp) lwz r0,-4(sp) lea r5,profile_globals beq profiler_memory_error if USE_TEMPORARY_MEMORY lwz r6,Globals.temp_handle_list(r5) stw r4,Globals.temp_handle_list(r5) lwz r4,0(r4) stw r6,0(r4) addi r4,r4,4 endif li r6,512 stw r4,Globals.last_allocated_block(r5) no_alloc: subi r6,r6,1 stw r6,Globals.n_free_records_in_block(r5) addi r7,r4,FunctionProfile stw r7,Globals.last_allocated_block(r5) lwz r6,Globals.profile_records(r5) li r8,0 stw r6,FunctionProfile.next(r4) stw r4,Globals.profile_records(r5) stw r3,FunctionProfile.name(r4) stw r4,0(r3) blr csect .write_profile_information write_profile_information: if USE_TEMPORARY_MEMORY mflr r0 if MACOSX mr g0,sp ori sp,sp,28 stwu g0,-(96+28)(sp) else stwu sp,-96(sp) endif stw r0,96-4(sp) lea r5,profile_globals lwz r3,Globals.profile_stack_handle(r5) bl free_temp_memory_handle lea r5,profile_globals stw r31,96-8(sp) lwz r31,Globals.temp_handle_list(r5) b free_temp_handles free_temp_handles_lp: mr r3,r31 lwz r31,0(r31) lwz r31,0(r31) bl free_temp_memory_handle free_temp_handles: cmpwi 0,r31,0 bne free_temp_handles_lp lwz r31,96-8(sp) lwz r0,96-4(sp) if MACOSX lwz sp,0(sp) else addi sp,sp,96 endif mtlr r0 endif lwz r0,0(sp) addi sp,sp,4 blr csect .write_profile_stack write_profile_stack: mflr r0 lea d0,profile_globals stwu r0,-4(sp) lwz d0,Globals.stack_pointer(d0) cmpwi 0,d0,0 beq @stack_not_initialised if MACOSX mr g0,sp ori sp,sp,28 stwu g0,-(64+28)(sp) else stwu sp,-64(sp) endif lea o0,stack_trace_string bl .er_print_string if MACOSX lwz sp,0(sp) else addi sp,sp,64 endif li d2,12 @write_functions_on_stack lwzu d1,-4(d0) cmpwi 0,d1,0 beq @end_profile_stack lwz o0,FunctionProfile.name(d1) if MACOSX mr g0,sp ori sp,sp,28 stwu g0,-(64+28)(sp) else stwu sp,-64(sp) endif addi o0,o0,4 bl .er_print_string nop li o0,13 bl .er_print_char nop if MACOSX lwz sp,0(sp) else addi sp,sp,64 endif subic. d2,d2,1 if 0 b @write_functions_on_stack else bne @write_functions_on_stack endif @end_profile_stack: @stack_not_initialised: lwz r0,0(sp) mtlr r0 lwz r0,4(sp) addi sp,sp,8 blr csect .init_profiler init_profiler: if 0 mflr r0 stw r0,-4(sp) stwu sp,-64(sp) bl .Debugger nop lwz r0,64-4(sp) addi sp,sp,64 mtlr r0 endif mflr r0 stwu r0,-4(sp) if 1 lea r3,stack_size lwz r3,0(r3) addi r3,r3,4095 rlwinm r3,r3,0,0,31-12 else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 endif if MACOSX mr g0,sp ori sp,sp,28 stwu g0,-(64+28)(sp) else stwu sp,-64(sp) endif if USE_TEMPORARY_MEMORY bl allocate_temp_memory_handle else bl .NewPtr nop endif if MACOSX lwz sp,0(sp) else addi sp,sp,64 endif lea r5,profile_globals and. r9,r3,r3 beq init_profiler_error if USE_TEMPORARY_MEMORY stw r9,Globals.profile_stack_handle(r5) lwz r9,0(r9) li r0,0 stw r0,Globals.temp_handle_list(r5) endif if CHECK_STACK_OVERFLOWS if 1 lea r3,stack_size lwz r3,0(r3) else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 endif add r3,r3,r9 stw r3,Globals.end_profile_stack(r5) endif lea r3,start_string bl allocate_function_profile_record lwz r0,0(sp) addi sp,sp,4 mtlr r0 li r0,0 stw r4,4(r9) stw r0,0(r9) addi r9,r9,8 stw r9,Globals.stack_pointer(r5) stw d7,Globals.n_words_free(r5) lwz r0,0(sp) addi sp,sp,4 blr if USE_TEMPORARY_MEMORY allocate_temp_memory_handle: mflr r0 stw r31,-4(sp) stw r0,8(sp) stwu sp,-96(sp) addi r4,sp,56 bl .TempNewHandle nop mr. r31,r3 beq return_r31 addi r4,sp,56 bl .TempHLock nop lha r0,56(sp) cmpwi r0,0 beq+ return_r31 mr r3,r31 addi r4,sp,56 bl .TempDisposeHandle nop li r31,0 return_r31: lwz r0,104(sp) mr r3,r31 mtlr r0 addi sp,sp,96 lwz r31,-4(sp) blr free_temp_memory_handle: mflr r0 stw r3,-4(sp) stw r0,8(sp) stwu sp,-96(sp) addi r4,sp,56 bl .TempHUnlock nop lwz r3,96-4(sp) addi r4,sp,56 bl .TempDisposeHandle nop lwz r0,104(sp) addi sp,sp,96 mtlr r0 blr endif init_profiler_error: lea o0,not_enough_memory_for_profile_stack lea r5,profile_globals li r4,0 stw r4,Globals.stack_pointer(r5) b print_error profiler_memory_error: lea o0,not_enough_memory_for_profiler b print_error if CHECK_STACK_OVERFLOWS profile_stack_overflow: mflr r0 stw r0,-4(sp) stwu sp,-64(sp) bl .Debugger nop lwz r0,64-4(sp) addi sp,sp,64 mtlr r0 b profile_stack_overflow endif csect data{RW} Globals: record n_free_records_in_block:ds.l 1 ; 0 n free records in block last_allocated_block: ds.l 1 ; 4 latest allocated block profile_records: ds.l 1 ; 8 profile record list stack_pointer: ds.l 1 ; 12 stack pointer n_words_free: ds.l 1 if USE_TEMPORARY_MEMORY temp_handle_list ds.l 1 profile_stack_handle ds.l 1 endif if CHECK_STACK_OVERFLOWS end_profile_stack ds.l 1 endif endr align 2 profile_globals: ds Globals align 2 if MODULE_NAMES m_system: dc.l 6 dc.b 'System' dc.b 0,0 dc.l m_system endif start_string: dc.l 0 dc.b 'start' dc.b 0 align 2 not_enough_memory_for_profile_stack: dc.b 'not enough memory for profile stack' dc.b 13 dc.b 0 not_enough_memory_for_profiler: dc.b 'not enough memory for profiler' dc.b 13 dc.b 0 stack_trace_string: dc.b 'Stack trace:' dc.b 13 dc.b 0 align 2 macro te &address tc &address{TC},&address endm toc te profile_globals te not_enough_memory_for_profile_stack te not_enough_memory_for_profiler te start_string te stack_trace_string te stack_size