Sona 0.50 Source

Sona 0.50/src-z80/vm_alu.z80

;****************************************************************************
; CxOpcodeGroup
; Handles the stream opcodes within $C0..$CF
;----------------------------------------------------------------------------
; input b ..... opcode
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; continues in the respective handler, then ProcessStreamLoop
;----------------------------------------------------------------------------
; notes: this is located here and not in `stream_process.z80` because all the
; subroutines are close and putting it here lets us use JR instead of JP for
; the jump table (saving some RAM)
;****************************************************************************

CxOpcodeGroup:
    PollPcm
    
    ld      a, b
    and     $0F
    add     a, a
    ld      (CxOpcodeJump), a
    
CxOpcodeJump: equ $+1
    jr      $
    
    jr      MoveImmToVar                ; SONAOP_VMMOVE_IMM
    jr      MoveVarToVar                ; SONAOP_VMMOVE_VAR
    jr      AddImmToVar                 ; SONAOP_VMADD_IMM
    jr      AddVarToVar                 ; SONAOP_VMADD_VAR
    jr      SubImmFromVar               ; SONAOP_VMSUB_IMM
    jr      SubVarFromVar               ; SONAOP_VMSUB_VAR
    jr      AndImmWithVar               ; SONAOP_VMAND_IMM
    jr      AndVarWithVar               ; SONAOP_VMAND_VAR
    jr      OrImmWithVar                ; SONAOP_VMOR_IMM
    jr      OrVarWithVar                ; SONAOP_VMOR_VAR
    jr      XorImmWithVar               ; SONAOP_VMXOR_IMM
    jr      XorVarWithVar               ; SONAOP_VMXOR_VAR
    jr      NegVar                      ; SONAOP_VMNEG
    jr      NotVar                      ; SONAOP_VMNOT
    jr      IncrVar                     ; SONAOP_VMINC
    jr      DecrVar                     ; SONAOP_VMDEC

;****************************************************************************
; MoveImmToVar [SONAOP_VMMOVE_IMM]
; MoveVarToVar [SONAOP_VMMOVE_VAR]
;
; Copies an immediate value or variable into (another) variable.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

MoveImmToVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      MoveToVar                   ; Go do the copy

MoveVarToVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to MoveToVar...       ; Go do the copy

;----------------------------------------------------------------------------

MoveToVar:
    ld      a, b
    ld      (de), a
    ret

;****************************************************************************
; AddImmToVar [SONAOP_VMADD_IMM]
; AddVarToVar [SONAOP_VMADD_VAR]
;
; Adds an immediate value or variable to (another) variable.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

AddImmToVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      AddToVar                    ; Go do the addition
    
AddVarToVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to AddToVar...        ; Go do the addition

;----------------------------------------------------------------------------

AddToVar:
    ld      a, (de)
    add     a, b
    ld      (de), a
    ret

;****************************************************************************
; SubImmFromVar [SONAOP_VMADD_IMM]
; SubVarFromVar [SONAOP_VMADD_VAR]
;
; Substract an immediate value or variable from (another) variable.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

SubImmFromVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      SubFromVar                  ; Go do the substraction
    
SubVarFromVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to SubFromVar...      ; Go do the substraction

;----------------------------------------------------------------------------

SubFromVar:
    ld      a, (de)
    sub     b
    ld      (de), a
    ret

;****************************************************************************
; AndImmWithVar [SONAOP_VMAND_IMM]
; AndVarWithVar [SONAOP_VMAND_VAR]
;
; Does a binary AND between an immediate value or variable from (another)
; variable, storing the result in the latter.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

AndImmWithVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      AndWithVar                  ; Go do the AND operation
    
AndVarWithVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to AndWithVar...      ; Go do the AND operation

;----------------------------------------------------------------------------

AndWithVar:
    ld      a, (de)
    and     b
    ld      (de), a
    ret

;****************************************************************************
; OrImmWithVar [SONAOP_VMOR_IMM]
; OrVarWithVar [SONAOP_VMOR_VAR]
;
; Does a binary OR between an immediate value or variable from (another)
; variable, storing the result in the latter.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

OrImmWithVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      OrWithVar                   ; Go do the OR operation
    
OrVarWithVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to OrWithVar...       ; Go do the OR operation

;----------------------------------------------------------------------------

OrWithVar:
    ld      a, (de)
    or      b
    ld      (de), a
    ret

;****************************************************************************
; XorImmWithVar [SONAOP_VMXOR_IMM]
; XorVarWithVar [SONAOP_VMXOR_VAR]
;
; Does a binary XOR between an immediate value or variable from (another)
; variable, storing the result in the latter.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

XorImmWithVar:
    call    FetchImmAndVar              ; Fetch the arguments
    jr      XorWithVar                  ; Go do the XOR operation
    
XorVarWithVar:
    call    FetchVarAndVar              ; Fetch the arguments
    ; fallthrough to XorWithVar...      ; Go do the XOR operation

;----------------------------------------------------------------------------

XorWithVar:
    ld      a, (de)
    xor     b
    ld      (de), a
    ret

;****************************************************************************
; NegVar [SONAOP_VMNEG]
; Flips the sign of a VM variable (two's complement).
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

NegVar:
    ReadArgByte                         ; Fetch variable
    
    ld      e, a                        ; Compute pointer to variable
    ld      d, VmVarList>>8
    
    ld      a, (de)                     ; Retrieve value and write it back
    neg                                 ; with the sign flipped
    ld      (de), a
    
    ret                                 ; End of subroutine

;****************************************************************************
; IncrVar [SONAOP_VMINC]
; Increments the value of a VM variable by 1.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

IncrVar:
    ReadArgByte                         ; Fetch variable
    
    ld      e, a                        ; Compute pointer to variable
    ld      d, VmVarList>>8
    
    ex      de, hl                      ; Increment the variable by 1
    inc     (hl)
    ex      de, hl
    
    ret                                 ; End of subroutine

;****************************************************************************
; DecrVar [SONAOP_VMDEC]
; Decrements the value of a VM variable by 1.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

DecrVar:
    ReadArgByte                         ; Fetch variable
    
    ld      e, a                        ; Compute pointer to variable
    ld      d, VmVarList>>8
    
    ex      de, hl                      ; Decrement the variable by 1
    dec     (hl)
    ex      de, hl
    
    ret                                 ; End of subroutine

;****************************************************************************
; NotVar [SONAOP_VMNOT]
; Does a binary NOT on a VM variable.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

NotVar:
    ReadArgByte                         ; Fetch variable
    
    ld      e, a                        ; Compute pointer to variable
    ld      d, VmVarList>>8
    
    ld      a, (de)                     ; Retrieve value and write it back
    cpl                                 ; with the bits flipped
    ld      (de), a
    
    ret                                 ; End of subroutine

;****************************************************************************
; FetchImmAndVar
;
; Fetches the operands for a VM opcode that takes an immediate source and
; a variable as destination.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output b .... value of source
; output de ... pointer to destination
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

FetchImmAndVar:
    ReadArgByte                         ; Fetch destination variable
    
    ld      e, b                        ; Compute pointer to its value so
    ld      d, VmVarList>>8             ; it can be used by the caller
    
    ReadArgByte                         ; Fetch source value
    ret                                 ; End of subroutine

;****************************************************************************
; FetchVarAndVar
;
; Fetches the operands for a VM opcode that takes a variable as source and
; another variable as destination.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output b .... value of source
; output de ... pointer to destination
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,b,de,a'
;****************************************************************************

FetchVarAndVar:
    ReadArgByte                         ; Fetch destination variable
    
    ld      a, b                        ; Save it for later
    ex      af, af'
    
    ReadArgByte                         ; Fetch source variable
    
    ld      e, b                        ; Get its value
    ld      d, VmVarList>>8
    ld      a, (de)
    ld      b, a
    
    ex      af, af'                     ; Compute pointer to the destination
    ld      e, a                        ; variable's value so it can be used
    ld      d, VmVarList>>8             ; by the caller
    
    PollPcm
    ret                                 ; End of subroutine