Steve2/A2iOS/src/cpu/instructions/6502_instr_branch.h

292 lines
7.7 KiB
C

//
// main.c
// 6502
//
// Created by Tamas Rudnai on 7/14/19.
// Copyright © 2019, 2020 Tamas Rudnai. All rights reserved.
//
// This file is part of Steve ][ -- The Apple ][ Emulator.
//
// Steve ][ is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Steve ][ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Steve ][. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef __6502_INSTR_BRANCH_H__
#define __6502_INSTR_BRANCH_H__
INLINE void BRA( int8_t reladdr ) {
m6502.PC += reladdr;
//#ifdef CLK_ABSOLUTE_PRECISE
uint8_t pg = m6502.PC >> 8;
m6502.clkfrm += m6502.PC >> 8 == pg ? 1 : 2;
// if ( m6502.PC >> 8 != pg ) {
// m6502.clkfrm += 1;
// }
//#else
// m6502.clktime++;
//#endif
#ifdef DEBUG
if ( reladdr == -2 ) {
dbgPrintf2("Infinite Loop at %04X!\n", m6502.PC);
}
#endif
dbgPrintf("BRA %04X ", m6502.PC);
}
/**
BCC Branch on Carry Clear
branch on C = 0 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BCC oper 90 2 2**
**/
INLINE void BCC( int8_t reladdr ) {
dbgPrintf("BCC ");
disPrintf(disassembly.inst, "BCC");
if ( ! m6502.C ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BCS Branch on Carry Set
branch on C = 1 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BCS oper B0 2 2**
**/
INLINE void BCS( int8_t reladdr ) {
dbgPrintf("BCS ");
disPrintf(disassembly.inst, "BCS");
if ( m6502.C ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BNE Branch on Result not Zero
branch on Z = 0 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BNE oper D0 2 2**
**/
INLINE void BNE( int8_t reladdr ) {
dbgPrintf("BNE ");
disPrintf(disassembly.inst, "BNE");
if ( ! m6502.Z ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BEQ Branch on Result Zero
branch on Z = 1 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BEQ oper F0 2 2**
**/
INLINE void BEQ( int8_t reladdr ) {
dbgPrintf("BEQ ");
disPrintf(disassembly.inst, "BEQ");
if ( m6502.Z ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BPL Branch on Result Plus
branch on N = 0 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BPL oper 10 2 2**
**/
INLINE void BPL( int8_t reladdr ) {
dbgPrintf("BPL ");
disPrintf(disassembly.inst, "BPL");
if ( ! m6502.N ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BMI Branch on Result Minus
branch on N = 1 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BMI oper 30 2 2**
**/
INLINE void BMI( int8_t reladdr ) {
dbgPrintf("BMI ");
disPrintf(disassembly.inst, "BMI");
if ( m6502.N ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BVC Branch on Overflow Clear
branch on V = 0 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BVC oper 50 2 2**
**/
INLINE void BVC( int8_t reladdr ) {
dbgPrintf("BVC ");
disPrintf(disassembly.inst, "BVC");
if ( ! m6502.V ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BVS Branch on Overflow Set
branch on V = 1 N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
relative BVC oper 70 2 2**
**/
INLINE void BVS( int8_t reladdr ) {
dbgPrintf("BVS ");
disPrintf(disassembly.inst, "BVS");
if ( m6502.V ) {
BRA( reladdr );
}
else {
dbgPrintf("-no-");
}
}
/**
BBR BBS - Branch on Bit Reset or Set
BBR and BBS test the specified zero page location and branch if the specified bit is clear (BBR) or set (BBS).
Note that as with TRB, the term reset in BBR is used to mean clear.
On the 6502 and 65C02, bit 7 is typically the most convenient bit to use for I/O and software flags because
it can be tested by several instructions, such as BIT and LDA. BBR and BBS can test any of the 8 bits without
affecting any flags or using any registers. Unlike other branch instructions, BBR and BBS always take the same
number of cycles (five) whether the branch is taken or not. It is often useful to test bit 0, for example, to test
whether a byte is even or odd. However, the usefulness of BBR and BBS is somewhat limited for a couple of reasons.
First, there is only a single addressing mode for these instructions -- no indexing by X or Y, for instance.
Second, they are restricted to zero page locations. For software flags this may be just fine, but it may not be very
convenient (or cost effective) to add any additional address decoding hardware that may be necessary to
map I/O locations to the zero page.
The addressing mode is a combination of zero page addressing and relative addressing -- really just a juxtaposition of the two.
The bit to test is typically specified as part of the instruction name rather than the operand, i.e.
Flags affected: none
OP LEN CYC MODE FLAGS SYNTAX
-- --- --- ---- ----- ------
0F 3 5 zp,rel ........ BBR0 $12,LABEL
1F 3 5 zp,rel ........ BBR1 $12,LABEL
2F 3 5 zp,rel ........ BBR2 $12,LABEL
3F 3 5 zp,rel ........ BBR3 $12,LABEL
4F 3 5 zp,rel ........ BBR4 $12,LABEL
5F 3 5 zp,rel ........ BBR5 $12,LABEL
6F 3 5 zp,rel ........ BBR6 $12,LABEL
7F 3 5 zp,rel ........ BBR7 $12,LABEL
8F 3 5 zp,rel ........ BBS0 $12,LABEL
9F 3 5 zp,rel ........ BBS1 $12,LABEL
AF 3 5 zp,rel ........ BBS2 $12,LABEL
BF 3 5 zp,rel ........ BBS3 $12,LABEL
CF 3 5 zp,rel ........ BBS4 $12,LABEL
DF 3 5 zp,rel ........ BBS5 $12,LABEL
EF 3 5 zp,rel ........ BBS6 $12,LABEL
FF 3 5 zp,rel ........ BBS7 $12,LABEL
**/
#define BBR(n) INLINE void BBR##n( uint8_t src, int8_t reladdr ) { \
dbgPrintf("BBR"#n" "); \
disPrintf(disassembly.inst, "BBR"#n); \
if ( ! (src & (1 << n) ) ) { \
BRA( reladdr ); \
} \
}
BBR(0)
BBR(1)
BBR(2)
BBR(3)
BBR(4)
BBR(5)
BBR(6)
BBR(7)
#define BBS(n) INLINE void BBS##n( uint8_t src, int8_t reladdr ) { \
dbgPrintf("BBS"#n" "); \
disPrintf(disassembly.inst, "BBS"#n); \
if ( (src & (1 << n) ) ) { \
BRA( reladdr ); \
} \
}
BBS(0)
BBS(1)
BBS(2)
BBS(3)
BBS(4)
BBS(5)
BBS(6)
BBS(7)
#endif // __6502_INSTR_BRANCH_H__