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. ===