Subversion Repositories SlidingHeap

Compare Revisions

Ignore whitespace Rev 6 → Rev 7

/tags/v2_12_1/!SlidingHp/!Help
New file
0,0 → 1,18
Sliding Heap module by Steven Haslam 1992.
 
32 bit compatibility by Christopher Bazley and much additional work
by Harriet Bazley.
 
This version has been packaged for the RISC OS Packaging project
(www.riscpkg.org) by Alan Buckley <alan_baa@hotmail.com>.
 
To package it I've included it in an Application directory !SlidingHp
that sets a variable SlidingHp$Dir.
 
There are two packages, the normal that only includes the module and
the BASIC library to use it and a "dev" package that includes the
documentation and examples.
 
If you have installed the "dev" package you will find the documentation
and examples by holding shift and double clicking on the !SlidingHp
application.
/tags/v2_12_1/!SlidingHp/!Boot,feb
New file
0,0 → 1,3
| Obey file to set location of sliding Heap module
 
Set SlidingHp$Dir <Obey$Dir>
/tags/v2_12_1/!SlidingHp/!Run,feb
New file
0,0 → 1,3
| Obey file to set location of sliding Heap module
 
Set SlidingHeap$Dir <Obey$Dir>
/tags/v2_12_1/RiscPkg/SlidingHeap.inc
New file
0,0 → 1,7
RiscPkg/*
SysVars/*
Apps/Library/!SlidingHp/SlidingHp
Apps/Library/!SlidingHp/SHeap
Apps/Library/!SlidingHp/!Boot
Apps/Library/!SlidingHp/!Run
Apps/Library/!SlidingHp/!Help
/tags/v2_12_1/RiscPkg/Control
New file
0,0 → 1,18
Source: SlidingHeap-Src
Version: 2.12-1
Section: Library
Priority: Optional
Maintainer: Alan Buckley <alan_baa@hotmail.com>
Standards-Version: 0.1.0
Licence: Free
Description: Create and manage a sliding heap of blocks of memory.
This is the source package.
 
Package: SlidingHeap
Description: Create and manage a sliding heap of blocks of memory.
This is the runtime package that just includes the sliding heap module and a BASIC library to use it.
 
Package: SlidingHeap-Dev
Description: Create and manage a sliding heap of blocks of memory.
This is the developer package that includes the examples and documentation.
Depends: SlidingHeap
/tags/v2_12_1/RiscPkg/Copyright
New file
0,0 → 1,15
The Sliding Heap module is copyright Steven Haslam 1992 and is distributed under the GNU Public licence.
 
32 bit compatibility by Christopher Bazley and much additional work by Harriet Bazley.
 
This version downloaded for packaging from www.startfighter.acornarcade.com/mysite/programming.htm.
 
Package maintained by Alan Buckley (alan_baa@hotmail).
 
For details of the GNU public licence see the file:
 
<Common_Licences$Dir>.GPL-1.txt
 
or downloaded it from the URL:
 
http://www.riscpkg.org/licences/GPL-1.txt
/tags/v2_12_1/RiscPkg/Rules
New file
0,0 → 1,40
# Makefile for Sliding Heap Module packages
 
VERSION=2.12-1
PACKAGES= \
SlidingHeap_$(VERSION) \
SlidingHeap-Dev_$(VERSION)
 
INSTALL_TO=Apps/Library
APP_DIR=Temp/$(INSTALL_TO)/!SlidingHp
 
 
pkg:
rm -rf Temp
mkdir -p Temp/RiscPkg
mkdir -p $(APP_DIR)
cp RiscPkg/Copyright Temp/RiscPkg
cp -R SysVars Temp/SysVars
cp !SlidingHp/!Help $(APP_DIR)
cp !SlidingHp/!Boot $(APP_DIR)
cp !SlidingHp/!Run $(APP_DIR)
cp -R Original/!Demo $(APP_DIR)
cp -R Original/!Errortest $(APP_DIR)
cp -R Original/Docs $(APP_DIR)
cp Original/ReadMe $(APP_DIR)
cp Original/SHeap $(APP_DIR)
cp Original/SlidingHp $(APP_DIR)
make -C Temp -f ../RiscPkg/Rules $(PACKAGES)
rm -rf Temp
 
.PHONY: $(PACKAGES)
$(PACKAGES): %:
riscpkg-gencontrol $(firstword $(subst _, ,$@)) < ../RiscPkg/Control > RiscPkg/Control
rm -f ../RiscPkg/$@
zip -r ../RiscPkg/$@ * -i@../RiscPkg/$(firstword $(subst _, ,$@)).inc
 
# If you wanted to rebuild the module use this target
build: Original/BasSource/SlidingHp
Run Original.BasSource.SlidingHp
 
 
/tags/v2_12_1/RiscPkg/SlidingHeap-Dev.inc
New file
0,0 → 1,6
RiscPkg/*
Apps/Library/!SlidingHp/!Demo/*
Apps/Library/!SlidingHp/!Errortest/*
Apps/Library/!SlidingHp/Docs/*
Apps/Library/!SlidingHp/ReadMe
 
/tags/v2_12_1/Original/!Demo/!RunImage,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Demo/Templates,fec
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Demo/!Help
New file
0,0 → 1,29
Demo Task for Sliding Heap Library
==================================
 
This application demonstrates how a program can load data into sliding blocks within its Wimpslot, resizing both blocks and Wimpslot as necessary as the size of the data varies.
 
If you run !Demo, a window will open showing two sets of icons. These represent two sliding blocks set up at the start of the program. For each sliding block, there is one icon showing its current size (initially zero), one showing the memory address of the start of the block in hexadecimal, and one large icon showing the contents of the block.
 
Drag any file onto the leftmost of the two large icons. You will see its contents reflected in the icon - if it is a text file, you may even be able to read it! The filesize will also be shown.
 
You will notice that although the address of this block has not changed,the address of the other block (on the right hand side) has gone up, although this block is still empty. This is because the second block 'slid' upwards in memory as the block below it expanded - that's why they are called 'sliding' blocks....
 
If you check the Wimpslot of the program (the green bar labelled Demo in the task display) you may see that it has also increased from its original size of 64K. Load a second, larger, file into the right-hand block and the Wimpslot will definitely increase! The program is automatically claiming more memory so that the sliding blocks can expand as far as necessary - it is possible to load files of many megabytes into this one small program, if you have enough memory to spare. Load smaller files, and you will see the Wimpslot shrink back to the minimum necessary. Close the window, and the application will quit automatically.
 
--------------------
 
If you load the BASIC file !Demo.!RunImage, you can see how it works. I've used just five of the procedures from the SHeap library file: PROCinitheaps, FNcreate_anchor, PROCcreate_named_sliding_block, PROCextend_named_sliding_block and PROCverify_heap (as a precaution). The relevant sections of the file are highlighted by lines of five stars: *****.
 
The sliding block handling itself isn't particularly complex; I initialise the sliding heap at the start of the program, create 'anchors' and attach blocks to them. Then, when a file is dragged onto one of the program's icons, I get the file's size, resize the relevant block to fit, and use OS_File 16 to load the file into that block.
 
The rest of the program is purely cosmetic and concerned with updating the icons.
 
----------------------
 
Harriet Bazley <harriet.bazley@blueyonder.co.uk>
 
43 Wilton Grove
Wimbledon
London SW19 3QU
4th November 2002
/tags/v2_12_1/Original/!Demo/SHeap,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Demo/SlidingHp,ffa
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Demo/!Run,feb
New file
0,0 → 1,5
WimpSlot -min 32K -max 32K
Set Demo$Dir <Obey$Dir>
RMEnsure SlidingHeap 2.0 RMLoad <Demo$Dir>.SlidingHp
Run <Demo$Dir>.!RunImage
 
/tags/v2_12_1/Original/BasSource/SlidingHp,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/Docs/Overview
New file
0,0 → 1,292
SLIDING HEAP MODULE
===================
 
The Sliding Heap module creates and manages a sliding heap of blocks of memory claimed from a program's Wimpslot as necessary, thus avoiding the fragmentation caused by repeatedly claiming and releasing memory from the RMA. Each block is assigned to an 'anchor', a single word of memory which is guaranteed always to hold the address of the start of that block. The order of blocks in the heap may change and their location will vary as other blocks grow and shrink; thus sliding blocks should always be referenced via their anchors.
 
The SHeap BASIC library can also manage a fixed heap at the base of the sliding heap via the OS_Heap SWIs. This can be used to store data where the size of the block will not change and where it is important for the base address of the block to remain constant; however this heap is liable to fragmentation, and no code is provided to scrap or resize fixed heap blocks. For normal usage it is expected that sliding blocks will be employed.
 
--------------------------------------------------------------------------------
BASIC INTERFACE
===============
 
A library of BASIC functions and procedures has been provided to make the Sliding Heap module simple to access from BASIC programs. This SHeap library will manage the Wimpslot as required and carry out all the necessary SWI calls. All global variables used within the library are prefixed by 'sh_', e.g. 'sh_fixedheapsize%', and programs should ensure that none of their internal variables share this prefix.
 
Usage
----
 
PROCinitheaps(fixedheapsize%,slidingblocks%)
 
This procedure should be called during the initialisation of any program wishing to link with the SHeap library, before any sliding blocks can be claimed. fixedheapsize% defines the initial size of the fixed heap, in bytes. slidingblocks% defines the maximum number of 'slots' reserved in the sliding heap and thus the maximum number of sliding blocks which may be usedat once. This limit may be increased subsequently by calling FNincreaseslots.
 
The recommended default is to set both parameters to 128 unless there is a particular reason to do otherwise.
 
Note that calling PROCinitheaps will automatically increase your program's Wimpslot by one 'page' of memory, although this space will initially be largely empty. The Wimpslot will not visibly change thereafter until you have stored more than one 'page' worth of data in the heap.
 
(Page sizes vary between different machines, but for most modern RISC OS computers the Wimpslot will increase and decrease by 4 kilobytes at a time. On machines running RISC OS 3.1 or earlier the initial increase may be as much as 32 kilobytes.)
 
 
FNcreate_anchor(name$)
 
This function returns the address of a single word of memory, which is known as the 'anchor' location for a sliding block. It serves the double purpose of identifying a given block when supplied as a parameter to other heap management functions, and of storing a pointer to the start of that block; if the contents of this word are zero, then no block is currently attached to this anchor. name$ should be supplied as a short string, which will be used to identify this block in error messages and in the output from PROCheapsinfo. Once created, anchors cannot be destroyed, although the blocks to which they refer may be scrapped and recreated.
 
Note that calling FNcreate_anchor does not in itself create a *block*. Before the anchor can be used, PROCcreate_named_sliding_block must be called.
 
 
PROCcreate_named_sliding_block(anchor%,size%)
 
This procedure reserves a new block of size% bytes within the sliding heap, increasing the Wimpslot if required. anchor% should be a value previously returned by FNcreate_anchor. Sliding heap blocks are always word-aligned; size% will be rounded up to a multiple of 4 bytes if necessary.
 
EXAMPLE:
test%=FNcreate_anchor("test")
PROCcreate_named_sliding_block(test%,232)
ptr%=!test%:REM get start of block
SYS"OS_File",16,"$.data",ptr% :REM load data into block
 
Do not use PROCcreate_named_sliding_block to change the size of an existing block - use PROCextend_named_sliding_block instead.
 
 
PROCextend_named_sliding_block(anchor%,newsize%)
 
This procedure increases (or decreases - the name is misleading) the size of a heap block. If the block does not yet exist, it will be created instead.
 
Other blocks may slide around as the block size changes. Note that newsize% gives the *total* size of the resulting block, not the amount by which you wish to increment or decrement it! The current size of the block may first be obtained, if desired, via FNsliding_block_size.
 
 
FNsliding_block_size(anchor%)
 
This function returns the current size, in bytes, of the sliding block referenced by anchor%.
 
 
PROCscrap_sliding_block(anchor%)
 
This procedure will discard a sliding block, returning its memory to the heap. The Wimpslot will shrink if appropriate.
 
Note that the anchor is NOT deleted and can be reused later. In fact anchors cannot be deleted.
 
 
PROCverify_heap
 
This procedure will force a check that none of the blocks have become corrupted, and that the heap's internal data structures are still valid. The heap is automatically verified after sliding block operations, but corruption (for example, writing to an old pointer after the blocks have moved) will not otherwise show up until next time a heap operation is carried out. Inserting PROCverify_heap earlier in the program allows you to test at what stage corruption occurred.
 
Note that a corrupted heap cannot be restored - PROCverifyheap does not return an error code, but will return silently if the heap verifies correctly and otherwise abort with an error.
 
 
PROCdestroyheaps
 
This procedure will destroy both fixed and sliding heaps, and reset the Wimpslot. It does *not* destroy any anchors, although it does reset any anchors in use to zero to indicate that those blocks have been scrapped.
 
The heap may be reinitialised by calling PROCinitheaps again, and the same anchors reused.
 
 
PROCheapsinfo(block%)
 
This procedure will print a breakdown of the current fixed and sliding heap contents to screen for debugging purposes. The parameter block% should point to a block of length at least 256 bytes which can be used as workspace.
 
EXAMPLE:
Fixed heap
----- ----
Heap base : &00088000
Heap size : 128 bytes
Largest free : 108 bytes
Total free : 112 bytes
Sliding heap
------- ----
Heap information requested
Generated by SlidingHeap 2.01, © Steven Haslam 1992 (29 Oct 2002)
Heap base : &00088100
Slots available in heap : 128
Slots used : 1
Top of heap : &00088934
Blocks: (not necessarily in the order as in the heap)
| Address | Length | Name
| &00088914 | 32 bytes | test
 
 
FNcreate_fixed_block(size%)
 
This function will create a block of size% bytes at the end of the fixed heap, shifting the sliding blocks upwards in memory and increasing the Wimpslot if necessary. It returns the address of the new block.
 
 
FNincreaseslots(new_maximum%)
 
This procedure will increase the total number of slots available in the heap, thus allowing up to new_maximum% blocks to be handled simultaneously. To find the number of slots currently allowed, use FNincreaseslots(0).
 
--------------------------------------------------------------------------------
 
SWI INTERFACE
============
 
The various software interrupts provided by the module can also be called directly, although a program that does this will have to provide its own Wimpslot (or other memory) management - the SlidingHeap SWIs themselves simply handle a heap at a given location without claiming or releasing memory. On entry, all SWIs require the location of the base of the heap to be passed in R0; this makes it easy for several applications to use the module at once, but also implies that a single program could theoretically manage two independent heaps.
 
 
SWI calls provided
------------------
 
&000C0280 SlidingHeap_Create
&000C0281 SlidingHeap_NewBlock
&000C0282 SlidingHeap_ScrapBlock
&000C0283 SlidingHeap_ExtendBlock
&000C0284 SlidingHeap_HeapInfo
&000C0285 SlidingHeap_VerifyHeap
&000C0286 SlidingHeap_NextFree
&000C0287 SlidingHeap_IncreaseSlots
&000C0288 SlidingHeap_DescribeBlock
&000C0289 SlidingHeap_ShiftHeap
 
Errors generated
----------------
 
&000001E6 "Unknown SlidingHeap operation" [UNKNOWN SWI]
&00C02800 "No more free slots in heap" [NewBlock]
&00C02801 " Block overflow in Sliding Heap (%*0)" [VerifyHeap]
&00C02802 "You must have at least one block in the heap!" [Create]
&00C02803 "Heap ID corrupted (Bad signature)" [VerifyHeap]
&00C02804 "Start of heap corrupted (Bad signature)" [VerifyHeap]
&00C02805 "Top of heap corrupted (Bad signature)" [Unused!]
&00C02806 "Anchor does not point to block (%*0) [VerifyHeap]
&00C02807 "Couldn't find anchor in heap (ScrapBlock)" [ScrapBlock]
&00C02808 "Couldn't find anchor in heap (ExtendBlock)" [ExtendBlock]
&00C02809 "Unable to decrease number of slots in heap" [IncreaseSlots]
&00C0280A "Heap is not in valid memory" [VerifyHeap]
&00C0280B "Couldn't find anchor in heap (DescribeBlock)" [DescribeBlock]
 
Heap format
-----------
 
base+0 = heap signature word "«Hz»"
base+4 = slot block count <n>
base+8 = address of start of blocks
base+12 = address of end of last block (and hence of the heap)
 
<n> slots of 4 words each
slot+0 = pointer to start of block
slot+4 = pointer to anchor word
slot+8 = block size
slot+12 = pointer to block name string
 
after last slot
base+ <n+1>*16 = block signature word "Blck"
start of blocks
each block is terminated by an extra word of data "Blck"
<heap block data, block sig word>
<heap block data, block sig word>
etc.
end of last block
 
 
Software Interrupts in detail
----------------------------
 
SlidingHeap_Create (&000C0280)
 
This SWI is called to initialise an empty sliding heap; sufficient memory must have been allocated for the heap before calling SlidingHeap_Create. The parameters define the location of the start of the heap, which grows upwards, and the maximum number of 'slots' available in the heap. Each slot controls a single sliding block.
 
=> R0 = base of new heap
R1 = 2 (optional)
if R1 = 2: R2 = maximum number of sliding blocks
if R1 and R2 are set to 0: assign 15 slots in heap
 
<= R0,R1,R2 corrupted
 
 
SlidingHeap_NewBlock (&000C0281)
 
This SWI is called to initialise an empty sliding block; sufficient memory must have been allocated to the heap to accommodate the desired block size (which will be rounded up to a multiple of 4 bytes) before calling SlidingHeap_NewBlock. If all the slots in the heap have already been initialised it will return an error.
 
=> R0 = base of heap
R1 = address of anchor word to use
R2 = size of block to reserve
R3 = address of string to be used as name of block
 
<= all registers preserved
 
 
SlidingHeap_ScrapBlock (&000C0282)
 
This SWI is called to delete a sliding block, free up the slot it occupied, and return the spare memory to the heap. This may enable the application to shrink its heap, but will not in itself do so. The memory allocated for the anchor will not be freed - instead, the anchor word will contain zero.
 
=> R0 = base of heap
R1 address of anchor word
 
<= all registers preserved
 
 
SlidingHeap_ExtendBlock (&000C0283)
 
This SWI is called to change the size of a sliding block, either increasing or decreasing it (the name is deceptive). Note that the total new size is specified, not the change in size. If the block is to grow, sufficient additional memory must already have been allocated to the heap; if it is to shrink, then the memory must be freed manually afterwards.
 
=> R0 = base of heap
R1 = address of anchor word
R2 = new block size
 
<= all registers preserved
 
 
SlidingHeap_HeapInfo (&000C0284)
 
This SWI prints out details of heap usage - address of base of heap, number of slots used out of the total, address of top of heap, and address, length and name of every current block, in slot order. It prints the information directly to the current output stream and is used for debugging only.
 
=> R0 = base of heap
 
<= all registers preserved
 
 
SlidingHeap_VerifyHeap (&000C0285)
 
This SWI checks the data held in the heap base and slots. It checks that the start and end of heap addresses correspond to valid memory locations and that the heap signature word is still present (and thus that the start of the heap has not been overwritten). It then checks each block for the block signature word at the end of the data, ensuring that the block start and length data are correct and that the end of the block has not been overwritten by attempting to write to another block using a bad pointer (the most common cause of heap corruption). It exits silently if no problem is found, and otherwise returns the relevant error.
 
It is a good idea to call this SWI after every call to SlidingHeap_NewBlock,SlidingHeap_ScrapBlock, SlidingHeap_ExtendBlock or SlidingHeap_ShiftHeap. It can also be inserted after other operations during debugging to determine where heap corruption is occurring.
 
=> R0 = base of heap
 
<= all registers preserved
 
 
SlidingHeap_NextFree (&000C0286)
 
This SWI returns the address of the next free word after the end of the last sliding block. This address can be used to test how much free space remains before enlarging or shrinking the heap.
 
=> R0 = base of heap
 
<= R0 = address of first word after final heap block
 
 
SlidingHeap_DescribeBlock (&000C0288)
 
This SWI returns the four slot data items for a given block.
 
=> R0 = base of heap
R1 = address of anchor word
 
<= R0 = start of block
R1 = address of anchor word
R2 = size of block
R3 = address of name string
 
SlidingHeap_IncreaseSlots (000C0287)
 
This SWI increases the maximum number of slots in the heap, or returns the current number of slots allocated.
 
=> R0 = current address of base of heap
R1 = new maximum number of slots, or 0 to read current value
 
<= R1 updated if 0 on entry
all other registers preserved
 
 
SlidingHeap_ShiftHeap (&000C0289)
 
This SWI moves the entire sliding heap in memory, updating the internal references and the external anchor pointers.
 
=> R0 = current address of base of heap
R1 = new address for base of heap
 
<= all registers preserved
/tags/v2_12_1/Original/Docs/SlidingHp,3d6
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/Docs/GNULicence
New file
0,0 → 1,345
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
 
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
 
 
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
 
 
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
 
 
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
 
 
Appendix: How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
 
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
 
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
 
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
 
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
/tags/v2_12_1/Original/!Errortest/!RunImage,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Errortest/BIG,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/!Errortest/!Run,feb
New file
0,0 → 1,9
Set ErrorTest$Dir <Obey$Dir>
RMEnsure SlidingHeap 2.10 RMLoad <ErrorTest$Dir>.^.SlidingHp
| we need the IncreaseSlots call to be available
Wimpslot -min 32k -max 32k
SetEval ErrorCode 255
Taskwindow "<ErrorTest$Dir>.!RunImage" -quit -ctrl -wimpslot 32k
If Errorcode=0 Then Run <ErrorTest$Dir>.Big
| a nice surprise!
Unset ErrorCode
/tags/v2_12_1/Original/!Errortest/Dungeon,ff7
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/SHeap,ffb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/SlidingHp,ffa
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+ application/octet-stream
/tags/v2_12_1/Original/ObjAsm/SlidingHp.s
New file
0,0 → 1,1172
;
; SlidingHeap module - a memory manager that works by using 'anchor points'
; Copyright (C) 1992 Steven Haslam
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
 
 
; Notes on changes for compatibility with 32-bit ARM modes
; ========================================================
;
; Since the original source code has been mislaid, this disassembly was
; generated automatically by Armalyser and further optimised and modified by
; hand. It is suitable for use with ObjAsm.
;
; In 26-bit mode caller flags are preserved by the SWI handler (except for
; setting V on error). In 32-bit mode, caller flags are not preserved by
; SlidingHeap SWIs.
;
; Single-register LDM/STMs have been replaced with LDR/STRs, since this is
; faster on some new processors.
;
; The old module explicitly enabled interrupts on entry to its SWI handler.
; This behaviour has been removed, since there seems little point and it may
; actually be counter-productive.
;
;
; The module no longer corrupts R0 (pointer to heap base) by default on exit
; from SWIs, making it easier to use from assembler.
;
; Christopher Bazley (chrisbazley@bigfoot.com), 26th October 2002
; Harriet Bazley (harriet.bazley@blueyonder.co.uk), 29th October 2002
 
 
; Errors + numbers
; &000001E6 "Unknown SlidingHeap operation" [UNKNOWN SWI]
; &00C02800 "No more free slots in heap" [NewBlock]
; &00C02802 "You must have at least one block in the heap!" [Create]
; &00C02803 "Heap ID corrupted (Bad signature)" [VerifyHeap]
; &00C02804 "Start of heap corrupted (Bad signature)" [VerifyHeap]
; &00C02805 "Top of heap corrupted (Bad signature)" [Unused!]
; &00C02807 "Couldn't find anchor in heap (ScrapBlock)" [ScrapBlock]
; &00C02808 "Couldn't find anchor in heap (ExtendBlock)" [ExtendBlock]
; &00C02809 "Unable to decrease number of slots in heap" [IncreaseSlots]
; &00C0280A "Heap is not in valid memory" [VerifyHeap]
; &00C0280B "Couldn't find anchor in heap (DescribeBlock)" [DescribeBlock]
 
; Same position in 26-bit mode PC and 32-bit mode PSR
V_flag * (1<<28)
; used in constructing error blocks - first word occupied by error number
short_workspace * (256-4)
 
; Armalyser analysis of IDEFS::Tamzin.$.Programming.SlidingHeap.SlidingHp
 
; Generated by Armalyser 0.33 (05-Sep-2002) DEEJ Technolgy PLC
; From IDEFS::Tamzin.$.Programming.SlidingHeap.SlidingHp
 
XOS_Module EQU &02001E
XOS_ValidateAddress EQU &02003A
XOS_WriteS EQU &020001
XOS_ConvertHex8 EQU &0200D4
XOS_Write0 EQU &020002
XOS_ConvertCardinal4 EQU &0200D8
XOS_ConvertFixedFileSize EQU &0200EB
XOS_WriteC EQU &020000
XOS_SubstituteArgs EQU &020043
XOS_WriteI EQU &020100
XOS_ReadUnsigned EQU &020021
 
AREA |SlidingHp$$Code|, CODE, READONLY
 
ORG &0
 
|L00000000.Module_Header.Offset|
DCD &00000000 ; Start offset
DCD |L0000013C.Initialisation_code| ; Initialisation offset
DCD |L00000154.Finalisation_code| ; Finalisation offset
DCD &00000000 ; Service call handler offset
DCD |L00000044.String| ; Title string offset -> "SlidingHeap"
DCD |L00000050.String| ; Help string offset -> "Sliding Heap 2.12 (13 Oct 2003) 32-bit compatible"
DCD |L00000070.Command_Table.String| ; Help and command keyword table offset
DCD &000C0280 ; SWI chunk base number
DCD |L00000168.SWI_handler_code| ; SWI handler code offset
DCD |L000000CC.SWI_Table.String| ; SWI decoding table offset
DCD &00000000 ; SWI decoding code offset
DCD 0 ; No MessageTrans file
DCD module_flags ; Flags word offset
 
module_flags
DCD 1 ; flags word (32-bit compatible)
 
|L0000002C.String|
DCB "© Steven Haslam 1992",0 ;~~ String -/-
|L00000044.String|
DCB "SlidingHeap",0 ; String -/- (referenced)
|L00000050.String|
DCB "Sliding Heap\t2.11 (16 Dec 2002) 32-bit compatible",0 ; String -/- (referenced)
ALIGN
 
|L00000070.Command_Table.String|
DCB "HeapInfo",0 ; Command Table: Command
ALIGN
DCD |command1| ; Command Table: Code offset -> Code @ &00000BD4
DCD &00010101 ; Command Table: Infomation Word
DCD |syntax1| ; Command Table: Syntax offset -> String array: "Syntax: *HeapInfo <address>",0
DCD |help1| ; Command Table: Help offset -> String array: "*HeapInfo will display information on the given sliding heap.\r\rS"
DCB "VerifyHeap",0 ; Command Table: Command
ALIGN
DCD |command2| ; Command Table: Code offset -> Code @ &00000B3C
DCD &00010101 ; Command Table: Infomation Word
DCD |syntax2| ; Command Table: Syntax offset -> String array: "Syntax: *VerifyHeap <address>",0
DCD |help2| ; Command Table: Help offset -> String array: "*VerifyHeap will check the integrity of the given heap.\r\rSyntax:"
DCB "Sliding_Heap",0 ; Command Table: Command
ALIGN
DCD &00000000 ; Command Table: Code offset
DCD &00000000 ; Command Table: Infomation Word
DCD &00000000 ; Command Table: Syntax offset
DCD |help3| ; Command Table: Help offset -> String: "SlidingHeap is a memory manager that works by using `anchor poin"
DCD &00000000 ; Command Table: End
 
|L000000CC.SWI_Table.String|
DCB "SlidingHeap",0 ; SWI Table
DCB "Create",0 ; SlidingHeap_Create
DCB "NewBlock",0 ; SlidingHeap_NewBlock
DCB "ScrapBlock",0 ; SlidingHeap_ScrapBlock
DCB "ExtendBlock",0 ; SlidingHeap_ExtendBlock
DCB "HeapInfo",0 ; SlidingHeap_HeapInfo
DCB "VerifyHeap",0 ; SlidingHeap_VerifyHeap
DCB "NextFree",0 ; SlidingHeap_NextFree
DCB "IncreaseSlots",0 ; SlidingHeap_IncreaseSlots
DCB "DescribeBlock",0 ; SlidingHeap_DescribeBlock
DCB "ShiftHeap",0 ; SlidingHeap_ShiftHeap
DCB 0
ALIGN
 
|L0000013C.Initialisation_code|
STMFD R13!,{R0-R3,R14} ; Entry Point, Initialisation code, (Referenced)
MOV R0,#6 ; Claim
MOV R3,#&0100 ; 256-byte workspace
SWI XOS_Module
STRVC R2,[R12,#0] ; store block address in private word
LDMFD R13!,{R0-R3,PC} ; exit, returning error status in V flag
 
|L00000154.Finalisation_code|
STMFD R13!,{R0-R3,R14} ; Entry Point, Finalisation code, (Referenced)
MOV R0,#7 ; Free
LDR R2,[R12,#0] ; get address of block from private word
SWI XOS_Module
LDMFD R13!,{R0-R3,PC} ; exit, returning error status in V flag
 
|L00000168.SWI_handler_code|
LDR R12,[R12,#0]
CMP R11,#&0A ; =10
ADDCC PC,PC,R11,LSL #2 ; Dynamic branch
B |Unknown| ; Ends
B |SlidingHeap_Create| ; Branch Table Offset 0, Ends
B |SlidingHeap_NewBlock| ; Branch Table Offset 1, Ends
B |SlidingHeap_ScrapBlock| ; Branch Table Offset 2, Ends
B |SlidingHeap_ExtendBlock| ; Branch Table Offset 3, Ends
B |SlidingHeap_HeapInfo| ; Branch Table Offset 4, Ends
B |SlidingHeap_VerifyHeap| ; Branch Table Offset 5, Ends
B |SlidingHeap_NextFree| ; Branch Table Offset 6, Ends
B |SlidingHeap_IncreaseSlots| ; Branch Table Offset 7, Ends
B |SlidingHeap_DescribeBlock| ; Branch Table Offset 8, Ends
B |SlidingHeap_ShiftHeap| ; Branch Table Offset 9, Ends
 
|Unknown|
ADR R0,|Unknown_err| ; -> Error Block Word: &000001E6
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|Unknown_err|
DCD &000001E6 ; Error Block Word r/- (referenced)
DCB "Unknown SlidingHeap operation",0 ; Error Block String -/-
ALIGN
 
|SlidingHeap_IncreaseSlots|
; On entry, R0 points to base of heap
; R1 holds new maximum number of slots desired in heap
; if R1 equals 0
; then exit, returning current number of slots in R1
; else extend heap base to make room for increased number of slots
 
; on exit all registers preserved
STMFD R13!,{R0-R7,R14}
LDR R3,[R0,#4] ;old number of slots
CMP R1,#0 ;if R1 equals zero, return,
BEQ |reportslots_exit| ;supplying current slot count in R1
SUBS R6,R1,R3 ;number of extra slots
BLO |decreaseslots|
MOV R7,R0 ;store start of heap base
;(we are about to corrupt this)
 
LDR R0,[R7,#8] ;start of blocks
LDR R5,[R7,#12] ;end of last block...
ADD R5,R5,#4 ;... start of following word
SUB R2,R5,R0 ;R2 holds total length of blocks
ADD R1,R0,R6,LSL #4 ;R1 holds new start of blocks =
;old start plus slots*16 (each is 16 bytes long)
BL |shiftblock| ;move heap blocks up
 
MOV R1,#0 ;value to store in new slots
MOV R2,R6 ;number of slots to initialise
ADD R0,R7,#&10 ;start of current slots
ADD R0,R0,R3,LSL #4 ;offset to first new slot
;R3 * 16 is end of old slots
BL |initheap_loop| ;initialise R2 slots
;starting from R0
 
MOV R1,R3 ;old number of slots
ADD R2,R1,R6 ;total new number of slots
STR R2,[R7,#4] ;update number of slots
 
ADD R0,R7,#&10 ;get start of slots
MOV R5,R6,LSL #4 ;offset by which heap has moved
;R1 still holds old number of slots, i.e. the number that need updating
;R7 holds heap base
B |shift_updateslots| ;now update all old slots
;(exit is via SlidingHeap_ShiftHeap)
 
|decreaseslots|
; SlidingHeap_IncreaseSlots exit
ADR R0,decreaseslots_err ; -> Error number &C02809
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|decreaseslots_err|
DCD &00C02809 ; Error number
DCB "Unable to decrease number of slots in heap",0
ALIGN
 
|reportslots_exit|
LDMFD R13!,{R0-R7,R14}
LDR R1,[R0,#4] ;return current number of slots in R1
; SlidingHeap_IncreaseSlots exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
MOVNES PC,R14 ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
MOV PC,R14 ; 32-bit exit, caller flags corrupted
 
 
|SlidingHeap_Create|
; on entry R0 points to base of heap
; If R1 equals 2
; then R2 holds max. number of sliding blocks
; else use default value of 15
 
; on exit R0,R1,R2 corrupted
 
CMP R1,#2
MOVNE R2,#&0F ; '2' code not found in R1
CMP R2,#0
BLE |Create_exit| ; if '2' specified, R2 must be supplied
LDR R1,heap_signature ; -> String: "«Hz»"
STR R1,[R0,#0]
STR R2,[R0,#4]
ADD R1,R0,#&10 ; offset to start of heap slots
ADD R1,R1,R2,LSL #4 ; plus R2 4-byte words makes
; total size of heap base
STR R1,[R0,#8]
STR R1,[R0,#&00C] ; =12
ADD R0,R0,#&10 ; R0+=16
MOV R1,#0
|initheap_loop|
CMP R2,#0 ; loop down to 0
BEQ |initheap_jumpout|
STR R1,[R0,#0]
STR R1,[R0,#4]
STR R1,[R0,#8]
STR R1,[R0,#&00C] ; =12
ADD R0,R0,#&10 ; =16
SUB R2,R2,#1
B |initheap_loop| ; Ends
|initheap_jumpout|
LDR R1,block_signature ; -> String: "Blck"
STR R1,[R0,#0]
MOV PC,R14 ; Function exit, Ends
; base+0 = heap signature word
; base+4 = max number of blocks
; base+8 = start of blocks in heap
; base+12 = end of blocks in heap
 
; R2 blocks of 4 words
; slot+0 = pointer to start of block
; slot+4 = pointer to anchor word
; slot+8 = block size
; slot+12 = pointer to block name string
 
; base+12+ R2*16 = block signature
 
|SlidingHeap_NewBlock|
; on entry R0 holds base address of sliding heap
; R1 holds address of anchor word (previously created)
; R2 holds size of block (rounded up to nearest word)
; Must check that there is enough space & increase Wimpslot if necessary
; *before* calling SlidingHeap_NewBlock!
; R3 points to name of block ( should be R1+4)
 
; on exit all registers preserved
 
STMFD R13!,{R0-R7,R14}
ADD R4,R0,#&10 ; start of heap slots
LDR R5,[R0,#4] ; R5 = number of slots in heap
|freeslot_loop|
LDR R6,[R4,#0]
CMP R6,#0 ; check for empty slot
BEQ |newblock|
ADD R4,R4,#&10 ; =16
SUBS R5,R5,#1
BNE |freeslot_loop|
ADR R0,|nonefree| ; -> Error Block Word: &00C02800
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
; SlidingHeap_NewBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
 
|nonefree|
DCD &00C02800 ; Error Block Word r/- (referenced)
DCB "No more free slots in heap",0 ; Error Block String -/-
ALIGN
 
|newblock|
STR R1,[R4,#4] ; store anchor address at slot+4
ADD R2,R2,#3
BIC R2,R2,#2_11 ; round requested block size up
; to nearest word
STR R2,[R4,#8] ; store size at slot+8
MOV R5,R0 ; shuffle registers to call SWI
MOV R6,R1 ;
MOV R0,R3 ;
MOV R1,R3 ;
SWI XOS_ValidateAddress
LDMVSFD R13!,{R0-R7,PC} ; Function exit on error
MOVCS R3,#0 ; carry set if bad address
MOV R1,R6 ; restore registers
MOV R0,R5
CMP R3,#0
ADREQ R3,unknown_block ; -> String: "Unknown block",0
STR R3,[R4,#&00C] ; store pointer to block name at
; slot+12
LDR R5,[R0,#&00C] ; pointer to first word after end
; of heap (base+12)
ADD R5,R5,#4 ; allow for block signature
STR R5,[R4,#0] ; store new block start at slot+0
STR R5,[R1,#0] ; and back into anchor address
ADD R5,R5,R2
STR R5,[R0,#&00C] ; store new heap end in base+12
LDR R4,block_signature ; -> String: "Blck"
STR R4,[R5,#0] ;mark end of block so we can
;check for heap corruption later
 
; SlidingHeap_NewBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
unknown_block
DCB "Unknown block",0 ; String r/- (referenced)
ALIGN
 
|SlidingHeap_ScrapBlock|
; on entry R0 points to heap base
; R1 points to address of anchor word
 
; on exit all registers preserved
 
; Wimpslot must be shrunk manually after this call if heap has contracted
; enough to allow it
STMFD R13!,{R0-R7,R14}
ADD R2,R0,#&10 ; base+16
LDR R3,[R0,#4] ; number of slots
|scrap_loop|
LDR R4,[R2,#4] ;get anchor for slot
CMP R4,R1 ;is it this one?
BEQ |scrapblock|
ADD R2,R2,#&10 ;next slot
SUBS R3,R3,#1
BGT |scrap_loop|
ADR R0,|noanchor| ; -> Error Block Word: &00C02807
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
; SlidingHeap_ScrapBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|noanchor|
DCD &00C02807 ; Error Block Word r/- (referenced)
DCB "Couldn\'t find anchor in heap (ScrapBlock)",0 ; Error Block String -/-
ALIGN
 
|scrapblock|
MOV R4,#0
STR R4,[R1,#0] ;zero anchor word
LDR R7,[R0,#&00C] ;get start of blocks from base+12
LDR R5,[R2,#0] ;get start of this block
SUB R7,R7,R5 ;offset
LDR R6,[R2,#8] ;get block size
SUB R7,R7,R6 ;offset to start of following data
ADD R7,R7,#4 ;total amount to slide by
LDR R6,[R2,#8] ;get block size
ADD R6,R6,R5 ;size + start = end
SUB R5,R5,#4
STMFD R13!,{R0-R3}
MOV R1,R6
MOV R2,R5
MOV R3,R7
BL |shiftup_blockdata| ;move stuff up from after block
LDMFD R13!,{R0-R3} ;restore corrupted registers
LDR R1,[R0,#4] ;number of blocks at base+4
LDR R7,[R2,#8] ;block size (again!)
ADD R7,R7,#4 ;including block sig
MOV R5,#0
STR R5,[R2,#0] ;zero block start
STR R5,[R2,#4] ;and anchor pointer
STR R5,[R2,#8] ;and block size...
STR R5,[R2,#&00C] ;and name string....
ADD R2,R0,#&10 ;point R2 to first slot in heap
|scrap_adjustotherslots|
LDR R5,[R2,#0] ;start of block
CMP R5,#0
BEQ |scrap_slotisblank|
CMP R5,R6 ;has this block just slid?
SUBGE R5,R5,R7 ;then adjust address by amount we slid by
STR R5,[R2,#0] ;and store back
LDR R4,[R2,#4] ;address of anchor word
STR R5,[R4,#0] ;update also with new block start
|scrap_slotisblank|
ADD R2,R2,#&10 ;next slot
SUBS R1,R1,#1 ;decrement block count
BNE |scrap_adjustotherslots|
LDR R5,[R0,#&00C] ; =12
SUB R5,R5,R7
STR R5,[R0,#&00C] ; =12
; SlidingHeap_ScrapBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
|SlidingHeap_ExtendBlock| ; SlidingHeap_ExtendBlock
; on entry R0 points to heap base
; R1 points to anchor word
; R2 points to desired new block size
; Wimpslot must have been manually extended before calling this SWI
; if not enough space for heap to grow
; and must be manually shrunk afterwards if heap has shrunk enough to allow it
 
; on exit all registers preserved
STMFD R13!,{R0-R7,R14}
ADD R3,R0,#&10 ;point to 1st slot in heap
LDR R4,[R0,#4] ;max no of blocks
|extend_loop|
LDR R5,[R3,#4] ;anchor word for this slot
CMP R5,R1 ;is it right one?
BEQ |extendblock|
ADD R3,R3,#&10 ; =16
SUBS R4,R4,#1
BGT |extend_loop| ; -> Error Block Word: &00C02808
ADR R0,|extend_notfound|
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
; SlidingHeap_ExtendBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|extend_notfound|
DCD &00C02808 ; Error Block Word r/- (referenced)
DCB "Couldn\'t find anchor in heap (ExtendBlock)",0 ; Error Block String -/-
ALIGN
 
|extendblock|
ADD R2,R2,#3 ;round new block size up
BIC R2,R2,#2_11 ;to nearest word
LDR R4,[R3,#0] ;start of block
LDR R5,[R3,#8] ;block size
ADD R4,R4,R5
ADD R4,R4,#4 ;end of block+sig
SUB R7,R2,R5 ;subtract from new block size
;offset now in R7
ADD R5,R7,R4 ;adjust end of block address by this offset
LDR R6,[R0,#&00C] ;end of heap blocks
SUB R6,R6,R4 ;distance to old block end
STMFD R13!,{R0-R3}
MOV R0,R4
MOV R1,R5
MOV R2,R6
BL |shiftblock|
LDMFD R13!,{R0-R3}
MOV R6,R7 ;restore offset
STR R2,[R3,#8] ;store new block size
LDR R1,[R0,#&00C] ;get end of heap blocks
ADD R1,R1,R6 ;plus offset
STR R1,[R0,#&00C] ;store new end at base+12
LDR R1,[R3,#0] ;get start of block
ADD R1,R1,R2 ;point to end of new block
LDR R7,block_signature ; -> String "Blck"
STR R7,[R1,#0] ;poke in block sig to mark end
ADD R2,R0,#&10 ;start of slots
LDR R1,[R3,#0] ;get start of block
LDR R0,[R0,#4] ;get number of slots
|extend_updateslot|
CMP R0,#0
BEQ extendblock_finished ;check for last slot
LDR R3,[R2,#0] ;start of block
CMP R3,R1 ;is it this block?
ADDGT R3,R3,R6 ;if so, apply offset
STRGT R3,[R2,#0]
LDRGT R7,[R2,#4] ;update anchor word
STRGT R3,[R7,#0]
ADD R2,R2,#&10 ;next slot
SUB R0,R0,#1
B |extend_updateslot| ; Ends
 
extendblock_finished
; SlidingHeap_ExtendBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
|SlidingHeap_HeapInfo|
; On entry R0 points to heap base
; on exit all registers preserved
STMFD R13!,{R0-R7,R14}
MOV R7,R0 ;preserve heap base address
SWI XOS_WriteS
DCB "\r\nHeap information requested\r\n\r\nGenerated by SlidingHeap 2.11, © Steven Haslam 1992 (16 Dec 2002)\r\n\r\nHeap base : &",0 ; Inline string -/-
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if error
MOV R1,R12 ; get private word in R1
MOV R2,#&0100 ; buffer size =256
SWI XOS_ConvertHex8
SWIVC XOS_Write0 ;print address of heap base
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
SWI XOS_WriteS
DCB "\r\nSlots available in heap : ",0
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
LDR R0,[R7,#4] ;get number of slots
MOV R1,R12 ;workspace again
MOV R2,#&0100 ; =256
SWI XOS_ConvertCardinal4 ;print number of slots
SWIVC XOS_Write0
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
SWI XOS_WriteS
DCB "\r\nSlots used : ",0 ; Inline string -/-
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
ADD R1,R7,#&10 ;first slot
LDR R3,[R7,#4] ;number of slots
MOV R0,#0 ;start count
|info_slotcount|
LDR R2,[R1,#0] ;start of block
CMP R2,#0 ;is it blank?
ADDNE R0,R0,#1 ; if not, increment count
ADD R1,R1,#&10 ;next slot
SUBS R3,R3,#1
BNE |info_slotcount|
MOV R6,R0 ;number of used slots in R6
MOV R1,R12 ;workspace
MOV R2,#&0100 ; =256
SWI XOS_ConvertCardinal4
SWIVC XOS_Write0 ;print no. of slots used
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
SWI XOS_WriteS
DCB "\r\nTop of heap : &",0
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
LDR R0,[R7,#&00C] ;end of heap blocks
SWI XOS_ConvertHex8
SWIVC XOS_Write0 ;print highest address in heap
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
SWI XOS_WriteS
DCB "\r\n\r\n",0
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
CMP R6,#0 ;number of used slots
BEQ heapinfo_finished
SWI XOS_WriteS
DCB "Blocks: (not necessarily in the order as in the heap)\r\n\r\n| Address | Length | Name\r\n",0 ; Inline string -/-
ALIGN
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
ADD R6,R7,#&10 ;start of slots
LDR R4,[R7,#4] ;number of slots
|info_slotinfo|
LDR R5,[R6,#0] ;address of block
CMP R5,#0
BEQ |info_nextslot|
SWI XOS_WriteI+"|"
SWIVC XOS_WriteI+" "
SWIVC XOS_WriteI+"&"
MOVVC R0,R5
MOVVC R1,R12
MOVVC R2,#&0100 ; =256
SWIVC XOS_ConvertHex8
SWIVC XOS_Write0
SWIVC XOS_WriteI+" "
SWIVC XOS_WriteI+"|"
SWIVC XOS_WriteI+" "
LDRVC R0,[R6,#8] ;size of block
SWIVC XOS_ConvertFixedFileSize
SWIVC XOS_Write0
SWIVC XOS_WriteI+" "
SWIVC XOS_WriteI+"|"
SWIVC XOS_WriteI+" "
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
LDR R1,[R6,#&00C] ;pointer to block name
|info_blockname|
LDRB R0,[R1],#1
CMP R0,#&20 ;if control character...
BLT return ;print return & exit
SWI XOS_WriteC ;print name of block
LDMVSFD R13!,{R0-R7,PC} ; Function exit if error
B |info_blockname|
return
SWI XOS_WriteI+13
SWIVC XOS_WriteI+10
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
|info_nextslot|
ADD R6,R6,#&10 ; =16
SUBS R4,R4,#1
BNE |info_slotinfo|
heapinfo_finished
; SlidingHeap_HeapInfo exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
|SlidingHeap_VerifyHeap|
; On entry, R0 points to heap base
; on exit, all registers preserved
STMFD R13!,{R0-R7,R14}
ADD R1,R0,#&10 ;first slot
SWI XOS_ValidateAddress ;check base is at valid address
LDMVSFD R13!,{R0-R7,PC} ; Function exit if error
BCS |heapinvalid|
LDR R1,[R0,#&00C] ;check end of heap blocks
ADD R1,R1,#4
SWI XOS_ValidateAddress
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
BCS |heapinvalid|
LDR R1,[R0,#0]
LDR R2,heap_signature ; -> String: "«Hz»"
CMP R1,R2 ; check heap ID using special signature
BNE |heap_nosig|
LDR R1,[R0,#8] ;check start of heap blocks
LDR R1,[R1,#0]
LDR R2,block_signature ; -> String: "Blck"
;check for string at end of heap base
CMP R1,R2
BNE |heap_nostart|
LDR R1,[R0,#4] ;max number of slots
ADD R0,R0,#&10 ;first slot
|checkslots|
LDR R3,[R0,#0] ;start of block
CMP R3,#0 ;is it in use?
BEQ |checkforlastslot| ;if last then exit
LDR R4,[R0,#8] ;block size
ADD R3,R3,R4 ;end of block
LDR R3,[R3,#0] ;last word of block
LDR R2,block_signature ; -> String "Blck"
CMP R2,R3
BEQ |goodblocksig| ;else block bad
LDR R0,[R0,#&00C] ;block name
MOV R1,R12
ADD R1,R1,#4 ;workspace+4
MOV R2,#short_workspace ;length 256-4
ADR R3,|overflowtemplate| ;get length of template
LDR R4,[R3],#4 ;and increment R3
;to point to actual string
SWI XOS_SubstituteArgs ;substitute in block name
LDMVSFD R13!,{R0-R7,PC} ; Function exit if VS
MOV R3,#0
SUB R2,R2,#1
STRB R3,[R1,R2] ;zero-terminate result string
LDR R0,|overflow_err| ;get error number
STR R0,[R12,#0] ;and put into 1st word of workspace
MOV R0,R12 ;R0 points to home-made error block
ADD R13,R13,#4 ;skip first stack entry (old R0)
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|goodblocksig|
;R0 points to slot
LDR R2,[R0,#4] ;anchor
LDR R2,[R2,#0] ;anchor contents (start of block)
LDR R3,[R0,#0] ;start of block (from slot data)
CMP R2,R3
BEQ |checkforlastslot| ;All OK, exit back to loop
;otherwise report error
make_badanchor_errblock
LDR R0,[R0,#&00C] ;block name
MOV R1,R12
ADD R1,R1,#4 ;workspace+4
MOV R2,#short_workspace ;length of remaining buffer
ADR R3,|badanchortemplate| ;get length of template string
LDR R4,[R3],#4 ;and increment R3
;to point to actual string
SWI XOS_SubstituteArgs
LDMVSFD R13!,{R0-R7,PC} ; Function exit if error
MOV R3,#0
SUB R2,R2,#1 ;length of result string -1
STRB R3,[R1,R2] ;zero-terminate string
LDR R0,|badanchor_err| ;get error number
STR R0,[R12,#0] ;store in 1st word of workspace
MOV R0,R12 ;R0 now points to error block
ADD R13,R13,#4 ;skip first stack entry (old R0)
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
; error exit
; Normal exit is via 'checkforlastslot'
 
 
|checkforlastslot|
;R0 points to current slot
;R1 holds slot counter
ADD R0,R0,#&10 ; =16
SUBS R1,R1,#1
BGT |checkslots| ;continue with check loop
; SlidingHeap_VerifyHeap exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
|SlidingHeap_NextFree|
; On entry, R0 points to base of heap
; on exit, R0 points to first word after end of heap
LDR R0,[R0,#&00C] ;end of current heap blocks
ADD R0,R0,#4 ;next word
MOV PC,R14 ; Function exit, Ends
 
|SlidingHeap_DescribeBlock|
; On entry, R0 points to base of heap
; R1 points to anchor word
; on exit, R0 points to start of block
; R1 points to anchor word
; R2 holds block size
; R3 points to block name string
STMFD R13!,{R0-R7,R14}
ADD R2,R0,#&10 ;start of slots
LDR R3,[R0,#4] ;number of slots
|describe_slotloop|
CMP R3,#0 ;all slots checked?
BEQ |describe_noanchor|
LDR R4,[R2,#4] ;pointer to anchor word
CMP R4,#0 ;slot unused?
BEQ |describe_slotunused|
CMP R4,R1
BEQ |describe_slotfound|
|describe_slotunused|
SUB R3,R3,#1 ;decrement slot counter
ADD R2,R2,#&10 ;next slot
B |describe_slotloop| ; Ends
|describe_noanchor|
ADR R0,|describe_noanchor_err| ; -> Error Block Word: &00C0280B
; SlidingHeap_DescribeBlock exit
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|describe_noanchor_err|
DCD &00C0280B ; Error Block Word r/- (referenced)
DCB "Couldn\'t find anchor in heap (DescribeBlock)",0 ; Error Block String -/-
ALIGN
 
|describe_slotfound|
MOV R0,R2 ;pointer to start of slot
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
LDMIA R0,{R0-R3} ;load slot data in R0-R3
; SlidingHeap_DescribeBlock exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
MOVNES PC,R14 ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
MOV PC,R14 ; 32-bit exit, caller flags corrupted
 
|SlidingHeap_ShiftHeap|
; On entry, R0 points to base of heap
; R1 points to new address for base of heap
; on exit, all registers preserved
STMFD R13!,{R0-R7,R14}
MOV R7,R1 ;destination address
MOV R6,R0 ;start of heap base
BL |SlidingHeap_NextFree|
;R0 points to first word after end of heap
RSB R2,R6,R0 ;total size of heap, base plus blocks
MOV R0,R6 ;restore parameters
MOV R1,R7
BL |shiftblock| ;shift whole heap
SUB R5,R7,R6 ;get offset (+/-) in R5
ADD R0,R7,#&10 ;new start of slots
LDR R1,[R7,#4] ;number of slots
|shift_updateslots|
LDR R2,[R0,#0] ;start of block
CMP R2,#0
ADDNE R2,R2,R5 ;...if not empty...
STRNE R2,[R0,#0] ;update start by offset amount
LDRNE R3,[R0,#4] ;get anchor
STRNE R2,[R3,#0] ;update anchor too
ADD R0,R0,#&10 ;next slot
SUBS R1,R1,#1
BNE |shift_updateslots|
LDR R0,[R7,#8] ;start of blocks in heap
ADD R0,R0,R5
STR R0,[R7,#8] ;update start of blocks by offset
LDR R0,[R7,#&00C]
ADD R0,R0,R5
STR R0,[R7,#&00C]
; SlidingHeap_ShiftHeap exit
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
LDMNEFD R13!,{R0-R7,PC}^ ; 26-bit exit - return, restoring flags
MSRVS CPSR_f,#0 ; forcibly clear flags, if V set
LDMFD R13!,{R0-R7,PC} ; 32-bit exit, caller flags corrupted
 
|Create_exit|
; SlidingHeap_Create exit
ADR R0,|create_err| ; -> Error Block Word: &00C02802
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|create_err|
DCD &00C02802 ; Error Block Word r/- (referenced)
DCB "You must have at least one block in the heap!",0 ; Error Block String -/-
ALIGN
 
|heapinvalid|
; SlidingHeap_VerifyHeap exit
ADR R0,|heapinvalid_err| ; -> Error Block Word: &00C0280A
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|heapinvalid_err|
DCD &00C0280A ; Error Block Word r/- (referenced)
DCB "Heap is not in valid memory",0 ; Error Block String -/-
ALIGN
 
|heap_nosig|
; SlidingHeap_VerifyHeap exit
ADR R0,|heap_nosigerr| ; -> Error Block Word: &00C02803
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|heap_nosigerr|
DCD &00C02803 ; Error Block Word r/- (referenced)
DCB "Heap ID corrupted (Bad signature)",0 ; Error Block String -/-
ALIGN
 
|heap_nostart|
; SlidingHeap_VerifyHeap exit
ADR R0,|heap_nostart_err| ; -> Error Block Word: &00C02804
ADD R13,R13,#4 ; R0 is first item on stack - skip
LDMFD R13!,{R1-R7,R14}
TEQ PC,PC ; check whether in 26-bit or 32-bit mode
ORRNES PC,R14,#V_flag ; 26-bit mode - set V flag and return
MSRVC CPSR_f,#V_flag ; 32-bit mode - ensure that V flag is set...
MOV PC,R14 ; ...and return
 
|heap_nostart_err|
DCD &00C02804 ; Error Block Word r/- (referenced)
DCB "Start of heap corrupted (Bad signature)",0 ; Error Block String -/-
ALIGN
 
|overflowtemplate|
DCD &24 ;length of template string
DCB "Block overflow in Sliding Heap (%*0)"
;length is given in first word so no terminator needed
|overflow_err|
DCD &00C02801 ;error number
 
|badanchortemplate|
DCD &24
DCB "Anchor does not point to block (%*0)"
|badanchor_err|
DCD &00C02806
 
heap_signature
DCB "«Hz»"
block_signature
DCB "Blck"
 
|command2| ; *VerifyHeap
STR R14,[R13,#-4]! ;store R14 on descending stack
LDR R12,[R12,#0] ;get workspace
MOV R1,R0 ;command tail string
MOV R0,#&10 ; expects base 16
SWI XOS_ReadUnsigned
MOVVC R0,R2 ;R2 holds heap base (we hope)
BLVC |SlidingHeap_VerifyHeap|
ADRVC R0,heap_ok
SWIVC XOS_Write0 ;output OK message
LDR PC,[R13],#4 ; exit, returning error status in V flag
 
heap_ok
DCB "Heap checked out OK\r\n",0
ALIGN
 
|help2|
DCB "*VerifyHeap will check the integrity of the given heap.\r\r"
|syntax2|
DCB "Syntax: *VerifyHeap <address>",0 ; String array r/- (referenced)
ALIGN
 
|command1| ; *HeapInfo
STR R14,[R13,#-4]! ;store R14 on descending stack
LDR R12,[R12,#0] ;get workspace
MOV R1,R0 ;command tail string
MOV R0,#&10 ; expects base 16
SWI XOS_ReadUnsigned
MOVVC R0,R2 ;R2 holds heap base (we hope)
BLVC |SlidingHeap_HeapInfo| ; SlidingHeap_HeapInfo
LDR PC,[R13],#4 ; exit, returning error status in V flag
 
|help1|
DCB "*HeapInfo will display information on the given sliding heap.\r\r"
|syntax1|
DCB "Syntax: *HeapInfo <address>",0 ; String array r/- (referenced)
 
|help3|
DCB "SlidingHeap is a memory manager that works by using `anchor points` into an area of memory; it is rather like Acorn C\'s `flex` library, however it is suitable for use in BASIC/ARM code programs. There is a set of BASIC procedures to interface with the sliding heap manager, which will also automatically increase and decrease the size of a WIMP task\'s memory area as required.\r" ; String -/- (referenced)
DCB "\r"
DCB "For more information, contact Steven Haslam at one of the following addresses:\r"
DCB "\r"
DCB "E-Mail:\r"
DCB "\xA0","FidoNet: 2:250/116.3, 2:254/27.0, 2:252/102.0, 2:254/405.0\r"
DCB "\r"
DCB "Snail-Mail:\r"
DCB "\r"
DCB "Steven Haslam\r"
DCB "\xA0","112 Keighley Road\r"
DCB "\xA0\xA0","Colne\r"
DCB "\xA0\xA0\xA0","Lancashire\r"
DCB "\xA0\xA0\xA0\xA0","BB8 0PH",0
ALIGN
 
|shiftup_blockdata|
; On entry, R0 points to heap base
; R1 points to end of block
; R2 points to start of block
; R3 = amount to slide heap up by
 
; On exit, R0-R3 corrupted
 
STR R14,[R13,#-4]! ;R14 on mini-stack
; TST R2,#3
; BNE |startnotaligned| ;not word-aligned
;|nonaligned_jumpback|
; TST R1,#3
; BNE |endnotaligned| ;not word-aligned
SUBS R3,R3,#&10
BLT |shift_8| ;less than 16 bytes to move
SUBS R3,R3,#&10
BLT |shift_16| ;less than 32 bytes to move
STMFD R13!,{R4-R9} ;we are about to corrupt these
|shift_32|
LDMIA R1!,{R0,R4-R9,R14} ;load stuff from after end
STMIA R2!,{R0,R4-R9,R14} ;and write from start
SUBS R3,R3,#&20 ; five registers' worth of data
BGE |shift_32|
CMN R3,#&20 ;check block size against -32
LDMEQFD R13!,{R4-R9,PC} ; Function exit if EQ
LDMFD R13!,{R4-R9} ;restore registers
|shift_16|
ADDS R3,R3,#&10
BLT |shift_8|
STMFD R13!,{R4,R5} ;preserve R4, R5
LDMIA R1!,{R0,R4,R5,R14} ;shift another 16 bytes
STMIA R2!,{R0,R4,R5,R14}
LDMEQFD R13!,{R4,R5,PC} ; Function exit if EQ
LDMFD R13!,{R4,R5}
SUB R3,R3,#&10 ; =16
|shift_8|
ADDS R3,R3,#8
BLT |shift_4|
LDMIA R1!,{R0,R14} ;shift another 8 bytes
STMIA R2!,{R0,R14}
LDREQ PC,[R13],#4 ; Function exit if EQ
SUB R3,R3,#8
|shift_4|
ADDS R3,R3,#4
BLT |lastword|
LDR R0,[R1],#4 ;just one register's worth now
STR R0,[R2],#4
LDREQ PC,[R13],#4 ; Function exit if EQ
SUB R3,R3,#4
|lastword|
ADDS R3,R3,#4
LDREQ PC,[R13],#4 ; Function exit if EQ
LDR R0,[R1,#0] ;grab last word from block end itself
|shift_byte|
STRB R0,[R2],#1
MOV R0,R0,LSR #8
SUBS R3,R3,#1
BGT |shift_byte|
LDR PC,[R13],#4 ; Function exit, Ends
;-------------------------------------------------------------------------------
 
;|startnotaligned|
; LDRB R0,[R1],#1
; STRB R0,[R2],#1
; SUBS R3,R3,#1
; LDREQ PC,[R13],#4 ; Function exit if EQ
; TST R2,#3 ;have we reached word boundary yet?
; BNE |startnotaligned|
; B |nonaligned_jumpback| ; note that R1 will now be non-aligned!
;;-------------------------------------------------------------------------------
;
;|endnotaligned|
; STMFD R13!,{R11,R12}
; AND R12,R1,#3 ;get bottom two bits in R12
; BIC R1,R1,#3 ;clear bottom bits
; MOV R12,R12,LSL #3 ;times 8
; RSB R11,R12,#&20 ;32 - R12
; ;R11 holds no. of bits to shift right by
; ;R12 holds no. of bits to shift left by
; LDR R0,[R1],#4 ;get full word from end of block
; MOV R0,R0,LSR R12 ;shift by no of significant bits
; ;to get non-aligned data
; SUBS R3,R3,#&10 ; =16
; BLT |lessthan8|
; SUBS R3,R3,#&10 ; =16
; BLT |lessthan16|
; STMFD R13!,{R4-R10} ;stack registers we're about to corrupt
;|atleast32|
; LDMIA R1!,{R4-R10,R14} ;load 8 registers from address in R1
; ;(32 bytes)
; ORR R0,R0,R4,LSL R11
; MOV R4,R4,LSR R12
; ORR R4,R4,R5,LSL R11
; MOV R5,R5,LSR R12 ;transfer data along through R0
; ;between registers in the block
; ORR R5,R5,R6,LSL R11 ;masking left and right as appropriate
; MOV R6,R6,LSR R12
; ORR R6,R6,R7,LSL R11
; MOV R7,R7,LSR R12
; ORR R7,R7,R8,LSL R11
; MOV R8,R8,LSR R12
; ORR R8,R8,R9,LSL R11
; MOV R9,R9,LSR R12
; ORR R9,R9,R10,LSL R11
; MOV R10,R10,LSR R12
; ORR R10,R10,R14,LSL R11
; STMIA R2!,{R0,R4-R10} ;then store to destination address R2
; MOV R0,R14,LSR R12
; SUBS R3,R3,#&20 ; =" " (32)
; BGE |atleast32|
; CMN R3,#&20 ;check for all data transferred
; ;in last loop
; LDMEQFD R13!,{R4-R12,PC} ; Function exit if EQ
; LDMFD R13!,{R4-R10}
;|lessthan16|
; ADDS R3,R3,#&10 ; =16
; BLT |lessthan8| ;we're about to corrupt these
; STMFD R13!,{R4-R6} ;load 4 registers, 16 bytes
; LDMIA R1!,{R4-R6,R14}
; ORR R0,R0,R4,LSL R11
; MOV R4,R4,LSR R12
; ORR R4,R4,R5,LSL R11
; MOV R5,R5,LSR R12
; ORR R5,R5,R6,LSL R11 ;more transfers to get it word-aligned
; MOV R6,R6,LSR R12
; ORR R6,R6,R14,LSL R11
; STMIA R2!,{R0,R4-R6} ;save at R2
; LDMEQFD R13!,{R4-R6,R11,R12,PC} ; Function exit if EQ
; LDMFD R13!,{R4-R6}
; SUB R3,R3,#&10 ; =16
; MOV R0,R14,LSR R12
;|lessthan8|
; ADDS R3,R3,#8
; BLT |lessthan4|
; STR R4,[R13,#-4]! ;stack R4
; LDMIA R1!,{R4,R14}
; ORR R0,R0,R4,LSL R11 ;shift data along via another
; MOV R4,R4,LSR R12 ;couple of registers
; ORR R4,R4,R14,LSL R11
; STMIA R2!,{R0,R4}
; LDMEQFD R13!,{R4,R11,R12,PC} ; Function exit if EQ
; LDR R4,[R13],#4
; SUB R3,R3,#8
; MOV R0,R14,LSR R12
;|lessthan4|
; ADDS R3,R3,#4
; BLT |grabend|
; LDR R14,[R1],#4
; ORR R0,R0,R14,LSL R11 ;grab 1 word and shift it
; STR R0,[R2],#4
; LDMEQFD R13!,{R11,R12,PC} ; Function exit if EQ
; SUB R3,R3,#4
; MOV R0,R14,LSR R12
;|grabend|
; ADDS R3,R3,#4
; LDMEQFD R13!,{R11,R12,PC} ; Function exit if EQ
; LDR R14,[R1,#0] ;load from end of block itself
; ORR R0,R0,R14,LSL R11
;|lastbytes|
; STRB R0,[R2],#1
; MOV R0,R0,LSR #8
; SUBS R3,R3,#1
; BGT |lastbytes|
; LDMFD R13!,{R11,R12,PC} ; Function exit, Ends
;-------------------------------------------------------------------------------
 
|shiftblock|
; on entry, R0 holds old end of block
; R1 holds new end of block
; R2 holds distance between R1 and end of heap
STMFD R13!,{R0-R4,R14} ; Function entry
CMP R0,R1
BLT |shift_fromend|
|shift_fromstart|
LDR R3,[R0],#4 ;copy from start of old block
STR R3,[R1],#4 ;...to start of new
SUBS R2,R2,#4
BPL |shift_fromstart|
LDMFD R13!,{R0-R4,PC} ; Function exit, Ends
 
|shift_fromend|
LDR R3,[R0,R2] ;copy from end of old block
STR R3,[R1,R2] ;...to end of new
SUBS R2,R2,#4
BPL |shift_fromend|
LDMFD R13!,{R0-R4,PC} ; Function exit, Ends
 
END
 
/tags/v2_12_1/Original/ObjAsm/Makefile,fe1
New file
0,0 → 1,27
# Project: SlidingHeap
 
 
# Toolflags:
CCflags = -c -depend !Depend -IC: -throwback
C++flags = -c -depend !Depend -IC: -throwback
Linkflags = -rmf -v -first SlidingHp -o $@
ObjAsmflags = -throwback -NoCache -depend !Depend -APCS 3/32bit
CMHGflags =
LibFileflags = -c -o $@
Squeezeflags = -o $@
 
 
# Final targets:
@.SlidingHp: @.o.SlidingHp
Link $(Linkflags) @.o.SlidingHp
 
 
# User-editable dependencies:
 
# Static dependencies:
@.o.SlidingHp: @.s.SlidingHp
ObjAsm $(ObjAsmflags) -o @.o.SlidingHp @.s.SlidingHp
 
 
# Dynamic dependencies:
o.SlidingHp: s.SlidingHp
/tags/v2_12_1/Original/ReadMe
New file
0,0 → 1,34
The Sliding Heap module is © Steven Haslam 1992 and is distributed under the GNU Public Licence. You will need the procedures in the SHeap BASIC library, or similar, to use it.
 
It creates and manages a sliding heap of blocks of memory, claimed from a program's Wimpslot as necessary, thus avoiding the fragmentation caused by repeatedly claiming and releasing memory from the RMA.
The module works under RISC OS 2 and RISC OS 3·1, and is compatible with RISC OS 3·5 and greater, and StrongARM, although dynamic areas can be used to perform the same task on such systems.
 
This new release of SlidingHeap (version 2.xx) has been reconstructed from a disassembly, in the absence of the original source code. The module should work in 32-bit ARM modes, and therefore has been flagged as compatible with RISC OS 5. For further information contact chrisbazley@bigfoot.com.
 
1st December 2002
 
Changes to the accompanying BASIC library
-----------------------------------------
 A new function has been added to the BASIC library - FNsliding_block_size(anchor%), which returns the current size of the specified block.
 Two new procedures have been added - PROCverify_heap, which enables the programmer to force a explicit check for corruption of the sliding heap at any point in his code, and PROCincreaseslots, which allows the programmer to increase the number of available slots in the heap, or to read its current setting.
 PROCheapsinfo now takes a parameter - PROCheapsinfo(address%), where address% points to a buffer of length 256 bytes. As a consequence, the library no longer relies on the (undocumented) existence of a block with a certain given name!
 Variables have been made LOCAL wherever possible, and global variables use the prefix 'sh_', e.g. 'sh_heap_trigger%'.
 PROCdestroyheaps now ensures that all anchors in use are reset to zero before the heap is destroyed, making it 'safe' to reuse them after a subsequent PROCinitheaps.
 
Module history
--------------
Version 2.01
 Most SWIs no longer corrupt R0.
 SWIs now *do* preserve flags in 26-bit mode (although not in new 32-bit mode) - which they never did before!
 A few optimisations, i.e. SUBS R1,R1,#1:BNE in place of SUB R1,R1,#1:CMP R1,#0:BNE
 
Version 2.10 (18 Nov 2002)
 Numbers of heap slots available/used are now reported via OS_ConvertCardinal (e.g. "2048") rather than OS_ConvertSpacedCardinal (e.g. "2 048"), as the leading digit proved too easily overlooked.
 New SWI added - SlidingHeap_IncreaseSlots. This allows programs to use a indeterminate number of blocks, without having to set an upper limit at the time of initialisation.
 
Version 2.11 (16 Dec 2002)
 A few more SUBS optimisations.
 
Version 2.12 (13 Oct 2003)
 SlidingHeap_ExtendBlock now rounds requested block sizes *up* to the nearest word, just as SlidingHeap_NewBlock always has.... Optimised this to use single BIC in place of AND NOT construction.
 Removed a large chunk of dead code from SlidingHeap_ScrapBlock (as far as I know, never called) dealing with the possibility of non-word-aligned blocks. As the SlidingHeap_ExtendBlock bug demonstrated, the SlidingHeap module cannot in any case cope gracefully with non-word-aligned blocks if they are accidentally created - and they should now never happen. They were never designed to happen in the first place!
/tags/v2_12_1/SysVars/SlidingHp=24Dir
New file
0,0 → 1,0
<Packages$@Apps.Library.!SlidingHp>