torch@attctc.Dallas.TX.US (Jay Finger) (02/09/90)
About a week ago I requested a copy of alloca for Think C 4.0. I received
several descriptions of what alloca is supposed to do, along with the version
of alloca in Earle Horton's port of bison to MPW. I also received several
requests for whatever I came up with, so here it is.
The alloca function below is completely inline: it uses a few more words
of memory that way, but since it's inline it doesn't have to jack with
the return address or stack frame (from what I've seen ThinkC always
puts a LINK instruction at the beginning of the function, even if it's
all in assembler and you've got no local variables).
I was rather suprised to discover that inline functions must be pascal
style functions; a C function would have been better because the
return value would be passed back in D0 instead of on the stack.
Anyhow, here's the declaration for alloca. You'll probable want to put
in a file called "alloca.h" somewhere. I've got bison (not the MPW
version; version 1.03 (8/23/89) from osu-cis) up and running after about
ten hours of work. I haven't tested it with anything big yet, but this
alloca isn't breaking it.
---------------------- cut here --------------------------------------
pascal void *alloca(long size) =
{
0x201F, /* MOVE.L (SP)+,D0 ;get size */
0x5680, /* ADDQ.L #3,D0 ;make it a multiple of 4 */
0x0240, 0xFFFC, /* ANDI.W #-4,D0 */
0x9FC0, /* SUB.L D0,SP ;allocate it */
0x2F0F /* MOVE.L SP,-(SP) ;return value on stack */
};
----------------------------------------------------------------------
Jay Finger,
{ames,mit-eddie}!attctc!torch
ames!torch@attctc
mikem@uhccux.uhcc.hawaii.edu (Mike Morton) (02/09/90)
Jay Finger writes: >pascal void *alloca(long size) = > { > 0x201F, /* MOVE.L (SP)+,D0 ;get size */ > 0x5680, /* ADDQ.L #3,D0 ;make it a multiple of 4 */ > 0x0240, 0xFFFC, /* ANDI.W #-4,D0 */ > 0x9FC0, /* SUB.L D0,SP ;allocate it */ > 0x2F0F /* MOVE.L SP,-(SP) ;return value on stack */ > }; Since the "calling" C code has already done something like a: SUBQ #4, SP to make room for a Pascal-style returned value, then isn't this allocating 4 bytes more than needed? I think changing -(SP) to just (SP) would work, but haven't tried it. -- Mike Morton // P.O. Box 11299, Honolulu, HI 96828, (808) 676-6966 HST Internet: mikem@uhccux.uhcc.hawaii.edu (anagrams): Mr. Machine Tool; Ethical Mormon; Chosen Immortal; etc.
torch@attctc.Dallas.TX.US (Jay Finger) (02/10/90)
Mike Morton cat allocax From mikem@uhccux.UUCP Thu Feb 8 23:38:06 1990 Path: attctc!ames!elroy.jpl.nasa.gov!jarthur!uunet!samsung!munnari.oz.au!uhccux!mikem From: mikem@uhccux.uhcc.hawaii.edu (Mike Morton) Newsgroups: comp.sys.mac.programmer Subject: Re: alloca for Think C 4.0: here it is Keywords: alloca Think C Message-ID: <6521@uhccux.uhcc.hawaii.edu> Date: 9 Feb 90 05:38:06 GMT References: <11376@attctc.Dallas.TX.US> Reply-To: mikem@uhccux.UUCP (Mike Morton) Organization: University of Hawaii Lines: 19 In <6521@uhccux.uhcc.hawaii.edu> Mike Morton writes: >Jay Finger writes: >>pascal void *alloca(long size) = >> { >> 0x201F, /* MOVE.L (SP)+,D0 ;get size */ >> 0x5680, /* ADDQ.L #3,D0 ;make it a multiple of 4 */ >> 0x0240, 0xFFFC, /* ANDI.W #-4,D0 */ >> 0x9FC0, /* SUB.L D0,SP ;allocate it */ >> 0x2F0F /* MOVE.L SP,-(SP) ;return value on stack */ >> }; > >Since the "calling" C code has already done something like a: > SUBQ #4, SP >to make room for a Pascal-style returned value, then isn't this >allocating 4 bytes more than needed? I think changing -(SP) to >just (SP) would work, but haven't tried it. You got me. You're right, almost. Changing to (SP) would keep the correct amount of space on the stack, but the pointer would then get screwed up: the address returned would be the address of the return value itself, which would then get popped off the stack, letting other things write into the newly allocated block. There are three ways to fix it (described from worst to (IMHO) best): 1: Move SP to D0, add 4, and then do a "MOVE.L D0,(SP)". This takes two more instructions, and about two additional words. 2: Replace "MOVE.L SP,-(SP)" with "LEA 4(SP),(SP)". The same number of instructions, but an extra word for the displacement. 3: Keep the "MOVE.L SP,-(SP)" at the bottom, but simply allocate four less bytes, making use of the four bytes that the caller already allocated for the return value. Since #3 is already being added to the block size for word-alligning, subtracting 4 can be merged into the operation by replacing the ADDQ #3 with a SUBQ #1. Same number of instructions, same number of words. So anyhow, here's a new version (using method #3) that allocates the correct number of bytes on the stack: ---------------------- cut here ---------------------- pascal void *alloca(long size) = { 0x201F, /* MOVE.L (SP)+,D0 ;get size */ 0x5380, /* SUBQ.L #1,D0 ;long-word allign, allowing for */ 0x0240, 0xFFFC, /* ANDI.W #-4,D0 ; 4 bytes already on the stack */ 0x9FC0, /* SUB.L D0,SP ;allocate it */ 0x2F0F /* MOVE.L SP,-(SP) ;return value on stack */ }; ---------------------- the end! ---------------------- Jay Finger, {ames,mit-eddie}!attctc!torch ames!torch@attctc