LIBRARY Memory

.extend
; *******************************************************************
; Subroutine:   extend
; Description:  extend a previously claimed block
; Parameters:   r0 = block
;               r1 = size to extend by
; Returns:      r0 = block, VS if error (r0 preserved)
; *******************************************************************
   STMFD   (sp)!,{r1-r3,link}            ; Stack registers
   MOV     r2,r0                         ; right register
   MOV     r3,r1                         ; right register
   XSWI    "XOS_Module",13               ; extend space
$noerror
   MOV     r0,r2                         ; return address
   LDMFD   (sp)!,{r1-r3,pc}              ; Return from call

.claim
; *******************************************************************
; Subroutine:   claim
; Description:  claim some RMA to r0 (size=r0)
; Parameters:   r0 = size
; Returns:      r0 = address, or 0 if failed
; *******************************************************************
   STMFD   (sp)!,{r1-r3,link}            ; Stack registers
   MOV     r3,r0                         ; right register
   XSWI    "XOS_Module",6                ; claim space
   MOVVS   r0,#0                         ; if error, return 0
   MOV     r0,r2                         ; return address
   LDMFD   (sp)!,{r1-r3,pc}^             ; Return from call

.release
; *******************************************************************
; Subroutine:   release
; Description:  release RMA at r0
; Parameters:   r0 = address
; Returns:      none
; *******************************************************************
   STMFD   (sp)!,{r0-r2,link}            ; Stack registers
   MOV     r2,r0                         ; right register
   XSWI    "XOS_Module",7                ; claim space
   LDMFD   (sp)!,{r0-r2,pc}^             ; Return from call

; *******************************************************************
; Subroutine:   strdup
; Description:  Copy a string
; Parameters:   r0-> string
; Returns:      r0-> new copy of string, VS if error
; *******************************************************************
.strdup
   STMFD   (sp)!,{r0,r1,r2,link}         ; Stack registers
   BL      strlen                        ; find length of string
   MOV     r2,r1                         ; hang on to length of string
   ADD     r0,r1,#1                      ; including terminator
   BL      claim                         ; claim space for it
   CMP     r0,#0                         ; did claim fail ?
   BEQ     $fail                         ; if so, give error
   MOV     r1,r0                         ; r1=destination
   LDR     r0,[sp]                       ; re-read source
   BL      strcpy                        ; copy string
   STR     r1,[sp]                       ; return destination
   MOV     r0,#0                         ; null terminator
   STRB    r0,[r1,r2]                    ; zero terminated
   LDMFD   (sp)!,{r0,r1,r2,pc}           ; Return from call
$fail
   ADD     sp,sp,#4                      ; skip r0
   LDMFD   (sp)!,{r1,r2,link}            ; restore registers
   ADR     r0,$`error                    ; get pointer to error
   ORRS    pc,link,#vbit                 ; return with V bit

$`error
   EQUD    0
   EQUZA   "String duplication failed - not enough memory"

; #Library "Strings",strlen.strcpy
