#undef DEBUG_PROFILER #define MODULE_NAMES #define d0 %eax #define d1 %ebx #define a0 %ecx #define a1 %edx #define a2 %ebp #define a3 %esi #define a4 %edi #define sp %esp #if defined(_WINDOWS_) # define align(n) .align (1<<n) #else # define align(n) .align n #endif .global init_profiler .global profile_r .global profile_l .global profile_l2 .global profile_n .global profile_n2 .global profile_s .global profile_s2 .global profile_t .global write_profile_information .global write_profile_stack #ifdef LINUX .global @malloc #else .global @allocate_memory #endif .global __STRING__ .global writeFC .global writeFI .global print_error .global @ab_stack_size .global @ew_print_string .global @ew_print_char .global @stack_trace_depth #define next 0 #define name 4 #define FunctionProfile 8 .text profile_t: subl $4,profile_stack_pointer ret profile_r: subl $4,profile_stack_pointer ret profile_l: push d1 mov (a2),d1 test d1,d1 je allocate_function_profile_record_l allocate_function_profile_record_lr: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif mov d1,(a2) add $4,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_l: call allocate_function_profile_record jmp allocate_function_profile_record_lr profile_l2: push d1 mov (a2),d1 test d1,d1 je allocate_function_profile_record_l2 allocate_function_profile_record_l2r: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif mov d1,(a2) mov d1,4(a2) add $8,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_l2: call allocate_function_profile_record jmp allocate_function_profile_record_l2r profile_n: push d1 mov (a2),d1 test d1,d1 je allocate_function_profile_record_n allocate_function_profile_record_nr: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif mov d1,(a2) add $4,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_n: call allocate_function_profile_record jmp allocate_function_profile_record_nr profile_n2: push d1 mov (a2),d1 test d1,d1 je allocate_function_profile_record_n2 allocate_function_profile_record_n2r: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif mov d1,(a2) mov d1,4(a2) add $8,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_n2: call allocate_function_profile_record jmp allocate_function_profile_record_n2r profile_s2: push d1 mov (a2),d1 test d1,d1 je allocate_function_profile_record_s2 allocate_function_profile_record_s2r: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif movl d1,(a2) movl d1,4(a2) add $8,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_s2: call allocate_function_profile_record jmp allocate_function_profile_record_s2r profile_s: push d1 movl (a2),d1 test d1,d1 je allocate_function_profile_record_s allocate_function_profile_record_sr: mov profile_stack_pointer,a2 #ifdef DEBUG_PROFILER testl (d1),d1 #endif movl d1,(a2) add $4,a2 mov a2,profile_stack_pointer pop d1 ret allocate_function_profile_record_s: call allocate_function_profile_record jmp allocate_function_profile_record_sr / argument: a2: function name adress-4 / result: d1: function profile record adress allocate_function_profile_record: push d0 mov global_n_free_records_in_block,d0 mov global_last_allocated_block,d1 test d0,d0 jne no_alloc push d1 push a0 push a1 pushl $512*FunctionProfile #ifdef LINUX call @malloc #else call @allocate_memory #endif add $4,sp test d0,d0 pop a1 pop a0 pop d1 je no_memory mov d0,d1 mov $512,d0 mov d1,global_last_allocated_block no_alloc: dec d0 mov d0,global_n_free_records_in_block lea FunctionProfile(d1),d0 mov d0,global_last_allocated_block mov global_profile_records,d0 mov a2,name(d1) mov d0,next(d1) mov d1,global_profile_records mov d1,(a2) pop d0 ret no_memory: movl $not_enough_memory_for_profiler,a2 pop d0 jmp print_error write_profile_information: ret write_profile_stack: mov profile_stack_pointer,d0 test d0,d0 je stack_not_initialised push d0 push $stack_trace_string call @ew_print_string add $4,sp pop d0 / mov $12,a2 movl @stack_trace_depth,a2 write_functions_on_stack: mov -4(d0),d1 sub $4,d0 test d1,d1 je end_profile_stack push d0 mov name(d1),a0 push a2 #ifdef MODULE_NAMES movl -4(a0),a1 #endif add $4,a0 #ifdef MODULE_NAMES pushl (a1) addl $4,a1 pushl a1 #endif push a0 call @ew_print_string add $4,sp #ifdef MODULE_NAMES pushl $module_string call @ew_print_string add $4,sp call @ew_print_text addl $8,sp pushl $']' call @ew_print_char add $4,sp #endif pushl $10 call @ew_print_char add $4,sp pop a2 pop d0 sub $1,a2 jne write_functions_on_stack end_profile_stack: stack_not_initialised: ret init_profiler: pushl @ab_stack_size #ifdef LINUX call @malloc #else call @allocate_memory #endif add $4,sp test d0,d0 je init_profiler_error push d0 mov $start_string,a2 call allocate_function_profile_record pop a1 mov d1,4(a1) movl $0,(a1) add $8,a1 mov a1,profile_stack_pointer mov end_heap,a1 sub a4,a1 add $32,a1 mov a1,global_n_bytes_free ret init_profiler_error: movl $0,profile_stack_pointer movl $not_enough_memory_for_profile_stack,a2 jmp print_error .data align (2) global_n_free_records_in_block: .long 0 / 0 n free records in block global_last_allocated_block: .long 0 / 4 latest allocated block global_profile_records: .long 0 / 8 profile record list profile_stack_pointer: .long 0 global_n_bytes_free: .long 0 align (2) @stack_trace_depth: .long 12 #ifdef MODULE_NAMES # if 0 / m_system also defined in cgistartup.s m_system: .long 6 .ascii "System" .byte 0 .byte 0 # endif .long m_system #endif start_string: .long 0 .asciz "start" align (2) not_enough_memory_for_profile_stack: .ascii "not enough memory for profile stack" .byte 10 .byte 0 not_enough_memory_for_profiler: .ascii "not enough memory for profiler" .byte 10 .byte 0 stack_trace_string: .ascii "Stack trace:" .byte 10 .byte 0 #ifdef MODULE_NAMES module_string: .asciz " [module: " #endif align (2)