module Z80::Utils::VecDeque::Macros

Z80::Utils::VecDeque macros.

Macros producing routines for working with double ended queues.

Public Instance Methods

vec_deque_clear(vec_deque, vec_deque_bot:) click to toggle source

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
vec_deque_empty?(vec_deque, branch_not_empty: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

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
vec_deque_full?(vec_deque, branch_not_full: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

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
vec_deque_length(vec_deque, vec_deque_bot:, vec_deque_top:, tt: de, subroutine: false) click to toggle source

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 or de.

  • 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
vec_deque_next_back(vec_deque=nil, vec_deque_bot:, vec_deque_top:, cursor: de, subroutine: false) click to toggle source

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 to get_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 or de 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
vec_deque_next_front(vec_deque=nil, vec_deque_bot:, vec_deque_top:, cursor: de, subroutine: false) click to toggle source

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 to get_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 or de 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
vec_deque_pop_back(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_empty: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

NOTE

If branch_on_empty is nil 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
vec_deque_pop_front(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_empty: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

NOTE

If branch_on_empty is nil 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
vec_deque_push_back(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_full: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

NOTE

If branch_on_full is nil 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
vec_deque_push_front(vec_deque, vec_deque_bot:, vec_deque_top:, branch_on_full: nil, branch_relative: true, tt: de) click to toggle source

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 or de.

NOTE

If branch_on_full is nil 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