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