My 6502 Emulation portion of my 2600 emulator continues with a look at increment and decrement operations.
Moving
memory around is often very important, but right now we are doing it one byte
at a time. The index operations allow for looping through blocks of memory but
that requires the ability to create a loop. Before we can do that, we need to
be able to increment or decrement the index registers. Since increasing or
decreasing an index register by one is an exceedingly common operation, there
are commands specifically for doing this. Strangely enough there is not a way
of incrementing or decrementing the accumulator by one, though there is
addition and subtraction commands which we will be covering later.
The INX and
INY commands are used to increment the X or Y registers. When the register has
the value of 255 incrementing it wraps the value making it become 0. DEX and
DEY are used for decrementing the X or Y registers. When they are 0,
decrementing wraps the register making them 255.
While there
is no commands for incrementing or decrementing the accumulator, there is an
INC and a DEC command that apply to memory at an indicated address. This is
handy to have as it lets you modify a variable in memory without needing to
load it into a register.
The most
common use of increment and decrement operations, as mentioned above, is
looping. This requires branching instructions at a minimum, so we will take a
look at branching instructions next.
INC – INCrement memory
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Zero Page
|
230
|
$E6
|
2
|
5
|
Zero Page, X
|
246
|
$F6
|
2
|
6
|
Absolute
|
238
|
$EE
|
3
|
6
|
Absolute,X
|
254
|
$FE
|
3
|
7
|
Flags affected: NZ
Usage: Incrementing a byte in memory
Test Code:
; INC, INX, INY tests
LDX
#$10
LDY
#255
INC
$50
INC
$41,X
INC
$110
INC
$101,X
INX
INY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=2, M51=3, M110=4, M111=5,
X=17, Y=0, Z=1
Implementation:
// zero page
val addressToInc = mem.read(state.ip+1)
mem.write(addressToInc,
setNumberFlags((mem.read(addressToInc) + 1) and 255))
// zero page,X
val addressToInc = mem.read(state.ip+1) +
state.x
mem.write(addressToInc,
setNumberFlags((mem.read(addressToInc) + 1) and 255))
// absolute
val addressToInc =
findAbsoluteAddress(state.ip)
mem.write(addressToInc,
setNumberFlags((mem.read(addressToInc) + 1) and 255))
// absolute,X
val addressToInc =
findAbsoluteAddress(state.ip) + state.x
mem.write(addressToInc,
setNumberFlags((mem.read(addressToInc) + 1) and 255))
INX – INcrement X register
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Implied
|
232
|
$E8
|
1
|
2
|
Flags affected: NZ
Usage: Adding one to value in x register. Useful for
looping.
Test Code:
; INC, INX, INY tests
LDX
#$10
LDY
#255
INC
$50
INC
$41,X
INC
$110
INC
$101,X
INX
INY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=2, M51=3, M110=4, M111=5,
X=17, Y=0, Z=1
Implementation:
state.x =
setNumberFlags((state.x+1) and 255)
INY – INcrement Y register
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Implied
|
200
|
$C8
|
1
|
2
|
Flags affected: NZ
Cycle Notes: remove if none
Usage: Adding one to value in y register. Useful for
looping.
Test Code:
; INC, INX, INY tests
LDX
#$10
LDY
#255
INC
$50
INC
$41,X
INC
$110
INC
$101,X
INX
INY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=2, M51=3, M110=4, M111=5,
X=17, Y=0, Z=1
Implementation:
state.y =
setNumberFlags((state.y+1) and 255)
DEC – DECrement memory
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Zero Page
|
198
|
$C6
|
2
|
5
|
Zero Page, X
|
214
|
$D6
|
2
|
6
|
Absolute
|
206
|
$CE
|
3
|
6
|
Absolute, X
|
222
|
$DE
|
3
|
7
|
Flags affected: NZ
Cycle Notes: remove if none
Usage: When you would use this command
Test Code:
; DEC, DEX, DEY tests
LDX
#$10
LDY
#0
DEC
$50
DEC
$41,X
DEC
$110
DEC
$101,X
DEX
DEY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=0, M51=1, M110=2, M111=3,
X=15, Y=255, N=1
Implementation:
// zero page
val addressToDec = mem.read(state.ip+1)
mem.write(addressToDec,
setNumberFlags((mem.read(addressToDec) - 1) and 255))
// zero page,X
val addressToDec = mem.read(state.ip+1) +
state.x
mem.write(addressToDec,
setNumberFlags((mem.read(addressToDec) - 1) and 255))
// absolute
val addressToDec =
findAbsoluteAddress(state.ip)
mem.write(addressToDec,
setNumberFlags((mem.read(addressToDec) - 1) and 255))
// absolute,X
val addressToDec = findAbsoluteAddress(state.ip)
+ state.x
mem.write(addressToDec,
setNumberFlags((mem.read(addressToDec) - 1) and 255))
DEX – DEcrement X register
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Implied
|
202
|
$CA
|
1
|
2
|
Flags affected: NZ
Usage: Decreasing X register by 1 is usually done for
countdown loops
Test Code:
; DEC, DEX, DEY tests
LDX
#$10
LDY
#0
DEC
$50
DEC
$41,X
DEC
$110
DEC
$101,X
DEX
DEY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=0, M51=1, M110=2, M111=3,
X=15, Y=255, N=1
Implementation:
state.x =
setNumberFlags((state.x-1) and 255)
DEY – DEcrement Y register
Address Mode
|
Decimal OPCode
|
Hexadecimal OpCode
|
Size
|
Cycles
|
Implied
|
136
|
$88
|
1
|
2
|
Flags affected: NZ
Usage: Decreasing Y register by 1 is usually done for
countdown loops
Test Code:
; DEC, DEX, DEY tests
LDX
#$10
LDY
#0
DEC
$50
DEC
$41,X
DEC
$110
DEC
$101,X
DEX
DEY
BRK
.ORG $50
.BYTE 1 2
.ORG $110
.BYTE 3 4
; expect M50=0, M51=1, M110=2, M111=3,
X=15, Y=255, N=1
Implementation:
state.y =
setNumberFlags((state.y-1) and 255)
No comments:
Post a Comment