; ; lit.s ; ; Literal pool management ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's BASIC Assembler Supplement. ; ; BAS 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, or (at your option) ; any later version. ; ; BAS 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 BAS. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sh.aofGen GET sh.bas GET sh.fastMove GET sh.flex GET sh.insert GET sh.workspace ;----- Main code ------------------------------------------------------------ AREA |BAS$$Code|,CODE,READONLY ; --- lit_add --- ; ; On entry: R0 == address of literal data ; R1 == size of literal data ; R2 == word align flag ; ; On exit: R0 set up as described below. ; ; Use: Adds the given data to the current literal pool. On the ; first pass, it returns the value of P% in R0. On the ; second pass, it returns the address of the literal item. EXPORT lit_add lit_add ROUT STMFD R13!,{R1-R5,R12,R14} ;Save some registers STR R12,[R7,#:INDEX:be__line] ;Store line value MOV R12,R7 ;Find my workspace MOV R3,R0 ;Keep the start address MOV R4,R1 ;And the size of the block BL aof_firstPass ;Is this the first pass? BCS %50lit_add ;Yes -- behave totally oddly ; --- Handle word aligning --- CMP R2,#0 ;Is the word align flag on? BEQ %10lit_add ;No -- don't bother then LDR R1,lit__contents+4 ;Load the current size ANDS R1,R1,#3 ;Get the nonwordalignedness BEQ %10lit_add ;No excess -- skip on then RSB R1,R1,#4 ;Find how much we have to add ADR R0,lit__contents ;Point to the contents block BL aof_ensure ;Get the memory area MOV R14,#0 ;A nice zero byte 05lit_add STRB R14,[R0],#1 ;Store it in the block SUBS R1,R1,#1 ;Decrement the counter BGT %05lit_add ;And carry on round ; --- Now add the contents --- 10lit_add LDR R5,lit__contents+4 ;Load offset of literal item ADR R0,lit__contents ;Point to the contents block MOV R1,R4 ;Get the block size BL aof_ensure ;Make sure it's big enough MOV R1,R3 ;Point to caller's block MOV R2,R4 ;Get the size BL fastMove ;Copy it over PDQ ; --- Now return the correct address --- LDR R14,lit__next ;Find next literal index LDR R0,lit__table ;Find the literal table LDR R0,[R0,R14] ;Load the pool base address ADD R0,R0,R5 ;And add the item offset LDMFD R13!,{R1-R5,R12,PC}^ ;And return to caller ; --- Handle a literal pool request on first pass --- 50lit_add LDR R3,lit__contents+4 ;Load the current size CMP R2,#0 ;Are we word aligning? ADDNE R3,R3,#3 ;If so, word align this BICNE R3,R3,#3 ;In time-honoured fashion ADD R3,R3,R1 ;Add on size of item STR R3,lit__contents+4 ;Save the new size back LDR R0,be__percents ;Find the % variables LDR R0,[R0,#('P'-'A')*4] ;Load current P% value LDMFD R13!,{R1-R5,R12,PC}^ ;And return to caller LTORG ; --- lit_ltorg --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Inserts a literal pool at the current position. EXPORT lit_ltorg lit_ltorg ROUT STMFD R13!,{R0-R4,R12,R14} ;Save some registers STR R12,[R7,#:INDEX:be__line] ;Store line value MOV R12,R7 ;Find my workspace BL insert_align ;Word align current pos LDR R14,lit__contents+4 ;Any data in literal pool? CMP R14,#0 ;If so, this won't be 0 BEQ %90lit_ltorg ;No -- just align then LDR R4,be__percents ;Find the % variables BL aof_firstPass ;Is this the first pass? BCC %20lit_ltorg ;No -- do the copying then ; --- Add an entry into the literal table --- LDR R2,[R4,#('P'-'A')*4] ;Load current P% value ADR R0,lit__table ;Find the literal table MOV R1,#4 ;Entries are 1 word long BL aof_ensure ;Make the space for it STR R2,[R0],#4 ;Store address in the block B %50lit_ltorg ;Do the rest of the LTORG op ; --- Copy the data in the pool over --- 20lit_ltorg LDR R0,[R4,#('O'-'A')*4] ;Load current O% value ADR R1,lit__contents ;Find the pool contents LDMIA R1,{R1,R2} ;Load address and size BL fastMove ;Copy the data over ADR R0,lit__contents ;Point to the anchor MOV R1,#256 ;Reduce it in size again BL flex_extend ;Put the block back again STR R1,lit__contents+8 ;Save this as the block size LDR R14,lit__next ;Load next literal pool index ADD R14,R14,#4 ;Bump it along one word STR R14,lit__next ;Save it back again ; --- Now move on P% and O% --- 50lit_ltorg LDR R0,lit__contents+4 ;Load the pool size ADD R1,R4,#('O'-'A')*4 ;Point to current O% value LDMIA R1,{R2,R3} ;Load O% and P% out ADD R2,R2,R0 ;Bump O% along ADD R3,R3,R0 ;Bump P% along STMIA R1,{R2,R3} ;Save adjusted values back MOV R0,#0 ;Next literal pool is clear STR R0,lit__contents+4 ;So reset its size to 0 90lit_ltorg BL insert_align ;Word align location LDMFD R13!,{R0-R4,R12,PC}^ ;And return to caller LTORG ; --- lit_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises things for the Literal Manager. EXPORT lit_init lit_init ROUT STMFD R13!,{R0-R3,R14} ;Save some registers MOV R2,#0 ;Blocks currently empty MOV R3,#256 ;Initial size is 256 MOV R1,#256 ;Allocate to 256 bytes ADR R0,lit__table ;Point to lit table anchor BL flex_alloc ;Try to allocate memory STMCCIB R0,{R2,R3} ;Save size information ADRCC R0,lit__contents ;Point to lit contents anchor BLCC flex_alloc ;Try to allocate memory STMCCIB R0,{R2,R3} ;Save size information BCS bas_noMem ;If no memory, die horridly MOV R14,#0 ;No current lit pool index STR R14,lit__next ;So save 0 as index LDMFD R13!,{R0-R3,PC}^ ;And return to caller LTORG ; --- lit_end --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Tidies up the Literal Manager after saving an AOF file. EXPORT lit_end lit_end ROUT STMFD R13!,{R0,R7,R14} ;Save some registers MOV R7,R12 ;For technical reasons LDR R12,be__line ;Keep the line number right BL lit_ltorg ;Insert final literal pool MOV R12,R7 ;Restore the workspace ptr ADR R0,lit__table ;Point to table anchor BL flex_free ;Free the memory ADR R0,lit__contents ;Point to contents block BL flex_free ;Free the memory LDMFD R13!,{R0,R7,PC}^ ;And return to caller LTORG ;----- That's all, folks ---------------------------------------------------- END