.Xlist Page 58,132 Subttl MACROS.INC Apple Emulator (65C02 Processor) ;****************************************************************************** ; ; Name: MACROS Apple Emulator (65C02 Processor) ; ; Group: Emulator ; ; Revision: 1.00 ; ; Date: January 30, 1988 ; ; Author: Randy W. Spurlock ; ;****************************************************************************** ; ; Module Functional Description: ; ; This module contains all the macros needed by the ; Apple emulator. This module can be included with any needed ; source files to define the Apple emulator macros. ; ;****************************************************************************** ; ; Changes: ; ; DATE REVISION DESCRIPTION ; -------- -------- ------------------------------------------------------- ; 1/30/88 1.00 Original ; ;****************************************************************************** _count = 00h _current= 00h _number = 00h Atari_Interrupt Macro vector lodsb mov di,vector mov di,ds:[di] ; get address pointed to by nmivector mov ax,si ; Get the current program counter dec ax ; Point to last instruction byte Push_16 ; Save the return address on the stack mov si,di ; Update the program counter mov al,dh ; get flags xor ah,ah ; ax = flags mov bx,ax ; used to encode flags mov al,cs:[bx + Flag_Encode] Push_8 ; flags saved on atari stack Endm Ticks Macro tickcount local _No_Update sub bp,tickcount ja _No_Update call Hardware_Update _No_Update: endm LineUp Macro divide,filler _value = $ - _current If _number Gt 00h Check %_number, %_value Endif .Xlist Ifb _fill = 00h Else _fill = filler Endif _addr = $ - Emulate _amt = _addr MOD divide If _amt NE 0 _amt = divide - _amt Db _amt dup (filler) ; Reserved required space to line up Endif .List _current= $ _number = _number + 1 Endm Check Macro Number, Value If2 If &Value Gt OP_SIZE %out *** Error - Opcode &Number length is &Value *** Endif Endif Endm String Macro Str _cnt = 0 Irpc x, _cnt = _cnt + 1 Endm Db _cnt,Str,0Dh,0Ah ; Define the requested string Endm Err_Str Macro Name, Str Def_Err %_Err_Cnt,Name, _Err_Cnt= _Err_Cnt + 1 Endm Def_Err Macro Number,Name,Str ERR_&Name Equ &Number ; Define the error name public ERR_&Name Error_&Number Equ This Word ; Define the error string String Endm Err_Tbl Macro Error_Table Equ This Word ; Declare start of error table _Err_Num= 0 Rept _Err_Cnt Def_Tbl %_Err_Num _Err_Num= _Err_Num + 1 Endm Endm Def_Tbl Macro Number Dw Error_&Number ; Define the error table entry Endm Encode Macro Value _base = Value And 10110101b _flag_Z = (Value And 01000000b) Shr 6 _flag_V = (Value And 00001000b) Shr 3 _flag_M = (Value And 00000010b) Shr 1 _value = _base + (_flag_V Shl 6) + (_flag_M Shl 3) + (_flag_Z Shl 1) Db _value ; Define the encoded byte value Endm Decode Macro Value _base = Value And 10110101b _flag_V = (Value And 01000000b) Shr 6 _flag_M = (Value And 00001000b) Shr 3 _flag_Z = (Value And 00000010b) Shr 1 _value = _base + (_flag_Z Shl 6) + (_flag_V Shl 3) + (_flag_M Shl 1) Db _value ; Define the decoded byte value Endm Save Macro a,b,c,d,e,f,g,h,i,j .Xlist Irp x, Ifnb push x ; Save the requested register Endif Endm .List Endm Restore Macro a,b,c,d,e,f,g,h,i,j .Xlist Irp x, Ifnb pop x ; Restore the requested register Endif Endm .List Endm Fault Macro or cs:[Emulate_Flag],SYS_DEBUG or dh,CPU_R ; Set emulator interrupt request Endm Fetch Macro lodsb xor ah,ah shl ax,1 ; Convert opcode to address mov di,ax ; Move routine address to DI jmp cs:[di] ; Jump to correct opcode routine Endm Flgnz Macro lahf ; Load flags into AH register and ah,CPU_N + CPU_Z ; Mask off all but sign/zero flags and dh,Not (CPU_N + CPU_Z) ; Clear the n and z flags or dh,ah ; Update the 65C02 status flags Endm Flgnzc Macro reg lahf ; Load flags into AH register (2) and ah,CPU_N + CPU_Z + CPU_C ; Mask off all but sign/carry/zero flags and dh,Not (CPU_N + CPU_Z + CPU_C) ; (4) (4) or dh,ah ; Update the 65C02 status flags Endm Flgnvzc Macro pushf ; Push the processor flags pop ax ; Pop flags into AX register and ax,0000100011000001b ; Mask all but overflow/sign/zero/carry or al,ah ; Logically OR in overflow flag and dh,Not (CPU_N + CPU_V + CPU_Z + CPU_C) or dh,al ; Update the 65C02 status flags Endm Push_16 Macro sub cs:Astack,2 ; mov bl,cs:Astack mov bh,1 mov ds:[bx+1],ax ; Push the 16-bit value Endm Push_8 Macro mov bl,cs:Astack mov bh,1 ; get stack pointer mov ds:[bx],al ; Push the 8-bit value dec cs:Astack ; Decrement the stack pointer Endm Pop_16 Macro add cs:Astack,2 mov bl,cs:Astack mov bh,1 mov ax,ds:[bx-1] ; Pop the 16-bit value Endm Pop_8 Macro inc cs:Astack mov bl,cs:Astack mov bh,1 mov al,ds:[bx] ; Pop the 8-bit value Endm DoImm Macro _type = 000h mov di,si ; Setup the effective address inc si ; Update the program counter Endm DoAbs Macro _type = 0FFh lodsw ; Get the absolute address mov di,ax ; Setup the effective address Endm DoDP Macro _type = 000h lodsb ; Get the direct page offset xor ah,ah ; Convert to direct page address mov di,ax ; Setup the effective address Endm DoDIX Macro _type = 000h lodsb ; Get the direct page offset add al,ch ; Add in the X index value xor ah,ah ; Convert to direct page address mov di,ax ; Setup the effective address Endm DoDIY Macro _type = 000h lodsb ; Get the direct page offset add al,cl ; Add in the Y index value xor ah,ah ; Convert to direct page address mov di,ax ; Setup the effective address Endm DoAIX Macro _type = 0FFh lodsw ; Get the absolute address add al,ch ; Add in the X index value adc ah,0 ; Do 16-bit arithmetic mov di,ax ; Setup the effective address Endm DoAIY Macro _type = 0FFh lodsw ; Get the absolute address add al,cl ; Add in the Y index value adc ah,0 ; Do 16-bit arithmetic mov di,ax ; Setup the effective address Endm DoAI Macro _type = 0FFh lodsw ; Get the absolute address mov di,ax ; Setup to do the indirection mov di,ds:[di] ; Setup the effective address Endm DoDI Macro _type = 0FFh lodsb ; Get the direct page offset xor ah,ah ; Convert to direct page address mov di,ax ; Setup to do the indirection mov di,ds:[di] ; Setup the effective address Endm DoAIIX Macro _type = 0FFh lodsw ; Get the absolute address add al,ch ; Add in the X index value adc ah,0 ; Do 16-bit arithmetic mov di,ax ; Setup to do the indirection mov di,ds:[di] ; Setup the effective address Endm DoDIIX Macro _type = 0FFh lodsb ; Get the direct page offset add al,ch ; Add in the X index value xor ah,ah ; Convert to direct page address mov di,ax ; Setup to do the indirection mov di,ds:[di] ; Setup the effective address Endm DoDIIY Macro _type = 0FFh lodsb ; Get the direct page offset xor ah,ah ; Convert to direct page address mov di,ax ; Setup to do the indirection mov di,ds:[di] ; Do the indirection mov al,cl ; Get the Y index value add di,ax ; Setup the effective address Endm DoPCR Macro _type = 000h mov di,si ; Get the current program counter lodsb ; Get the program counter offset cbw ; Convert offset into a full word add di,ax ; Setup the effective address Endm OpADC Macro local _addr, _update ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov ah,dh ; Copy 65C02 flags into AH register test dh,CPU_M ; Check for in decimal mode (BCD) jz _addr ; Jump if in binary mode shr ah,1 ; Shift 65C02 carry into real carry adc al,dl ; Add with carry to accumulator daa ; Do the adjust for decimal mode mov dl,al ; Update the accumulator value jmp Short _update ; Go update the 65C02 flags _addr: shr ah,1 ; Shift 65C02 carry into real carry adc dl,al ; Add with carry to accumulator _update: Flgnvzc ; Update the 65C02 processor flags Endm OpAND Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif and dl,al ; AND accumulator with memory Flgnz ; Update the 65C02 processor flags Endm OpASL Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif shl al,1 ; Shift the memory location left mov bx,ax ; Save the memory location value Flgnzc ; Update the 65C02 processor flags mov ax,bx ; Restore the memory location value If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpBIT Macro Local _addr and dh,Not (CPU_N + CPU_V + CPU_Z) ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif test dl,al ; AND accumulator with memory value jnz _addr ; Jump if the value is non-zero or dh,CPU_Z ; Zero result, set the zero flag _addr: and al,11000000b ; Mask off all but upper two bits xor ah,ah ; Convert flag bits to full word mov bx,ax ; Setup to decode the flag value or dh,cs:[bx + Flag_Decode]; Set correct bits in 65C02 status Endm OpBITz Macro Local _addr and dh,Not CPU_Z ; Clear the z flag ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif test dl,al ; AND accumulator with memory value jnz _addr ; Jump if the value is non-zero or dh,CPU_Z ; Zero result, set the zero flag _addr: Endm OpCMP Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif cmp dl,al ; Compare accumulator with memory cmc ; Toggle carry to the correct state Flgnzc ; Update the 65C02 processor flags Endm OpCPX Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif cmp ch,al ; Compare X index register with memory cmc ; Toggle carry to the correct state Flgnzc ; Update the 65C02 processor flags Endm OpCPY Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif cmp cl,al ; Compare Y index register with memory cmc ; Toggle carry to the correct state Flgnzc ; Update the 65C02 processor flags Endm OpDEC Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif dec al ; Decrement the memory location mov bx,ax ; Save the memory location value Flgnz ; Update the 65C02 processor flags mov ax,bx ; Restore the memory location value If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpEOR Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif xor dl,al ; Exclusive-OR accumulator with memory Flgnz ; Update the 65C02 processor flags Endm OpINC Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif inc al ; Increment the memory location mov bx,ax ; Save the memory location value Flgnz ; Update the 65C02 processor flags mov ax,bx ; Restore the memory location value If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpJMP Macro mov si,di ; Update the program counter Endm OpJSR Macro mov ax,si ; Get the current program counter dec ax ; Point to last instruction byte Push_16 ; Save the return address on the stack mov si,di ; Update the program counter call Jsr_Steal ; override atari code Endm OpLDA Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov dl,al ; Load accumulator from memory or dl,dl ; Set the status flags correctly Flgnz ; Update the 65C02 processor flags Endm OpLDX Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov ch,al ; Load X index register from memory or ch,ch ; Set the status flags correctly Flgnz ; Update the 65C02 processor flags Endm OpLDY Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov cl,al ; Load Y index register from memory or cl,cl ; Set the status flags correctly Flgnz ; Update the 65C02 processor flags Endm OpLSR Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif shr al,1 ; Shift the memory location right mov bx,ax ; Save the memory location value Flgnzc ; Update the 65C02 processor flags mov ax,bx ; Restore the memory location value If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpORA Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif or dl,al ; OR accumulator with memory Flgnz ; Update the 65C02 processor flags Endm OpROL Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov ah,dh ; Copy 65C02 flags into AH register shr ah,1 ; Shift 65C02 carry into real carry rcl al,1 ; Rotate the memory location left rcr ah,1 ; Save carry result in AH register If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif or al,al ; Set the n and z flags correctly rcl ah,1 ; Restore the carry result Flgnzc ; Update the 65C02 processor flags Endm OpROR Macro ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov ah,dh ; Copy 65C02 flags into AH register shr ah,1 ; Shift 65C02 carry into real carry rcr al,1 ; Rotate the memory location right rcr ah,1 ; Save carry result in AH register If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif or al,al ; Set the n and z flags correctly rcl ah,1 ; Restore the carry result Flgnzc ; Update the 65C02 processor flags Endm OpSBC Macro local _addr ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif mov ah,dh ; Copy 65C02 flags into AH register shr ah,1 ; Shift 65C02 carry into real carry cmc ; Invert carry to correct state xchg al,dl ; Get the current accumulator value sbb al,dl ; Subtract from accumulator with borrow lahf ; Save the actual flags value test dh,CPU_M ; Check for decimal mode jz _addr ; Jump if in binary mode sahf ; Restore the actual flags value das ; Do the adjust for decimal mode lahf ; Save the actual flags value _addr: sahf ; Restore the actual flags value mov dl,al ; Update the accumulator value cmc ; Invert carry back to correct state Flgnvzc ; Update the 65C02 processor flags Endm OpSTA Macro mov al,dl ; Store the accumulator in memory If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpSTX Macro mov al,ch ; Store X index register in memory If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpSTY Macro mov al,cl ; Store Y index register in memory If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpSTZ Macro xor al,al ; Store zero in memory If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif Endm OpTRB Macro Local _addr ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif and dh,Not CPU_Z ; Clear the z flag mov ah,dl ; Get a copy of the accumulator not ah ; Invert the accumulator value and al,ah ; Mask off the desired memory bits If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif not ah ; Restore the accumulator value and ah,al ; AND accumulator with memory jnz _addr ; Jump if the result is non-zero or dh,CPU_Z ; Zero result, set the z flag _addr: Endm OpTSB macro Local _addr ; If _type ; call Read_Memory ; call routine to read 65C02 memory ; Else mov al,ds:[di] ; Read the 65C02 memory value ; Endif and dh,Not CPU_Z ; Clear the z flag mov ah,dl ; Get a copy of the accumulator or al,ah ; Set the desired memory bits If _type call Write_Memory ; call routine to write 65C02 memory Else mov ds:[di],al ; Write the 65C02 memory value Endif and ah,al ; AND accumulator with memory jnz _addr ; Jump if the result is non-zero or dh,CPU_Z ; Zero result, set the z flag _addr: Endm OpRMB Macro Value If _type ; call Read_Memory ; call routine to read 65C02 memory mov al,ds:[di] ; Read the memory location and al,Not Value ; Reset the requested bit call Write_Memory ; call routine to write 65C02 memory Else and Byte Ptr ds:[di],Not Value Endif Endm OpSMB Macro Value If _type ; call Read_Memory ; call routine to read 65C02 memory mov al,ds:[di] ; Read the memory location or al,Value ; Set the requested bit call Write_Memory ; call routine to write 65C02 memory Else or Byte Ptr ds:[di],Value Endif Endm Private Macro Name,Size Name Equ This Byte Private_Stack ; Define private stack header Db Size Dup (?) ; Define the actual stack data area Endm Row Macro String Calc String,%_count _count = _count + 1 Endm Calc Macro String,Cnt _x&Cnt = 0 Irpc c, _x&Cnt = _x&Cnt Shl 1 Ifidn ,<*> _x&Cnt = _x&Cnt + 1 Endif Endm Endm Define Macro _number = 0 Rept _count Data %_number _number = _number + 1 Endm _count = 0 Endm Data Macro Cnt Db _x&Cnt Endm .List