Foreword
In the previous post I have implemented arithmetic instructions and flag modification instructions.
In this post I will be implementing Bit logic instruction and bit shifting instructions.
The source code for this post can be found on Github, with the following tag:
https://github.com/ovalcode/c64_flutter/releases/tag/c64_flutter_part_6
Enjoy!
Logic Operators
Let us start with the logic operators:
/*
AND (bitwise AND with accumulator)
Affects Flags: N Z
MODE SYNTAX HEX LEN TIM
Immediate AND #$44 $29 2 2
Zero Page AND $44 $25 2 3
Zero Page,X AND $44,X $35 2 4
Absolute AND $4400 $2D 3 4
Absolute,X AND $4400,X $3D 3 4+
Absolute,Y AND $4400,Y $39 3 4+
Indirect,X AND ($44,X) $21 2 6
Indirect,Y AND ($44),Y $31 2 5+
+ add 1 cycle if page boundary crossed
*/
case 0x29:
_a = _a & arg0;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x25:
case 0x35:
case 0x2D:
case 0x3D:
case 0x39:
case 0x21:
case 0x31:
_a = _a & memory.getMem(resolvedAddress);
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
/*
EOR (bitwise Exclusive OR)
Affects Flags: N Z
MODE SYNTAX HEX LEN TIM
Immediate EOR #$44 $49 2 2
Zero Page EOR $44 $45 2 3
Zero Page,X EOR $44,X $55 2 4
Absolute EOR $4400 $4D 3 4
Absolute,X EOR $4400,X $5D 3 4+
Absolute,Y EOR $4400,Y $59 3 4+
Indirect,X EOR ($44,X) $41 2 6
Indirect,Y EOR ($44),Y $51 2 5+
+ add 1 cycle if page boundary crossed
*/
case 0x49:
_a = _a ^ arg0;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x45:
case 0x55:
case 0x4D:
case 0x5D:
case 0x59:
case 0x41:
case 0x51:
_a = _a ^ memory.getMem(resolvedAddress);
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
/*
ORA (bitwise OR with Accumulator)
Affects Flags: N Z
MODE SYNTAX HEX LEN TIM
Immediate ORA #$44 $09 2 2
Zero Page ORA $44 $05 2 3
Zero Page,X ORA $44,X $15 2 4
Absolute ORA $4400 $0D 3 4
Absolute,X ORA $4400,X $1D 3 4+
Absolute,Y ORA $4400,Y $19 3 4+
Indirect,X ORA ($44,X) $01 2 6
Indirect,Y ORA ($44),Y $11 2 5+
+ add 1 cycle if page boundary crossed
*/
case 0x09:
_a = _a | arg0;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x05:
case 0x15:
case 0x0D:
case 0x1D:
case 0x19:
case 0x01:
case 0x11:
_a = _a | memory.getMem(resolvedAddress);
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
Everything is straightforward here, and nothing to comment on.Shifting operators
/*
ASL (Arithmetic Shift Left)
Affects Flags: N Z C
MODE SYNTAX HEX LEN TIM
Accumulator ASL A $0A 1 2
Zero Page ASL $44 $06 2 5
Zero Page,X ASL $44,X $16 2 6
Absolute ASL $4400 $0E 3 6
Absolute,X ASL $4400,X $1E 3 7
ASL shifts all bits left one position. 0 is shifted into bit 0 and the original bit 7 is shifted into the Carry.
*/
case 0x0A:
_a = _a << 1;
_c = ((_a & 0x100) != 0) ? 1 : 0;
_a = _a & 0xff;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x06:
case 0x16:
case 0x0E:
case 0x1E:
int temp = memory.getMem(resolvedAddress) << 1;
_c = ((temp & 0x100) != 0) ? 1 : 0;
temp = temp & 0xff;
_n = ((temp & 0x80) != 0) ? 1 : 0;
_z = (temp == 0) ? 1 : 0;
memory.setMem(temp, resolvedAddress);
/*
LSR (Logical Shift Right)
Affects Flags: N Z C
MODE SYNTAX HEX LEN TIM
Accumulator LSR A $4A 1 2
Zero Page LSR $44 $46 2 5
Zero Page,X LSR $44,X $56 2 6
Absolute LSR $4400 $4E 3 6
Absolute,X LSR $4400,X $5E 3 7
LSR shifts all bits right one position. 0 is shifted into bit 7 and the original bit 0 is shifted into the Carry.
*/
case 0x4A:
_c = _a & 1;
_a = _a >> 1;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x46:
case 0x56:
case 0x4E:
case 0x5E:
int temp = memory.getMem(resolvedAddress);
_c = temp & 1;
temp = temp >> 1;
_n = ((temp & 0x80) != 0) ? 1 : 0;
_z = (temp == 0) ? 1 : 0;
memory.setMem(temp, resolvedAddress);
/*
ROL (ROtate Left)
Affects Flags: N Z C
MODE SYNTAX HEX LEN TIM
Accumulator ROL A $2A 1 2
Zero Page ROL $44 $26 2 5
Zero Page,X ROL $44,X $36 2 6
Absolute ROL $4400 $2E 3 6
Absolute,X ROL $4400,X $3E 3 7
ROL shifts all bits left one position. The Carry is shifted into bit 0 and the original bit 7 is shifted into the Carry.
*/
case 0x2A:
_a = (_a << 1) | _c;
_c = ((_a & 0x100) != 0) ? 1 : 0;
_a = _a & 0xff;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x26:
case 0x36:
case 0x2E:
case 0x3E:
int temp = (memory.getMem(resolvedAddress) << 1) | _c;
_c = ((temp & 0x100) != 0) ? 1 : 0;
temp = temp & 0xff;
_n = ((temp & 0x80) != 0) ? 1 : 0;
_z = (temp == 0) ? 1 : 0;
memory.setMem(temp, resolvedAddress);
/*
ROR (ROtate Right)
Affects Flags: N Z C
MODE SYNTAX HEX LEN TIM
Accumulator ROR A $6A 1 2
Zero Page ROR $44 $66 2 5
Zero Page,X ROR $44,X $76 2 6
Absolute ROR $4400 $6E 3 6
Absolute,X ROR $4400,X $7E 3 7
ROR shifts all bits right one position. The Carry is shifted into bit 7 and the original bit 0 is shifted into the Carry.
*/
case 0x6A:
_a = _a | (_c << 8);
_c = _a & 1;
_a = _a >> 1;
_n = ((_a & 0x80) != 0) ? 1 : 0;
_z = (_a == 0) ? 1 : 0;
case 0x66:
case 0x76:
case 0x6E:
case 0x7E:
int temp = memory.getMem(resolvedAddress) | (_c << 8);
_c = temp & 1;
temp = temp >> 1;
_n = ((temp & 0x80) != 0) ? 1 : 0;
_z = (temp == 0) ? 1 : 0;
memory.setMem(temp, resolvedAddress);
As you can see, with the shifting instructions, either the contents of the accumulator is shifted, or the contents of a memory location is shifted. Obviously, when shifting the contents of a memory location, more steps are involved.The Test Program
/*asl C <- [76543210] <- 0 lsr 0 -> [76543210] -> C rol C <- [76543210] <- C ror C -> [76543210] -> C*/ LDA #01 A9 01 ORA #02 09 02 EOR #06 49 06 LSR A 4A ROL A 2A SEC 38 AND #$fe 29 fe ROR A 6a LDA #3 a9 03 STA $60 85 60 CLC 18 LSR $60 46 60 ROL $60 26 60 ROR $60 66 60I have added a comment on the top as a quick reference to how the different shifting instructions work, just making it easier to follow the program.