aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/ssxcpp.s
diff options
context:
space:
mode:
authorDavid Jones2005-03-01 15:09:19 +0000
committerDavid Jones2005-03-01 15:09:19 +0000
commit013278a0c2594d08f824b9cab078dc7cd22b43d7 (patch)
tree5cc2b98448ec741b63faaa6554386b6dd7bb26b2 /mps/code/ssxcpp.s
parent21bbbcb0a0fb01c9ad71ef24bb57d1bab08a0a6e (diff)
downloademacs-013278a0c2594d08f824b9cab078dc7cd22b43d7.tar.gz
emacs-013278a0c2594d08f824b9cab078dc7cd22b43d7.zip
Mps: stack scanner for xcppgc. does not work.
Copied from Perforce Change: 147094 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/ssxcpp.s')
-rw-r--r--mps/code/ssxcpp.s132
1 files changed, 132 insertions, 0 deletions
diff --git a/mps/code/ssxcpp.s b/mps/code/ssxcpp.s
new file mode 100644
index 00000000000..74060910262
--- /dev/null
+++ b/mps/code/ssxcpp.s
@@ -0,0 +1,132 @@
1# ssxcpp.s: STACK SCANNING FOR MAC OS X / POWERPC
2#
3# .quote.why: The following is in quotes because otherwise the
4# preprocessor seems to barf.
5# "$Header$"
6#
7# Copyright (c) 2005 Ravenbrook Limited. See end of file for license.
8#
9# .readership: Any MPS developer that is prepared to read PowerPC
10# assembly code in GNU 'as' syntax.
11#
12#
13# It's possible that since this is mostly PowerPC and GNU 'as' that we
14# could use the same code for lippgc. See .future.abi
15#
16#
17# REFERENCES
18#
19# [OSXAG] "Introduction to Mac OS X Assembler Guide",
20# http://developer.apple.com/documentation/DeveloperTools/Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
21# http://developer.apple.com/documentation/DeveloperTools/Reference/Assembler/Assembler.pdf
22#
23# [PEM] "PowerPC Microprocessor Family: The Programming Environments for
24# 32-bit Microprocessors", Motorola, 1997-01. MPCFPE32B/AD REV.1
25#
26# [MORT] "Introduction to Mach-O Runtime Architecture",
27# http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html
28# http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/MachORuntime.pdf
29#
30# [MORT] Chapter 2 is the place to go for the stack layout. But it is
31# still a bit vague. For example, what is the exact format of the
32# Linkage Area?
33#
34#
35# Stack Layout and Register Usage
36#
37# Let SPEP be the value of the stack pointer (r1) on entry to the
38# function. r1 is the Stack Pointer, descending full stack (that is
39# -4(r1) is the address of the next available free slot on the stack).
40#
41# On entry, stack looks like (numerically higher addresses appear higher
42# up the page, stack grows down (towards address 0) in memory and on
43# paper):
44#
45# | |
46# +-----------------------------------+
47# | -- Parameter area -- |
48# | Lowest addresses have leftmost |
49# | actual arguments. |
50# | Note that some actual arguments |
51# | may be in registers. They |
52# | still have a slot reserved in |
53# | this area, even if the value is |
54# | not written in. |
55# +-----------------------------------+
56# | -- Linkage area -- |
57# | Apparently this is 24 bytes long. |
58# | (See [MORT] Listing 2-1) |
59# | 12(SPEP)-23(SPEP) unknown |
60# | 8(SPEP) - optional lr |
61# | 4(SPEP) - optional cr |
62# | 0(SPEP) - previous SPEP |
63# +-----------------------------------+
64# 8(SPEP) - available to store the callee's lr if desired.
65# 4(SPEP) - available to store the callee's cr if desired.
66# 0(SPEP) - not available. The caller saves their SPEP here. In other
67# words, this points to the highest address of the caller's frame. The
68# callee will decrement sp and store SPEP at the new sp, thus creating a
69# new linkage area in preparation for calling another function.
70#
71# Note that the callee can access locations -1(SPEP) to -224(SPEP)
72# without changing the stack pointer. This is called a Red Zone (see
73# [MORT] Chapter 2, section "The Red Zone"). This means that we must
74# overscan when scanning the stacks of other threads.
75#
76# [MORT] Table 2-4 specifies which registers are saved (required to be
77# preserved by a callee when called, aka nonvolatile). They are: r1,
78# r13-r31, fr14-fr31, v20-v31, VRSAVE, cr2-cr4.
79#
80# Stack Scanner Design
81#
82# All we have to do is create a stack frame, push the saved registers
83# onto it, and call TraceScanArea with appropriate arguments.
84# We assume that of the saved registers, only the general purpose ones
85# can contain roots (in other words the client doesn't store pointers in
86# floating pointer registers, and other silliness). So we'll only store
87# r13 through to r31. r1 will be stored in the callee's new linkage
88# area, as per convention. lr will be stored in the caller's linkage
89# area, as per convention. CTR (a future PC value, so a potential root)
90# is volatile so cannot be a root.
91#
92# Future Directions
93#
94# .future.clear: We could poke all the stack locations that we have
95# access to and set them to 0 (the ones that we are not using), just
96# in case any false references are hiding there.
97#
98# .future.abi:
99# One can imagine a sort of minimal ABI version that pushed
100# all registers and only used stack space that it had reserved itself.
101# We would, alas, still have to assume that r1 was SP though.
102#
103# To do this we would need to:
104# - save more registers
105# - possibly not use the caller's stack
106
107# Exported symbols
108.globl _StackScan
109
110linkageArea = 24 ; size of linkage area to create
111paramArea = 12 ; size of param area to create
112# .local.size: this size is directly related to what registers we save.
113localArea = 76 ; size of local workspace (for 19 registers, r13-r31)
114frameSize = linkageArea + paramArea + localArea
115
116_StackScan:
117# r1 is SPEP
118 mflr r0
119# value of localArea depends on r13, see .local.size
120 stmw r13, -localArea(r1)
121 stw r0, 8(r1)
122 stwu r1, -frameSize(r1)
123# r1 + frameSize is SPEP
124
125 lwz r1, 0(r1)
126# r1 is SPEP again
127 lwz r0, 8(r1)
128 mtlr r0
129# See .local.size
130 lmw r13, -localArea(r1)
131 li r3, 0
132 blr