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.