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
VecDequeStateaddressing the queue descriptor.
Options:
vec_deque_bot-
An address, a pointer to memory holding an address or
hlregister 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
VecDequeStateaddressing 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
truerelative jumps are being used for branching.
tt-
A temporary 16-bit register
bcorde.
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
VecDequeStateaddressing 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
bcorde.
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
VecDequeStateaddressing 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
bcorde.
subroutine-
Pass
truefor 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
VecDequeStateaddressing 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_nextsublabel 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
bcordeholding the cursor position.
subroutine-
Pass
truefor 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
VecDequeStateaddressing 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_nextsublabel 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
bcordeholding the cursor position.
subroutine-
Pass
truefor 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
VecDequeStateaddressing 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
truerelative jumps are being used for branching.
tt-
A temporary 16-bit register
bcorde.
- NOTE
-
If
branch_on_emptyisnilthen 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
VecDequeStateaddressing 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
truerelative jumps are being used for branching.
tt-
A temporary 16-bit register
bcorde.
- NOTE
-
If
branch_on_emptyisnilthen 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
VecDequeStateaddressing 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
truerelative jumps are being used for branching.
tt-
A temporary 16-bit register
bcorde.
- NOTE
-
If
branch_on_fullisnilthen 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
VecDequeStateaddressing 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
truerelative jumps are being used for branching.
tt-
A temporary 16-bit register
bcorde.
- NOTE
-
If
branch_on_fullisnilthen 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