249 lines
5.7 KiB
NASM
249 lines
5.7 KiB
NASM
; ***************************************************************************
|
|
; copyright : (C) 2025 by Martin Preuss
|
|
; email : martin@libchipcard.de
|
|
;
|
|
; ***************************************************************************
|
|
; * This file is part of the project "AqHome". *
|
|
; * Please see toplevel file COPYING of that project for license details. *
|
|
; ***************************************************************************
|
|
|
|
#ifndef AQH_AVR_COMMON_LIST_H
|
|
#define AQH_AVR_COMMON_LIST_H
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; This code implements a simple single-linked list.
|
|
; It assumes that the first 2 bytes of an object managed by this code contain
|
|
; a 2 byte pointer to the next object.
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; defs
|
|
|
|
.equ LIST_OFFS_NEXT_LO = 0
|
|
.equ LIST_OFFS_NEXT_HI = 1
|
|
.equ LIST_SIZE = 2
|
|
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_InitObject @global
|
|
;
|
|
; Reset list object fields.
|
|
; @param Y pointer to object
|
|
; @clobbers r16
|
|
|
|
List_InitObject:
|
|
clr r16 ; set this->NEXT to NULL
|
|
std Y+LIST_OFFS_NEXT_LO, r16
|
|
std Y+LIST_OFFS_NEXT_HI, r16
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_FiniObject @global
|
|
;
|
|
; @param Y pointer to object
|
|
; @clobbers r16
|
|
|
|
List_FiniObject:
|
|
clr r16 ; set this->NEXT to NULL
|
|
std Y+LIST_OFFS_NEXT_LO, r16
|
|
std Y+LIST_OFFS_NEXT_HI, r16
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_GetNextObject @global
|
|
|
|
; @param Y pointer to object
|
|
; @return X pointer to successor object
|
|
; @clobbers none
|
|
|
|
List_GetNextObject:
|
|
ldd xl, Y+LIST_OFFS_NEXT_LO
|
|
ldd xh, Y+LIST_OFFS_NEXT_HI
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_GetLastObject
|
|
|
|
; @param X pointer to one object in a list
|
|
; @return X pointer to last object which has an empty NEXT pointer
|
|
; @clobbers r16, r17, X, Y
|
|
|
|
List_GetLastObject:
|
|
clr yl
|
|
clr yh
|
|
rjmp List_GetPredecessorFor
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_GetPredecessorFor
|
|
|
|
; @param Y pointer to this object
|
|
; @param X pointer to first object in a list
|
|
; @return X pointer to object whose NEXT pointer points to the given object (or NULL)
|
|
; @clobbers r16, r17, X
|
|
|
|
List_GetPredecessorFor:
|
|
mov r16, xl
|
|
or r16, xh
|
|
breq List_GetPredecessorFor_ret
|
|
ld r16, X+
|
|
ld r17, X+
|
|
cp r16, yl
|
|
brne List_GetPredecessorFor_next
|
|
cp r17, yh
|
|
breq List_GetPredecessorFor_haveIt
|
|
List_GetPredecessorFor_next:
|
|
mov xl, r16
|
|
mov xh, r17
|
|
rjmp List_GetPredecessorFor
|
|
List_GetPredecessorFor_haveIt:
|
|
sbiw xh:xl, 2
|
|
List_GetPredecessorFor_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_AddObject
|
|
|
|
; @param X pointer to first object in a list
|
|
; @param Y pointer to object to add
|
|
; @clobbers r16, r17, x
|
|
|
|
List_AddObject:
|
|
push yl
|
|
push yh
|
|
rcall List_GetLastObject ; (r16, r17, X, Y)
|
|
pop yh
|
|
pop yl
|
|
mov r16, xl
|
|
or r16, xh
|
|
clc
|
|
breq List_AddObject_ret
|
|
st X+, yl ; LIST_OFFS_NEXT_LO
|
|
st X+, yh ; LIST_OFFS_NEXT_HI
|
|
sec
|
|
List_AddObject_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_UnlinkObject
|
|
|
|
; @param X pointer to first object in a list
|
|
; @param Y pointer to object to remove
|
|
; @clobbers r16, r17, x
|
|
|
|
List_UnlinkObject:
|
|
push yl
|
|
push yh
|
|
rcall List_GetPredecessorFor ; (r16, r17, X)
|
|
pop yh
|
|
pop yl
|
|
mov r16, xl
|
|
or r16, xh
|
|
breq List_UnlinkObject_ret
|
|
ldd r16, Y+LIST_OFFS_NEXT_LO ; get this->NEXT
|
|
ldd r17, Y+LIST_OFFS_NEXT_HI
|
|
st X+, r16 ; store as NEXT in predecessor
|
|
st X, r17
|
|
clr r16 ; set this->NEXT to NULL
|
|
std Y+LIST_OFFS_NEXT_LO, r16
|
|
std Y+LIST_OFFS_NEXT_HI, r16
|
|
List_UnlinkObject_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_UnlinkAllObjects
|
|
|
|
; @param Y pointer to first object in a list
|
|
; @clobbers r16, r17, r18, Y
|
|
|
|
List_UnlinkAllObjects:
|
|
clr r18
|
|
List_UnlinkAllObjects_loop:
|
|
ldd r16, Y+LIST_OFFS_NEXT_LO
|
|
ldd r17, Y+LIST_OFFS_NEXT_HI
|
|
std Y+LIST_OFFS_NEXT_LO, r18
|
|
std Y+LIST_OFFS_NEXT_HI, r18
|
|
mov yl, r16
|
|
mov yh, r17
|
|
or r16, r17
|
|
brne List_UnlinkAllObjects_loop
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine List_ForEveryObject
|
|
;
|
|
; Calls the given function for every object until it
|
|
; returns with a set carry flag or until the full list
|
|
; is handled.
|
|
; All registers that can be used by the given function, however
|
|
; R16, R18, R19 and Y are modified between function calls.
|
|
;
|
|
; @param Y pointer to first object in a list
|
|
; @param Z routine to call for every object
|
|
; @clobbers r16, r17, r18, r19, X, Y (r24, r25)
|
|
|
|
List_ForEveryObject:
|
|
List_ForEveryObject_loop:
|
|
ldd r18, Y+LIST_OFFS_NEXT_LO ; next
|
|
ldd r19, Y+LIST_OFFS_NEXT_HI ; next
|
|
push r18 ; next
|
|
push r19 ; next
|
|
rcall List_ForEveryObject_callZ
|
|
pop r19 ; next
|
|
pop r18 ; next
|
|
brcs List_ForEveryObject_ret
|
|
mov yl, r18
|
|
mov yh, r19
|
|
or r18, r19
|
|
brne List_ForEveryObject_loop
|
|
List_ForEveryObject_ret:
|
|
ret
|
|
List_ForEveryObject_callZ:
|
|
ijmp
|
|
; @end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif ; AQH_AVR_COMMON_LIST_H
|