Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!simtel!swidir.switch.ch!newsfeed.ACO.net!Austria.EU.net!EU.net!newsfeed.internetmci.com!usenet.eel.ufl.edu!willow!amigagod
From: Out of his mind <amigagod@grove.ufl.edu>
Newsgroups: comp.unix.bsd.netbsd.misc
Subject: m68k alloca.S replacement
Date: Fri, 11 Aug 1995 16:59:17 -0400
Lines: 191
Message-ID: <Pine.ULT.3.91.950811162941.17184D-100000@willow>
NNTP-Posting-Host: grove.ufl.edu
Mime-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
X-Sender: amigagod@willow
X-URL: http://grove.ufl.edu/~amigagod/
While resuming work on AmiNIX (after months of financial difficulty), I've
been reworking a couple of the NetBSD libc sources in assembly, and found
the alloca.S supplied for m68k to not only be lacking but quite unstable.
(To see what I mean, read the source and ask yourself what a calling
function will find if it tries to access a stack argument after calling
alloca().)
Attached below are the as (I think it's fully as compliant; please correct
me if not--it translates to Metacomco correctly), and Metacomco format
sources for an alloca replacement that is very compact. It acts much like
the GNU alloca; it doesn't use the stack for storage and allows an
alloca(0) call to do garbage collection now and then. It *should* work on
just about any m68k-based OS that has the ANSI C functions malloc, free,
and realloc. And no, this doesn't free() before realloc()ing (who ever
allowed that horrid situation in the first place?).
Feel free to give this a lookthrough; I haven't gotten the code to screw
up yet. I'd be curious, though, to see if it passes the GNU autoconf
alloca() tests.
===== alloca.S =====
/*
* alloca.S - alloca(), properly implemented for m68k
*
* Behaves much like GNU alloca, but with far less overhead
* (doesn't actually use the stack, and supports alloca(0) flush call)
*
* Author: Todd Vierling
* Version: @AmiNIX: src/lib/libc/stdlib/alloca.S 0.9.1 95.08.11@
*/
#include <machine/asm.h>
.globl _malloc
.globl _free
.globl _realloc
ENTRY(alloca)
movml d2/a2,sp@- | save d2,a2
movl allocstack,a2 | get current allocstack
startflush:
movl a2,d1 | test register (68000 ok)
beq getnew | if 0, assume flushed and get new
cmpl a2@(4),sp | compare stackpointers
beq flushed | equal, assume flushed
bgt getnew | greater, assume flushed and get new
flush:
movl a2,sp@- | save a2
movl a2@(8),a2 | get first entry
floop:
movl a2,d1 | test block address (68000 ok)
beq endfloop | if 0, done flushing
movl a2,sp@- | push memptr
movl a2@,a2 | get address of next block
jbsr _free | free memptr
lea sp@(4),sp | ignore memptr
bra floop | try again
endfloop:
movl sp@,a2 | pop and repush a2
movl a2@,a2 | get new struct pointer
jbsr _free | free old struct
lea sp@(4),sp | ignore saved a2
bra startflush | try to flush again
getnew:
movl sp@(12),d0 | alloca(0)? (flush only)
beq quit | yes, skip allocation
moveq #12,d0 | size of struct
movl d0,sp@- | push as argument to malloc()
jbsr _malloc | get memory
lea sp@(4),sp | ignore 12
tstl d0 | is memory full?
beq quit | yes, skip everything
movl d0,a0 | make it an a-register (no test)
movl a2,a0@+ | save old allocstack
movl sp,a0@+ | shove in the stackpointer
clrl a0@ | start entry at 0
lea a0@(-8),a2 | new allocstack
flushed:
movl sp@(12),d0 | alloca(0)? (flush only)
beq quit | yes, skip allocation
addql #4,d0 | add 4 for pointer
movl d0,sp@- | allocation bytes
jbsr _malloc | try to allocate them
lea sp@(4),sp | ignore argument
movl d0,d2 | did we get it?
beq quit | no, return 0
movl a2@(8),a1 | get first block
exg a1,d2 | swap first block/new block
movl d2,a1@ | insert first block in new block
movl a1,a2@(8) | put new block in struct
movl a1,d0 | prepare return value
addql #4,d0 | skip over list pointer
quit:
movl a2,allocstack | put (possibly new) allocstack back
movml sp@+,d2/a2 | pop d2,a2
rts | return
/*
* The allocstack structure has the following format:
* struct allocstack {
* struct allocstack *next; * next higher level
* u_int32_t stackptr; * sp for which this reflects
* void *memfirst; * the entries themselves, linked list
* };
*/
.data
allocstack:
.long 0
===== alloca.asm
machine 68000
public _malloc
public _free
public _realloc
cseg
even
public _alloca
_alloca:
movem.l d2/a2,-(sp)
move.l allocstack,a2
startflush:
move.l a2,d1
beq getnew
cmp.l 4(a2),sp
beq flushed
bgt getnew
flush:
move.l a2,-(sp)
move.l 8(a2),a2
floop:
move.l a2,d1
beq endfloop
move.l a2,-(sp)
move.l (a2),a2
jsr _free
lea 4(sp),sp
bra floop
endfloop:
move.l (sp),a2
move.l (a2),a2
jsr _free
lea 4(sp),sp
bra startflush
getnew:
move.l 12(sp),d0
beq quit
moveq #12,d0
move.l d0,-(sp)
jsr _malloc
lea 4(sp),sp
tst.l d0
beq quit
move.l d0,a0
move.l a2,(a0)+
move.l sp,(a0)+
clr.l (a0)
lea -8(a0),a2
flushed:
move.l 12(sp),d0
beq quit
addq.l #4,d0
move.l d0,-(sp)
jsr _malloc
lea 4(sp),sp
move.l d0,d2
beq quit
move.l 8(a2),a1
exg a1,d2
move.l d2,(a1)
move.l a1,8(a2)
move.l a1,d0
addq.l #4,d0
quit:
move.l a2,allocstack
movem.l (sp)+,d2/a2
rts
dseg
allocstack:
dc.l 0
=====
=== Todd Vierling (amigagod@grove.ufl.edu): Finger for PGP 2.6 public key ===
=== I remember the hopes, the fears, the successes, and the failures that ===
== brought us to the pinnacles of achievement today. -- essay "I Remember" ==
=== Vierling's Law: The revolution won't be televised; it will be posted. ===