;Implementation of SoftMMU - xalloc ;================================== .global xalloc .global xalloc_trynext .global xalloc_getbestfit ;------ xalloc: ;------ **** OLD CODE!!! **** ; Allocate memory out of an available expanded memory ; pool. ; ; <- X = zero page pointer to memory struct ; A/Y = size (in pages) of memory chunk to allocate ; ; Memory struct (5 bytes): ; $00,x = physical 6502 pointer to memory window page ; $02,x = offset into memory chunk, in pages ; $04,x = single-byte pointer into TSP chunk descriptor ; --- ; Allocation method ; --- ; ; For each memory source, a page is allocated which contains a list of ; 4-byte structures which hold the start position and size of each ; chunk of free memory in the memory source. When memory is allocated, ; the size value stored in the structure is reduced. A size of zero ; indicates that the structure is defunct, and may be overwritten when ; a new structure needs to be created. When memory is freed, the routine ; scans through the structures to see if the freed section is adjacent ; to any current free structures. If so, it merely expands the structure ; by updating its size and/or location. If not, a new structure is ; created. ; ; Structure description: ; $00 = size of chunk, in pages ; $02 = starting page of chunk ; This entire routine is atomic, so zptemp is used for storage: ; tmpzp = general pointer ; tmpzp+2 = .X arg, zp pointer to memory structure ; tmpzp+3 = .A arg, num pages to allocate ;First things first jsr locktsw ;Save parameters stx tmpzp+2 sta tmpzp+3 sty tmpzp+4 ;Loop through the available memory systems, trying to allocate. ldy #$ff xalloc_trynext: iny ldx sm_memlist,y beq xalloc_nomem lda sm_xalloclo,x sta tmpzp lda sm_xallochi,x jmp (tmpzp) xalloc_nomem: jmp catcherr ; --- ; Helper functions for the allocation ; --- ;----------------- xalloc_getbestfit: ;----------------- **** OLD CODE!!! **** ; The expansion-specific routine will bring the free memory structures ; into 6502 address space, at (tmpzp)+Y through (tmpzp)+255, and then ; call this routine to find a nice fit for the new memory chunk from ; the free memory structures presented. Call this as many times as ; needed to scan the entire free memory list. After each call, if a new ; best fit is found, tmpzp+7 will be nonzero, and contain the .Y value ; at which the best fit was found, plus 1. This should flag the calling ; routine to store where this current set of structures is, so that it can ; be easily recalled when the scanning is done. ; ; Oh yeah, initialize tmpzp+5,tmpzp+6 to $ffff before calling this the ; first time. ; This is still atomic, so zptemp is retained: ; tmpzp = general pointer ; tmpzp+2 = .X arg, zp pointer to memory structure ; tmpzp+3 = .Y arg, num pages to allocate ; tmpzp+5 = free memory struct length ; tmpzp+7 = temp storage for free mem struct pointer lda #$00 ;reset flag sta tmpzp+7 - lda (tmpzp),y ;see if chunk size >= requested size iny cmp tmpzp+3 lda (tmpzp),y sbc tmpzp+4 bcc + dey lda (tmpzp),y ;see if chunk size < last best size iny cmp tmpzp+5 lda (tmpzp),y sbc tmpzp+6 bcs + dey ;alright! let's keep this one lda (tmpzp),y sta tmpzp+5 iny lda (tmpzp),y sta tmpzp+6 sty tmpzp+7 + iny iny bne - rts ;--------- xalloc_do: ;--------- *** OLD CODE!!! **** ; Actually perform the allocation, which entails updating the free memory ; list, initializing the zp user structure, and creating a tsp structure ; for the newly created chunk. Before calling this routine, set up tmpzp ; and .Y using the last best value set by xalloc_getbestfit. Once this is ; finished, the expansion-specific routine must set up the actual window ; pointer and spalloc a page for it, if required, and set the memory source ; in the tsp struct. ; ; If tmpzp+5 returns nonzero, the ; This is still atomic, so zptemp is retained: ; tmpzp = general pointer ; tmpzp+2 = .X arg, zp pointer to memory structure ; tmpzp+3 = .Y arg, num pages to allocate ; tmpzp+5 = free memory struct length ; tmpzp+7 = temp storage for free mem struct pointer ; syszp = free memory struct start ; syszp+2 = end of allocated memory/start of new free memory struct sty tmpzp+7 ;zp stuff clc ;First, let's get a tsp structure lda tsp_smptr tay adc #$06 sta tsp_smptr ldx tmpzp+2 ;and point the zp & tsp structs to each other sty $04,X txa sta (lk_tsp),y ;tsp stuff ldy tmpzp+7 ;copy the chunk start location iny lda (tmpzp),y sta syszp iny lda (tmpzp),y sta syszp+1 ldy $04,x ;save it in TSP, and add the length to get ending address iny ;save ending address to store later ;clc ;should be clear from above ADC #$06 lda syszp sta (lk_tsp),y adc tmpzp+3 iny iny sta (lk_tsp),y sta syszp+2 lda syszp+1 dey sta (lk_tsp),y adc tmpzp+4 iny iny sta (lk_tsp),y sta syszp+3 ;free mem list stuff ldy tmpzp+7 ;Reduce the length of the free memory struct dey sec lda tmpzp+5 sbc tmpzp+3 php sta (tmpzp),y iny lda tmpzp+6 sbc tmpzp+4 sta (tmpzp),y bne + ;check to see if the entire free chunk got allocated plp bne ++ lda #$ff bne +++ ;always branch + plp + lda #$00 + sta tmpzp+5 iny ;and set the start of the free chunk to the end of the lda syszp+2 ;allocated one sta (tmpzp),y iny lda syszp+3 sta (tmpzp),y rts