diff options
| author | David Jones | 2005-03-01 15:09:19 +0000 |
|---|---|---|
| committer | David Jones | 2005-03-01 15:09:19 +0000 |
| commit | 013278a0c2594d08f824b9cab078dc7cd22b43d7 (patch) | |
| tree | 5cc2b98448ec741b63faaa6554386b6dd7bb26b2 /mps/code/ssxcpp.s | |
| parent | 21bbbcb0a0fb01c9ad71ef24bb57d1bab08a0a6e (diff) | |
| download | emacs-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.s | 132 |
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 | |||
| 110 | linkageArea = 24 ; size of linkage area to create | ||
| 111 | paramArea = 12 ; size of param area to create | ||
| 112 | # .local.size: this size is directly related to what registers we save. | ||
| 113 | localArea = 76 ; size of local workspace (for 19 registers, r13-r31) | ||
| 114 | frameSize = 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 | ||