File: M6507Lo.cxx

package info (click to toggle)
stella 0.7-2
  • links: PTS
  • area: non-free
  • in suites: hamm, slink
  • size: 864 kB
  • ctags: 1,158
  • sloc: cpp: 6,615; ansic: 492; makefile: 224; asm: 31
file content (150 lines) | stat: -rw-r--r-- 5,016 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//============================================================================
//
//    SSSS    tt          lll  lll              
//   SS  SS   tt           ll   ll                
//   SS     tttttt  eeee   ll   ll   aaaa    "An Atari 2600 VCS Emulator"
//    SSSS    tt   ee  ee  ll   ll      aa      
//       SS   tt   eeeeee  ll   ll   aaaaa   Copyright (c) 1995,1996,1997
//   SS  SS   tt   ee      ll   ll  aa  aa         Bradford W. Mott
//    SSSS     ttt  eeeee llll llll  aaaaa    
//
//============================================================================

/**
  This class emulates a 6507 microprocessor, however, the memory
  accesses and cycle counts it generates are only valid at the
  instruction level.  For better compatibility it's neccessary to
  increment cycles counts at the sub-instruction level and issues
  "false" reads for some instructions (such as Indirect,X addressing
  when it crosses a page boundary).

  @author  Bradford W. Mott
  @version $Id: M6507Lo.cxx,v 1.1 1997/05/17 19:04:13 bwmott Exp $
*/

#include <assert.h>
#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
#include "M6507Lo.hxx"

//============================================================================
// Answers true iff the two addresses are not on the same page
//============================================================================
static inline bool notSamePage(uWord addr1, uWord addr2)
{
  return (addr1 ^ addr2) & 0xff00;
}

//============================================================================
// Default constructor
//============================================================================
M6507Low::M6507Low(System& system)
    : M6507(system)
{
}

//============================================================================
// Destructor
//============================================================================
M6507Low::~M6507Low()
{
}

//============================================================================
// Answer the byte at the given address (only lower 8-bits used)
//============================================================================
inline uWord M6507Low::peek(uWord addr)
{
  return mySystem.peek(addr);
}

//============================================================================
// Answer the uByte at the given address that should be part of
// an instruction we're trying to execute
//============================================================================
inline uWord M6507Low::iPeek(uWord addr)
{
#ifdef M6507_FAST_ACCESS
  return mySystem.fastPeek(addr);
#else
  return mySystem.peek(addr);
#endif
}

//============================================================================
// Answer the uWord at the given address
//============================================================================
inline uWord M6507Low::iDPeek(uWord addr)
{
#ifdef M6507_FAST_ACCESS
  return mySystem.fastDPeek(addr);
#else
  uWord value = mySystem.peek(addr++);
  return value | (((uWord)mySystem.peek(addr)) << 8);
#endif
}

//============================================================================
// Write given byte to the given address 
//============================================================================
inline void M6507Low::poke(uWord addr, uByte value)
{
  mySystem.poke(addr,value);
}

//============================================================================
// Execute instructions until at least the given number of
// cycles have passed or execution is halted by someone
//============================================================================
void M6507Low::execute(uLong numberOfCycles)
{
  uLong stop = myCycles + numberOfCycles;
  myHaltExecution = false;

  // Loop until execution is halted or we're finished
  while(!myHaltExecution && (myCycles < stop))
  {
    uWord operandAddress = 0;

#ifdef DEBUG
    debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif

    // Fetch instruction at the program counter
    IR = iPeek(PC++);

    // Update cycles
    myCycles += ourInstructionCycleTable[IR];

#ifdef DEBUG
    debugStream << "IR=" << hex << setw(2) << (int)IR << " ";
    debugStream << "<" << ourAddressingModeTable[IR] << " ";
#endif

    // Call the code to execute the instruction
    switch(IR)
    {
      // The code to simulate the 6507 instructions is 
      // generated by an M4 macro file
      #include "M6507.ins"

      default:
        invalidInstruction();
    } 

#ifdef DEBUG
    debugStream << hex << setw(4) << operandAddress << " ";
    debugStream << setw(4) << ourInstructionMnemonicTable[IR];
    debugStream << "> ";
    debugStream << "A=" << ::hex << setw(2) << (int)A << " ";
    debugStream << "X=" << ::hex << setw(2) << (int)X << " ";
    debugStream << "Y=" << ::hex << setw(2) << (int)Y << " ";
    debugStream << "PS=" << ::hex << setw(2) << (int)PS() << " ";
    debugStream << "SP=" << ::hex << setw(2) << (int)SP << " ";
    debugStream << "Cyc=" << ::dec << cycles();
    debugStream << endl;
#endif
  }
}