mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 15:29:46 +00:00
268 lines
8.0 KiB
PHP
268 lines
8.0 KiB
PHP
; smc.mac
|
|
; ca65 Macro-Pack for Self Modifying Code (SMC)
|
|
;
|
|
; (c) Christian Krüger, latest change: 17-Jul-2016
|
|
;
|
|
; This software is provided 'as-is', without any expressed or implied
|
|
; warranty. In no event will the authors be held liable for any damages
|
|
; arising from the use of this software.
|
|
;
|
|
; Permission is granted to anyone to use this software for any purpose,
|
|
; including commercial applications, and to alter it and redistribute it
|
|
; freely, subject to the following restrictions:
|
|
;
|
|
; 1. The origin of this software must not be misrepresented; you must not
|
|
; claim that you wrote the original software. If you use this software
|
|
; in a product, an acknowledgment in the product documentation would be
|
|
; appreciated but is not required.
|
|
; 2. Altered source versions must be plainly marked as such, and must not
|
|
; be misrepresented as being the original software.
|
|
; 3. This notice may not be removed or altered from any source
|
|
; distribution.
|
|
;
|
|
|
|
.define _SMCDesignator .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))
|
|
.define _SMCAlias .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))
|
|
.define SMC_AbsAdr $FADE
|
|
.define SMC_ZpAdr $00
|
|
.define SMC_Opcode nop
|
|
.define SMC_Value $42
|
|
|
|
.macro SMC_OperateOnValue opcode, label
|
|
opcode _SMCDesignator+1
|
|
.endmacro
|
|
|
|
.macro SMC_OperateOnLowByte opcode, label
|
|
SMC_OperateOnValue opcode, label
|
|
.endmacro
|
|
|
|
.macro SMC_OperateOnHighByte opcode, label
|
|
opcode _SMCDesignator + 2
|
|
.endmacro
|
|
|
|
.macro SMC_Import alias
|
|
.import _SMCAlias
|
|
.endmacro
|
|
|
|
.macro SMC_Export alias, label
|
|
.export _SMCAlias := _SMCDesignator
|
|
.endmacro
|
|
|
|
.macro SMC label, statement
|
|
_SMCDesignator: statement
|
|
.endmacro
|
|
|
|
.macro SMC_TransferOpcode label, opcode, register
|
|
.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
|
|
lda #opcode
|
|
sta _SMCDesignator
|
|
.elseif .match ({register}, x)
|
|
ldx #opcode
|
|
stx _SMCDesignator
|
|
.elseif .match ({register}, y)
|
|
ldy #opcode
|
|
sty _SMCDesignator
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_TransferOpcode'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_LoadOpcode label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
lda _SMCDesignator
|
|
.elseif .match ({register}, x)
|
|
ldx _SMCDesignator
|
|
.elseif .match ({register}, y)
|
|
ldy _SMCDesignator
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_LoadOpcode'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_StoreOpcode label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
sta _SMCDesignator
|
|
.elseif .match ({register}, x)
|
|
stx _SMCDesignator
|
|
.elseif .match ({register}, y)
|
|
sty _SMCDesignator
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_StoreOpcode'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_ChangeBranch label, destination, register
|
|
.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
|
|
lda #(<(destination - _SMCDesignator -2))
|
|
sta _SMCDesignator+1
|
|
.elseif .match ({register}, x)
|
|
ldx #(<(destination - _SMCDesignator - 2))
|
|
stx _SMCDesignator+1
|
|
.elseif .match ({register}, y)
|
|
ldy #(<(destination - _SMCDesignator - 2))
|
|
sty _SMCDesignator+1
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_ChangeBranch'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_TransferValue label, value, register
|
|
.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
|
|
lda value
|
|
sta _SMCDesignator+1
|
|
.elseif .match ({register}, x)
|
|
ldx value
|
|
stx _SMCDesignator+1
|
|
.elseif .match ({register}, y)
|
|
ldy value
|
|
sty _SMCDesignator+1
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_TransferValue'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_LoadValue label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
lda _SMCDesignator+1
|
|
.elseif .match ({register}, x)
|
|
ldx _SMCDesignator+1
|
|
.elseif .match ({register}, y)
|
|
ldy _SMCDesignator+1
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_LoadValue'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_StoreValue label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
sta _SMCDesignator+1
|
|
.elseif .match ({register}, x)
|
|
stx _SMCDesignator+1
|
|
.elseif .match ({register}, y)
|
|
sty _SMCDesignator+1
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_StoreValue'"
|
|
.endif
|
|
.endmacro
|
|
|
|
|
|
.macro SMC_TransferLowByte label, value, register
|
|
SMC_TransferValue label, value, register
|
|
.endmacro
|
|
|
|
.macro SMC_LoadLowByte label, register
|
|
SMC_LoadValue label, register
|
|
.endmacro
|
|
|
|
.macro SMC_StoreLowByte label, register
|
|
SMC_StoreValue label, register
|
|
.endmacro
|
|
|
|
.macro SMC_TransferHighByte label, value, register
|
|
.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
|
|
lda value
|
|
sta _SMCDesignator+2
|
|
.elseif .match ({register}, x)
|
|
ldx value
|
|
stx _SMCDesignator+2
|
|
.elseif .match ({register}, y)
|
|
ldy value
|
|
sty _SMCDesignator+2
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_TransferHighByte'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_LoadHighByte label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
lda _SMCDesignator+2
|
|
.elseif .match ({register}, x)
|
|
ldx _SMCDesignator+2
|
|
.elseif .match ({register}, y)
|
|
ldy _SMCDesignator+2
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_LoadHighByte'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_StoreHighByte label, register
|
|
.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
|
|
sta _SMCDesignator+2
|
|
.elseif .match ({register}, x)
|
|
stx _SMCDesignator+2
|
|
.elseif .match ({register}, y)
|
|
sty _SMCDesignator+2
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_StoreHighByte'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_TransferAddressSingle label, address, register
|
|
.if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )
|
|
.if (.match (.left (1, {address}), #))
|
|
; immediate mode
|
|
lda #<(.right (.tcount ({address})-1, {address}))
|
|
sta _SMCDesignator+1
|
|
lda #>(.right (.tcount ({address})-1, {address}))
|
|
sta _SMCDesignator+2
|
|
.else
|
|
; assume absolute or zero page
|
|
lda address
|
|
sta _SMCDesignator+1
|
|
lda 1+(address)
|
|
sta _SMCDesignator+2
|
|
.endif
|
|
.elseif .match ((register), x)
|
|
.if (.match (.left (1, {address}), #))
|
|
; immediate mode
|
|
ldx #<(.right (.tcount ({address})-1, {address}))
|
|
stx _SMCDesignator+1
|
|
ldx #>(.right (.tcount ({address})-1, {address}))
|
|
stx _SMCDesignator+2
|
|
.else
|
|
; assume absolute or zero page
|
|
ldx address
|
|
stx _SMCDesignator+1
|
|
ldx 1+(address)
|
|
stx _SMCDesignator+2
|
|
.endif
|
|
.elseif .match ((register), y)
|
|
.if (.match (.left (1, {address}), #))
|
|
; immediate mode
|
|
ldy #<(.right (.tcount ({address})-1, {address}))
|
|
sty _SMCDesignator+1
|
|
ldy #>(.right (.tcount ({address})-1, {address}))
|
|
sty _SMCDesignator+2
|
|
.else
|
|
; assume absolute or zero page
|
|
ldy address
|
|
sty _SMCDesignator+1
|
|
ldy 1+(address)
|
|
sty _SMCDesignator+2
|
|
.endif
|
|
.else
|
|
.error "Invalid usage of macro 'SMC_TransferAddressSingle'"
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_TransferAddress label, address
|
|
.if (.match (.left (1, {address}), #))
|
|
; immediate mode
|
|
lda #<(.right (.tcount ({address})-1, {address}))
|
|
sta _SMCDesignator+1
|
|
ldx #>(.right (.tcount ({address})-1, {address}))
|
|
stx _SMCDesignator+2
|
|
.else
|
|
; assume absolute or zero page
|
|
lda {address}
|
|
sta _SMCDesignator+1
|
|
ldx 1+{address}
|
|
stx _SMCDesignator)+2
|
|
.endif
|
|
.endmacro
|
|
|
|
.macro SMC_StoreAddress label
|
|
sta _SMCDesignator+1
|
|
stx _SMCDesignator+2
|
|
.endmacro
|