module Z80::Utils::VecDeque::Macros
Z80::Utils::VecDeque
macros.¶ ↑
Macros
producing routines for working with double ended queues.
Public Instance Methods
Creates a routine that initializes or clears the queue.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address, a pointer to memory holding an address or
hl
register holding an address of the first byte of memory holding the queue values.
Modifies: hl
.
# File lib/z80/utils/vec_deque.rb, line 39 def vec_deque_clear(vec_deque, vec_deque_bot:) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and (vec_deque_bot == hl or address?(vec_deque_bot)) isolate do ld hl, vec_deque_bot unless vec_deque_bot == hl ld [vec_deque.head], hl ld [vec_deque.tail], hl ld hl, vec_deque.head_bf_tail ld [hl], 0 end end
Creates a routine that checks if the queue is empty.
In case branch_not_full
is nil
the Z
flag, if set, indicates the queue is empty.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
branch_not_empty
-
A target address or a label where to jump to when the queue is NOT empty.
branch_relative
-
If
true
relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 102 def vec_deque_empty?(vec_deque, branch_not_empty: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and (branch_not_empty.nil? or (address?(branch_not_empty) and !pointer?(branch_not_empty))) isolate do |eoc| ld hl, [vec_deque.head] ld tt, [vec_deque.tail] ora a sbc hl, tt if branch_relative jr NZ, branch_not_empty || eoc else jp NZ, branch_not_empty || eoc end ld a, [vec_deque.head_bf_tail] anda a if branch_not_empty if branch_relative jr NZ, branch_not_empty else jp NZ, branch_not_empty end end end end
Creates a routine that checks if the queue is full.
In case branch_not_full
is nil
the Z
flag, if set, indicates the queue is full.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
branch_not_full
-
A target address or a label where to jump to when the queue is NOT full.
branch_relative
-
If true relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 63 def vec_deque_full?(vec_deque, branch_not_full: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and (branch_not_full.nil? or (address?(branch_not_full) and !pointer?(branch_not_full))) isolate do |eoc| ld hl, [vec_deque.head] ld tt, [vec_deque.tail] ora a sbc hl, tt if branch_relative jr NZ, branch_not_full || eoc else jp NZ, branch_not_full || eoc end ld a, [vec_deque.head_bf_tail] if branch_not_full anda a if branch_relative jr Z, branch_not_full else jp Z, branch_not_full end else xor -1 end end end
Creates a routine that calculates the current length of the queue.
The length is made available as a 16-bit integer in the hl
register.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
tt
-
A temporary 16-bit register
bc
orde
.
subroutine
-
Pass
true
for a subroutine.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 142 def vec_deque_length(vec_deque, vec_deque_bot:, vec_deque_top:, tt: de, subroutine: false) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and address?(vec_deque_bot) and address?(vec_deque_top) isolate do |eoc| ld hl, [vec_deque.head] ld tt, [vec_deque.tail] ora a sbc hl, tt jr C, head_before_tail if subroutine ret NZ else jr NZ, eoc end ld a, [vec_deque.head_bf_tail] anda a if subroutine ret Z else jr Z, eoc end ld hl, 0 head_before_tail ld tt, vec_deque_top add hl, tt ld tt, vec_deque_bot ora a sbc hl, tt ret if subroutine end end
Creates a routine that reads a byte element from the back of the queue advancing the cursor backwards.
The removed element is provided in accumulator
.
vec_deque
-
An optional label of a type
VecDequeState
addressing the queue descriptor. If provided the cursor is set to the back of the queue first. In this instance it's possible to skip this part by jumping toget_next
sublabel address of the routine being created.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
cursor
-
A 16-bit register
bc
orde
holding the cursor position.
subroutine
-
Pass
true
for a subroutine.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 439 def vec_deque_next_back(vec_deque=nil, vec_deque_bot:, vec_deque_top:, cursor: de, subroutine: false) raise ArgumentError unless (vec_deque.nil? or (address?(vec_deque) and !pointer?(vec_deque))) and address?(vec_deque_bot) and address?(vec_deque_top) and [bc, de].include?(cursor) isolate do |eoc| ld cursor, [vec_deque.head] unless vec_deque.nil? get_next ld hl, vec_deque_bot ora a sbc hl, cursor jp NZ, skip_wrap ld cursor, vec_deque_top skip_wrap dec cursor ld a, [cursor] ret if subroutine end end
Creates a routine that reads a byte element from the front of the queue advancing the cursor forward.
The removed element is provided in accumulator
.
vec_deque
-
An optional label of a type
VecDequeState
addressing the queue descriptor. If provided the cursor is set to the front of the queue first. In this instance it's possible to skip this part by jumping toget_next
sublabel address of the routine being created.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
cursor
-
A 16-bit register
bc
orde
holding the cursor position.
subroutine
-
Pass
true
for a subroutine.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 401 def vec_deque_next_front(vec_deque=nil, vec_deque_bot:, vec_deque_top:, cursor: de, subroutine: false) raise ArgumentError unless (vec_deque.nil? or (address?(vec_deque) and !pointer?(vec_deque))) and address?(vec_deque_bot) and address?(vec_deque_top) and [bc, de].include?(cursor) isolate do |eoc| ld cursor, [vec_deque.tail] unless vec_deque.nil? get_next ld a, [cursor] inc cursor ld hl, vec_deque_top ora a sbc hl, cursor if subroutine ret NZ else jr NZ, eoc end ld cursor, vec_deque_bot ret if subroutine end end
Creates a routine that removes a byte element from the back of the queue.
The removed element is provided in accumulator
.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
branch_on_empty
-
A target address or a label where to jump to when the queue IS empty.
branch_relative
-
If
true
relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
- NOTE
-
If
branch_on_empty
isnil
then the check is NOT being performed and the routine created assumes there is at least one element available in the queue.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 244 def vec_deque_pop_back(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_empty: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and address?(vec_deque_bot) and address?(vec_deque_top) unless branch_on_empty.nil? or (address?(branch_on_empty) and !pointer?(branch_on_empty)) raise ArgumentError, "branch_on_empty should be an address" end isolate do ld tt, [vec_deque.head] if branch_on_empty ld hl, [vec_deque.tail] ora a sbc hl, tt jp NZ, pop_value ld hl, vec_deque.head_bf_tail bit 0, [hl] if branch_relative jr Z, branch_on_empty else jp Z, branch_on_empty end end pop_value ld hl, vec_deque_bot ora a sbc hl, tt jp NZ, skip_wrap ld hl, vec_deque.head_bf_tail ld [hl], 0 ld tt, vec_deque_top skip_wrap dec tt ld a, [tt] ld [vec_deque.head], tt end end
Creates a routine that removes a byte element from the front of the queue.
The removed element is provided in accumulator
.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
branch_on_empty
-
A target address or a label where to jump to when the queue IS empty.
branch_relative
-
If
true
relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
- NOTE
-
If
branch_on_empty
isnil
then the check is NOT being performed and the routine created assumes there is at least one element available in the queue.
Modifies: af
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 349 def vec_deque_pop_front(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_empty: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and address?(vec_deque_bot) and address?(vec_deque_top) unless branch_on_empty.nil? or (address?(branch_on_empty) and !pointer?(branch_on_empty)) raise ArgumentError, "branch_on_empty should be an address" end isolate do ld tt, [vec_deque.tail] if branch_on_empty ld hl, [vec_deque.head] ora a sbc hl, tt jp NZ, pop_value ld hl, vec_deque.head_bf_tail bit 0, [hl] if branch_relative jr Z, branch_on_empty else jp Z, branch_on_empty end end pop_value ld a, [tt] inc tt ld hl, vec_deque_top ora a sbc hl, tt jr NZ, skip_wrap ld hl, vec_deque.head_bf_tail ld [hl], 0 ld tt, vec_deque_bot skip_wrap ld [vec_deque.tail], tt end end
Creates a routine that appends a byte element to the back of the queue.
accumulator
-
Should hold a value to be pushed to the queue.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
branch_on_full
-
A target address or a label where to jump to when the queue IS full.
branch_relative
-
If
true
relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
- NOTE
-
If
branch_on_full
isnil
then the check is NOT being performed and the routine created assumes there is enough space for another element in the queue.
Modifies: f
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 191 def vec_deque_push_back(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_full: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and address?(vec_deque_bot) and address?(vec_deque_top) unless branch_on_full.nil? or (address?(branch_on_full) and !pointer?(branch_on_full)) raise ArgumentError, "branch_on_full should be a direct address" end isolate do ld tt, [vec_deque.head] if branch_on_full ld hl, [vec_deque.tail] ora a sbc hl, tt jp NZ, push_value ld hl, vec_deque.head_bf_tail bit 0, [hl] if branch_relative jr NZ, branch_on_full else jp NZ, branch_on_full end end push_value ld [tt], a inc tt ld hl, vec_deque_top ora a sbc hl, tt jp NZ, skip_wrap ld hl, vec_deque.head_bf_tail ld [hl], -1 ld tt, vec_deque_bot skip_wrap ld [vec_deque.head], tt end end
Creates a routine that appends a byte element to the front of the queue.
accumulator
-
Should hold a value to be pushed to the queue.
vec_deque
-
A label of a type
VecDequeState
addressing the queue descriptor.
Options:
vec_deque_bot
-
An address or a pointer to memory holding an address of the first byte of memory holding the queue values.
vec_deque_top
-
An address or a pointer to memory holding an address immediately succeeding the last byte of memory holding the queue values.
branch_on_full
-
A target address or a label where to jump to when the queue IS full.
branch_relative
-
If
true
relative jumps are being used for branching.
tt
-
A temporary 16-bit register
bc
orde
.
- NOTE
-
If
branch_on_full
isnil
then the check is NOT being performed and the routine created assumes there is enough space for another element in the queue.
Modifies: f
, hl
, tt
.
# File lib/z80/utils/vec_deque.rb, line 296 def vec_deque_push_front(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_full: nil, branch_relative: true, tt: de) raise ArgumentError unless address?(vec_deque) and !pointer?(vec_deque) and [bc, de].include?(tt) and address?(vec_deque_bot) and address?(vec_deque_top) unless branch_on_full.nil? or (address?(branch_on_full) and !pointer?(branch_on_full)) raise ArgumentError, "branch_on_full should be a direct address" end isolate do ld tt, [vec_deque.tail] if branch_on_full ld hl, [vec_deque.head] ora a sbc hl, tt jp NZ, push_value ld hl, vec_deque.head_bf_tail bit 0, [hl] if branch_relative jr NZ, branch_on_full else jp NZ, branch_on_full end end push_value ld hl, vec_deque_bot ora a sbc hl, tt jr NZ, skip_wrap ld hl, vec_deque.head_bf_tail ld [hl], -1 ld tt, vec_deque_top skip_wrap dec tt ld [tt], a ld [vec_deque.tail], tt end end