123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816 |
- // z80compiler.cpp : Defines the entry point for the console application.
- //
- #include <stdarg.h> // For va_start, etc.
- #include <regex>
- #include <string>
- #include <fstream>
- #include <functional>
- using namespace std;
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- #define BITFLAG(n) (1 << n)
- #define F BITFLAG(0)
- #define A BITFLAG(1)
- #define AF (A | F)
- #define C BITFLAG(2)
- #define B BITFLAG(3)
- #define BC (B | C)
- #define E BITFLAG(4)
- #define D BITFLAG(5)
- #define DE (D | E)
- #define L BITFLAG(6)
- #define H BITFLAG(7)
- #define HL (H | L)
- #define IY BITFLAG(8)
- #define IX BITFLAG(9)
- #define R BITFLAG(10)
- #define SP BITFLAG(11)
- #define CARRY BITFLAG(12)
- #define ZERO BITFLAG(13)
- #define SIGN BITFLAG(14)
- #define HFLAG BITFLAG(15)
- #define OVERFLOWFLAG BITFLAG(16)
- #define NFLAG BITFLAG(17)
- #define FLAGS (CARRY|ZERO|SIGN|HFLAG|OVERFLOWFLAG|NFLAG)
- class C6502Translator
- {
- public:
- C6502Translator( const string& oZ80Code )
- : m_oZ80Code( oZ80Code )
- {
- Replace(m_oZ80Code, "\r", "");
- };
- ~C6502Translator() {};
- string Translate();
- private:
- void Replace(string& str, const string& from, const string& to);
- bool GetNextLine(string& oLine);
- bool ParsingOK( const string& oSource, const char *szPattern, const char* szArgument1, const char* szArgument2 );
- bool ParsingOK( const string& oSource, const char *szPattern, const char* szArgument1 );
- bool FixArg( char* szArgument );
- int CountParameters( string pattern );
- string string_format(const string fmt, ...);
- void MakeParameterALabel( char *szArgument );
- void AddReferencedLabel( string oLabel );
- void AddDefinedLabel( string oLabel );
- string AddReferencedNotDefinedLabels();
- string m_oZ80Code;
- vector<string> m_oReferencedLabels;
- vector<string> m_oDefinedLabels;
- };
- void C6502Translator::AddReferencedLabel( string oLabel )
- {
- if ( !oLabel.empty() )
- {
- if ( oLabel.substr(0,1) == "(" && oLabel.substr(oLabel.size()-1, 1) == ")" )
- {
- oLabel = oLabel.substr( 1, oLabel.size() - 2 );
- }
- m_oReferencedLabels.push_back( oLabel );
- }
- }
- void C6502Translator::AddDefinedLabel( string oLabel )
- {
- if ( !oLabel.empty() )
- {
- if ( oLabel.substr(0,1) == "(" && oLabel.substr(oLabel.size() - 1, 1) == ")" )
- {
- oLabel = oLabel.substr( 1, oLabel.size() - 2 );
- }
- if ( oLabel.find( ':') != -1 )
- {
- oLabel = oLabel.substr(0, oLabel.find( ':') );
- }
- m_oDefinedLabels.push_back( oLabel );
- }
- }
- int CompareStrings( const string &pElem1, const string &pElem2 )
- {
- return pElem1.compare(pElem2);
- }
- string C6502Translator::AddReferencedNotDefinedLabels()
- {
- string oLabel;
- string oCode;
- string oStr;
- // sort arrays
- sort(m_oDefinedLabels.begin(), m_oDefinedLabels.end(), greater<string>());
- sort(m_oReferencedLabels.begin(), m_oReferencedLabels.end(), greater<string>());
- // remove duplicates from defined labels
- auto last_def = unique(m_oDefinedLabels.begin(), m_oDefinedLabels.end());
- m_oDefinedLabels.erase(last_def, m_oDefinedLabels.end());
- // remove duplicates from referenced labels
- auto last_ref = unique(m_oReferencedLabels.begin(), m_oReferencedLabels.end());
- m_oReferencedLabels.erase(last_ref, m_oReferencedLabels.end());
- for ( size_t iPos = 0; iPos < m_oReferencedLabels.size(); iPos++ )
- {
- oLabel = m_oReferencedLabels[iPos];
- if ( find(m_oDefinedLabels.begin(), m_oDefinedLabels.end(), oLabel) != m_oDefinedLabels.end())
- {
- char* pEnd = NULL;
- oStr = oLabel.substr(1);
- //oStr = oLabel;
- if ( strtol( oStr.c_str(), &pEnd, 16 ) != 0 && !*pEnd )
- {
- oCode += oLabel + " equ $" + oStr + "\n";
- }
- else
- {
- oCode += oLabel + " equ " + oStr + "\n";
- }
- }
- }
- return oCode;
- }
- void C6502Translator::Replace(string& str, const string& from, const string& to) {
- if (from.empty())
- return;
- for (size_t pos = 0; ; pos += to.length()) {
- // Locate the substring to replace
- pos = str.find(from, pos);
- if (pos == string::npos) break;
- // Replace by erasing and inserting
- str.erase(pos, from.length());
- str.insert(pos, to);
- }
- }
- bool C6502Translator::GetNextLine( string& oLine )
- {
- int iPos = m_oZ80Code.find( "\n" );
- if ( iPos >= 0 )
- {
- oLine = m_oZ80Code.substr(0, iPos );
- m_oZ80Code = m_oZ80Code.substr( iPos + 1 );
- }
- else
- {
- oLine = m_oZ80Code;
- m_oZ80Code.clear();
- }
- return !oLine.empty() || !m_oZ80Code.empty();
- }
- int C6502Translator::CountParameters(string pattern)
- {
- return count(pattern.begin(), pattern.end(), '%' );
- }
- string C6502Translator::string_format(const string fmt, ...) {
- int size = ((int)fmt.size()) * 2 + 50; // Use a rubric appropriate for your code
- string str;
- va_list ap;
- while (1) { // Maximum two passes on a POSIX system...
- str.resize(size);
- va_start(ap, fmt);
- int n = vsnprintf((char *)str.data(), size, fmt.c_str(), ap);
- va_end(ap);
- if (n > -1 && n < size) { // Everything worked
- str.resize(n);
- return str;
- }
- if (n > -1) // Needed size returned
- size = n + 1; // For null char
- else
- size *= 2; // Guess at a larger size (OS specific)
- }
- return str;
- }
- bool C6502Translator::ParsingOK( const string& oSource, const char *szPattern, const char* szArgument1, const char* szArgument2 )
- {
- string oResult = string_format( szPattern, szArgument1, szArgument2 );
- return oSource == oResult;
- }
- bool C6502Translator::ParsingOK( const string& oSource, const char *szPattern, const char* szArgument1 )
- {
- string oResult = string_format( szPattern, szArgument1 );
- return oSource == oResult;
- }
- bool C6502Translator::FixArg( char* szArgument )
- {
- char *p=strchr(szArgument,')');
- if (!p) p=strchr(szArgument,',');
- if (p) *p = '\0';
- return true;
- }
- void C6502Translator::MakeParameterALabel( char *szArgument )
- {
- string oParameter = string(szArgument);
- char *szEnd = NULL;
- if ( !oParameter.empty()
- && (oParameter[0] != 'L')
- && (oParameter[0] != '(')
- && strtol(szArgument, &szEnd, 16) != 0L
- && *szEnd == 0)
- {
- oParameter.insert(0, "L");
- }
- else
- {
- //oParameter = '$' + oParameter;
- }
- strncpy( szArgument, oParameter.c_str(), oParameter.size());
- }
- #define FLAG_MAKE_1ST_PARAM_A_LABEL 1
- struct
- {
- const char *szPattern;
- const char *sz6502Code;
- int iRead;
- int iWrite;
- int iFlag;
- } g_oCodePatterns[] =
- {
- { "LD C,D", "lda z80_d|sta z80_c", D, C },
- { "LD C,L", "lda z80_l|sta z80_c", L, C },
- { "LD L,C", "lda z80_c|sta z80_l", C, L },
- { "LD A,A", "ora #$00 ; WHY?", A, A },
- { "LD H,A", "sta z80_h", A, H },
- { "LD A,H", "lda z80_h", H, A },
- { "LD C,A", "sta z80_c", A, C },
- { "LD A,C", "lda z80_c", C, A },
- { "LD L,A", "sta z80_l", A, L },
- { "LD A,L", "lda z80_l", L, A },
- { "LD E,A", "sta z80_e", A, E },
- { "LD A,B", "lda z80_b", B, A },
- { "LD B,A", "sta z80_b", A, B },
- { "LD A,D", "lda z80_d", D, A },
- { "LD D,A", "sta z80_d", A, D },
- { "LD D,B", "lda z80_b|sta z80_d", B, D },
- { "LD H,B", "lda z80_b|sta z80_h", B, H },
- { "LD H,D", "lda z80_d|sta z80_h", D, H },
- { "LD H,E", "lda z80_e|sta z80_h", E, H },
- { "LD H,H", "lda z80_h|sta z80_h", H, H },
- { "LD H,L", "lda z80_l|sta z80_h", L, H },
- { "LD L,D", "lda z80_d|sta z80_l", D, L },
- { "LD L,E", "lda z80_e|sta z80_l", E, L },
- { "LD A,E", "lda z80_e", E, A },
- { "LD B,C", "lda z80_c|sta z80_b", C, B },
- { "LD B,H", "lda z80_h|sta z80_b", H, B },
- { "LD E,L", "lda z80_l|sta z80_e", L, E },
- { "LD E,C", "lda z80_c|sta z80_e", C, E },
- { "LD H,C", "lda z80_c|sta z80_h", C, H },
- { "LD D,L", "lda z80_l|sta z80_d", L, D },
- { "LD D,H", "lda z80_h|sta z80_d", H, D },
- { "LD A,R", "ld_a_r", R, A },
- { "LD SP,HL", "; TODO: LD SP,HL", HL, SP },
- { "LD SP,HL", "; TODO: LD SP,HL", HL, SP},
- { "LD A,$%02s", "lda #$%1", 0, A },
- { "LD B,$%02s", "lda #$%1|sta z80_b", 0, B },
- { "LD C,$%02s", "lda #$%1|sta z80_c", 0, C },
- { "LD D,$%02s", "lda #$%1|sta z80_d", 0, D },
- { "LD E,$%02s", "lda #$%1|sta z80_e", 0, E },
- { "LD L,$%02s", "lda #$%1|sta z80_l", 0, L },
- { "LD H,$%02s", "lda #$%1|sta z80_h", 0, H },
- { "LD IY,%s", "lda #<%1|sta z80_iy|lda #>%1|sta z80_iy+1", 0, IY, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD IX,%s", "lda #<%1|sta z80_ix|lda #>%1|sta z80_ix+1", 0, IX, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD BC,(%05s)", "lda %1|sta z80_c|lda %1+1|sta z80_b", 0, HL, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD BC,%s", "lda #<%1|sta z80_c|lda #>%1|sta z80_b", 0, BC, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD DE,(%05s)", "lda %1|sta z80_e|lda %1+1|sta z80_d", 0, HL, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD DE,%s", "lda #<%1|sta z80_e|lda #>%1|sta z80_d", 0, DE, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD HL,(%05s)", "lda %1|sta z80_l|lda %1+1|sta z80_h", 0, HL, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD HL,%s", "lda #<%1|sta z80_l|lda #>%1|sta z80_h", 0, HL, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD A,(IX+%02s)", "ldy #$%1|lda (z80_ix),y", IX, A },
- { "LD A,(IY+%02s)", "ldy #$%1|lda (z80_iy),y", IY, A },
- { "LD B,(IX+%02s)", "ldy #$%1|lda (z80_ix),y|sta z80_b", IX, B },
- { "LD C,(IX+%02s)", "ldy #$%1|lda (z80_ix),y|sta z80_c", IX, C },
- { "LD D,(IX+%02s)", "ldy #$%1|lda (z80_ix),y|sta z80_d", IX, D},
- { "LD L,(IX+%02s)", "ldy #$%1|lda (z80_ix),y|sta z80_l", IX, L },
- { "LD H,(IX+%02s)", "ldy #$%1|lda (z80_ix),y|sta z80_h", IX, H },
- { "LD (IX+%02s),A", "ldy #$%1|sta (z80_ix),y", A|IX, 0 },
- { "LD (IX+%02s),B", "ldy #$%1|lda z80_b|sta (z80_ix),y", B|IX, 0 },
- { "LD (IX+%02s),C", "ldy #$%1|lda z80_c|sta (z80_ix),y", C|IX, 0 },
- { "LD (IX+%02s),L", "ldy #$%1|lda z80_l|sta (z80_ix),y", L|IX, 0 },
- { "LD (IX+%02s),H", "ldy #$%1|lda z80_h|sta (z80_ix),y", H|IX, 0 },
- { "LD (IX+%02s),%02s", "ldy #$%1|lda #$%2|sta (z80_ix),y", IX, 0 },
- { "LD (IY+%02s),A", "ldy #$%1|sta (z80_iy),y", A|IY, 0 },
- { "LD (IY+%02s),C", "ldy #$%1|lda z80_c|sta (z80_iy),y", C|IY, 0 },
- { "LD (IY+%02s),D", "ldy #$%1|lda z80_d|sta (z80_iy),y", D|IY, 0 },
- { "LD (IY+%02s),E", "ldy #$%1|lda z80_e|sta (z80_iy),y", E|IY, 0 },
- { "LD (IY+%02s),%02s", "ldy #$%1|lda #$%2|sta (z80_iy),y", IY, 0 },
- { "LD D,(IY+%02s)", "ldy #$%1|lda (z80_iy),y|sta z80_d", IY, D },
- { "LD E,(IY+%02s)", "ldy #$%1|lda (z80_iy),y|sta z80_e", IY, E },
- { "LD L,(IY+%02s)", "ldy #$%1|lda (z80_iy),y|sta z80_l", IY, L },
- { "LD A,(HL)", "ldy #$00|lda (z80_hl),y", HL, A },
- { "LD A,(DE)", "ldy #$00|lda (z80_de),y", DE, A },
- { "LD A,(BC)", "ldy #$00|lda (z80_bc),y", BC, A },
- { "LD (BC),A", "ldy #$00|sta (z80_bc),y", A|BC, 0 },
- { "LD (DE),A", "ldy #$00|sta (z80_de),y", A|DE, 0 },
- { "LD A,(%05s)", "lda %1", 0, A, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD (%05s),A", "sta %1", A, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD B,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_b", HL, B },
- { "LD C,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_c", HL, C },
- { "LD D,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_d", HL, D },
- { "LD E,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_e", HL, E },
- { "LD H,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_h", HL, H },
- { "LD L,(HL)", "ldy #$00|lda (z80_hl),y|sta z80_l", HL, L },
- { "LD (HL),A", "ldy #$00|sta (z80_hl),y", A|HL, 0 },
- { "LD (HL),C", "lda z80_c|ldy #$00|sta (z80_hl),y", C|HL, 0 },
- { "LD (HL),D", "lda z80_d|ldy #$00|sta (z80_hl),y", D|HL, 0 },
- { "LD (HL),E", "lda z80_e|ldy #$00|sta (z80_hl),y", E|HL, 0 },
- { "LD (HL),$%02s", "lda #$%1|ldy #$00|sta (z80_hl),y", HL, 0 },
- { "LD SP,(%05s)", "; LD SP,(%1): TODO ", 0, SP},
- { "LD SP,%s", "; LD SP,%1: TODO ", 0, SP},
- { "LD (%05s),HL", "lda z80_l|sta %1|lda z80_h|sta %1+1", HL, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD A,(%s)", "lda %1", 0, A, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD (%s),A", "sta %1", A, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD (%05s),SP", "; TODO: LD (%1),SP", SP, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD (%05s),HL", "lda z80_l|sta %1|lda z80_h|sta %1+1", HL, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LD (%05s),DE", "lda z80_e|sta %1|lda z80_d|sta %1+1", DE, 0, FLAG_MAKE_1ST_PARAM_A_LABEL },
- { "LDH A,($%02s) ; %s", "lda $FF%1", 0, A },
- { "LDH ($%02s),A ; %s", "sta $FF%1", A, 0 },
- { "OR (IY+%02s)", "ldy #$%1|ora (z80_iy),y", A|IY, A|FLAGS },
- { "OR (IX+%02s)", "ldy #$%1|ora (z80_ix),y", A|IX, A|FLAGS },
- { "OR A", "ora #$00 ; OR A: Warning: probably tests for zero", A, A | FLAGS },
- { "OR B", "ora z80_b", A|B, A|FLAGS },
- { "OR C", "ora z80_c", A|C, A|FLAGS },
- { "OR D", "ora z80_d", A|D, A|FLAGS },
- { "OR E", "ora z80_e", A|E, A|FLAGS },
- { "OR L", "ora z80_l", A|L, A|FLAGS },
- { "OR H", "ora z80_h", A|H, A|FLAGS },
- { "OR (HL)", "ldy #$00|ora (z80_hl),y", A|HL, A|FLAGS },
- { "OR $%02s", "ora #$%1", A, A|FLAGS },
- { "ADD A,A", "asl @", A, A|FLAGS },
- { "ADD A,B", "clc|adc z80_b", A|B, A|FLAGS },
- { "ADD A,C", "clc|adc z80_c", A|C, A|FLAGS },
- { "ADD A,D", "clc|adc z80_d", A|D, A|FLAGS },
- { "ADD A,E", "clc|adc z80_e", A|E, A|FLAGS },
- { "ADD A,L", "clc|adc z80_l", A|L, A|FLAGS },
- { "ADD A,H", "clc|adc z80_h", A|H, A|FLAGS },
- { "ADD IY,DE", "jsr add_iy_de", IY|DE, IY|HFLAG|CARRY|NFLAG },
- { "ADD IY,BC", "jsr add_iy_bc", IY|BC, IY|HFLAG|CARRY|NFLAG },
- { "ADD IX,DE", "jsr add_ix_de", IX|DE, IX|HFLAG|CARRY|NFLAG },
- { "ADD HL,DE", "jsr add_hl_de", HL|DE, HL|HFLAG|CARRY|NFLAG },
- { "ADD HL,BC", "jsr add_hl_bc", HL|BC, HL|HFLAG|CARRY|NFLAG },
- { "ADD HL,SP", "jsr add_hl_sp", HL|SP, HL|HFLAG|CARRY|NFLAG },
- { "ADD HL,HL", "asl z80_l|rol z80_h", HL, HL|HFLAG|CARRY|NFLAG },
- { "ADD A,(HL)", "ldy #$00|clc|adc (z80_hl),y", A|HL, A|FLAGS },
- { "ADD A,(IX+%02s)", "ldy #$%1|clc|adc (z80_ix),y", A|IX, A|FLAGS },
- { "ADD A,(IY+%02s)", "ldy #$%1|clc|adc (z80_iy),y", A|IY, A|FLAGS },
- { "ADD A,$%02s", "clc|adc #$%1", A, A|FLAGS },
- { "ADD A", "asl @", A, A|FLAGS },
- { "ADC A,B", "adc z80_b", A|B|CARRY, A|FLAGS },
- { "ADC A,$%02s", "adc #$%1", A|CARRY, A|FLAGS },
- { "SUB (IX+%02s)", "ldy #$%1|sec|sbc (z80_ix),y", A|IX, A|FLAGS },
- { "SUB (IY+%02s)", "ldy #$%1|sec|sbc (z80_iy),y", A|IY, A|FLAGS },
- { "SUB B", "sec|sbc z80_b", A|B, A|FLAGS },
- { "SUB C", "sec|sbc z80_c", A|C, A|FLAGS },
- { "SUB D", "sec|sbc z80_d", A|D, A|FLAGS },
- { "SUB E", "sec|sbc z80_e", A|E, A|FLAGS },
- { "SUB L", "sec|sbc z80_l", A|L, A|FLAGS },
- { "SUB H", "sec|sbc z80_h", A|H, A|FLAGS },
- { "SUB (HL)", "ldy #$00|sec|sbc (z80_hl),y", A | HL, A | FLAGS },
- { "SUB $%02s", "sec|sbc #$%1", A, A|FLAGS },
- { "SBC A,A", "lda #$00|sec", A | A | FLAGS },
- { "SBC A,B", "sec|sbc z80_b", A | B, A | FLAGS },
- { "SBC A,H", "sec|sbc z80_h", A | H, A | FLAGS },
- { "SBC A,(HL)", "ldy #$00|sec|sbc (z80_hl),y", A | HL, A | FLAGS },
- { "SBC HL,DE", "jsr sbc_hl_de", HL|DE|CARRY, HL|FLAGS },
- { "SBC HL,BC", "jsr sbc_hl_bc", HL|BC|CARRY, HL|FLAGS },
- { "AND A", "; AND A: Warning: probably tests for zero", A, A|FLAGS },
- { "AND B", "and z80_b", A|B, FLAGS },
- { "AND C", "and z80_c", A|C, FLAGS },
- { "AND D", "and z80_d", A|D, FLAGS },
- { "AND L", "and z80_l", A|L, FLAGS },
- { "AND (HL)", "ldy #$00|and (z80_hl),y", A|HL, A|FLAGS },
- { "AND $%02s", "and #$%1", A, A|FLAGS },
- { "CP B", "cmp z80_b", A|B, FLAGS },
- { "CP C", "cmp z80_c", A|C, FLAGS },
- { "CP D", "cmp z80_d", A|D, FLAGS },
- { "CP E", "cmp z80_e", A|E, FLAGS },
- { "CP H", "cmp z80_h", A|H, FLAGS },
- { "CP L", "cmp z80_l", A|L, FLAGS },
- { "CP (HL)", "ldy #$00|cmp (z80_hl),y", A|HL, FLAGS },
- { "CP (IX+%02s)", "ldy #$%1|cmp (z80_ix),y", A|IX, FLAGS },
- { "CP (IY+%02s)", "ldy #$%1|cmp (z80_iy),y", A|IY, FLAGS },
- { "CP $%02s", "cmp #$%1", A, FLAGS },
- { "NEG", "eor #$ff|clc|adc #$01", A, A|FLAGS },
- { "CPL", "eor #$ff", A, A|NFLAG|HFLAG },
- { "XOR A", "lda #$00", 0, A|FLAGS },
- { "XOR B", "eor z80_b", A|B, FLAGS },
- { "XOR C", "eor z80_c", A|C, FLAGS },
- { "XOR D", "eor z80_d", A|D, FLAGS },
- { "XOR E", "eor z80_e", A|E, FLAGS },
- { "XOR (HL)", "ldy #$00|eor (z80_hl),y", A|HL, A|FLAGS },
- { "XOR (IX+%02s)", "ldy #$%1|eor (z80_ix),y", A|IX, A|FLAGS },
- { "XOR $%02s", "eor #$%1", A, A|FLAGS },
- { "INC A", "clc|adc #$01", A, A|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC B", "inc z80_b", B, B|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC C", "inc z80_c", C, C|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC D", "inc z80_d", D, D|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC E", "inc z80_e", E, E|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC L", "inc z80_l", L, L|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC H", "inc z80_h", H, H|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC HL", "inc z80_l|bne *+4|inc z80_h", HL, HL },
- { "INC BC", "inc z80_c|bne *+4|inc z80_b", BC, BC },
- { "INC DE", "inc z80_e|bne *+4|inc z80_d", DE, DE },
- { "INC IX", "inc z80_ix|bne *+4|inc z80_ix+1", IX, IX },
- { "INC IY", "inc z80_iy|bne *+4|inc z80_iy+1", IY, IY },
- { "INC SP", "pla", SP, SP },
- { "INC (IX+%02s)", "ldy #$%1|lda (z80_ix),y|clc|adc #$01|sta (z80_ix),y", IX, SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "INC (HL)", "ldy #$00|lda (z80_hl),y|clc|adc #$01|sta (z80_hl),y", HL, SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC A", "sec|sbc #$01", A, A|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC B", "dec z80_b", B, B|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC C", "dec z80_c", C, C|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC D", "dec z80_d", D, D|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC E", "dec z80_e", E, E|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC H", "dec z80_h", H, H|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC L", "dec z80_l", L, L|SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC (HL)", "ldy #$00|lda (z80_hl),y|sec|sbc #$01|sta (z80_hl),y", HL, SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC (IX+%02s)", "ldy #$%1|lda (z80_ix),y|sec|sbc #$01|sta (z80_ix),y", IX, SIGN|ZERO|HFLAG|OVERFLOWFLAG|NFLAG },
- { "DEC IX", "jsr dec_ix", IX, IX },
- { "DEC HL", "jsr dec_hl", HL, HL },
- { "DEC BC", "jsr dec_bc", BC, BC },
- { "DEC DE", "jsr dec_de", DE, DE },
- { "DEC SP", "pha", SP, SP },
- { "EX DE,HL", "jsr ex_de_hl", DE|HL, DE|HL },
- { "RRCA", "lsr @ ; RRCA: Warning: this copies bit 0 to bit 7", A, A|HFLAG|NFLAG|CARRY },
- { "RRC A", "lsr @ ; RRCA: Warning: this copies bit 0 to bit 7", A, A|HFLAG|NFLAG|CARRY },
- { "RLCA", "asl @ ; RLCA: Warning: this copies bit 7 to bit 0", A, A|HFLAG|NFLAG|CARRY },
- { "RRA", "ror @", A|CARRY, A|HFLAG|NFLAG|CARRY },
- { "SRA A", "cmp #$80|ror @", A, A|FLAGS },
- { "SRL A", "lsr @", A, A|FLAGS },
- { "SRL E", "lsr z80_e", E, E|FLAGS },
- { "SRL D", "lsr z80_d", D, D|FLAGS },
- { "SRL B", "lsr z80_b", B, B|FLAGS },
- { "SRL C", "lsr z80_c", C, C|FLAGS },
- { "SLA A", "asl @", A, A|FLAGS },
- { "SLA C", "asl z80_c", C, C|FLAGS },
- { "SLA E", "asl z80_e", E, E|FLAGS },
- { "SRL H", "lsr z80_h", H, H|FLAGS },
- { "RL C", "rol z80_c", C|CARRY, C|FLAGS },
- { "RL D", "rol z80_d", D|CARRY, D|FLAGS },
- { "RL E", "rol z80_e", E|CARRY, E|FLAGS },
- { "RR C", "ror z80_c", C|CARRY, C|FLAGS },
- { "RR L", "ror z80_l", L|CARRY, L|FLAGS },
- { "CALL C,%s", "bcs *+5|jsr %1 ; CALL C: Warning: check carry", CARRY, 0 },
- { "CALL NC,%s", "bcc *+5|jsr %1 ; CALL NC: Warning: check carry", CARRY, 0 },
- { "CALL Z,%s", "bne *+5|jsr %1", ZERO, 0 },
- { "CALL NZ,%s", "beq *+5|jsr %1", ZERO, 0 },
- { "CALL %s", "jsr %1", 0, 0 },
- { "JP Z,%s", "jeq %1", ZERO, 0 },
- { "JP NZ,%s", "jne %1", ZERO, 0 },
- { "JP NC,%s", "jcs %1", CARRY, 0 },
- { "JP C,%s", "jcc %1", CARRY, 0 },
- { "JP M,%s", "jmi %1", SIGN, 0 },
- { "JP P,%s", "jpl %1", SIGN, 0 },
- { "JP (HL)", "jmp (z80_hl)", HL, 0 },
- { "JP %s", "jmp %1", 0, 0 },
- { "DJNZ %s", "dec z80_b|jne %1", B, B },
- { "JR Z,%s", "jeq %1", ZERO, 0 },
- { "JR C,%s", "jcc %1", CARRY, 0 },
- { "JR NC,%s", "jcs %1", CARRY, 0 },
- { "JR NZ,%s", "jne %1", ZERO, 0 },
- { "JR %s", "jmp %1", 0, 0 },
- { "BIT %1s,(IX+%02s)", "ldy #$%2|lda (z80_ix),y|bit _bitmem%1", IX, ZERO|HFLAG|NFLAG },
- { "SET %1s,(IX+%02s)", "ldy #$%2|lda (z80_ix),y|ora #_bitvalue%1|sta (z80_ix),y", IX, 0 },
- { "RES %1s,(IX+%02s)", "ldy #$%2|lda (z80_ix),y|and #_notbitvalue%1|sta (z80_ix),y", IX, 0 },
- { "BIT %1s,(IY+%02s)", "ldy #$%2|lda (z80_iy),y|bit _bitmem%1", IY, ZERO|HFLAG|NFLAG },
- { "SET %1s,(IY+%02s)", "ldy #$%2|lda (z80_iy),y|ora #_bitvalue%1|sta (z80_iy),y", IY, 0 },
- { "RES %1s,(IY+%02s)", "ldy #$%2|lda (z80_iy),y|and #_notbitvalue%1|sta (z80_iy),y", IY, 0 },
- { "RES %1s,(HL)", "ldy #$00|lda (z80_hl),y|and #_notbitvalue%1|sta (z80_hl),y", HL, 0 },
- { "SET %1s,(HL)", "ldy #$00|lda (z80_hl),y|ora #_bitvalue%1|sta (z80_hl),y", HL, 0 },
- { "BIT %1s,(HL)", "ldy #$00|lda (z80_hl),y|bit _bitmem%1", HL, ZERO|HFLAG|NFLAG },
- { "BIT %1s,E", "lda z80_e|bit _bitmem%1", E, ZERO|HFLAG|NFLAG },
- { "BIT %1s,C", "lda z80_c|bit _bitmem%1", C, ZERO|HFLAG|NFLAG },
- { "SET %1s,C", "lda z80_c|ora #_bitvalue%1|sta z80_c", C, C },
- { "RES %1s,C", "lda z80_c|and #_notbitvalue%1|sta z80_c", C, C },
- { "BIT %1s,A", "bit _bitmem%1", A, ZERO|HFLAG|NFLAG },
- { "SET %1s,A", "lda z80_a|ora #_bitvalue%1|sta z80_a", A, A }, // added
- { "RES %1s,A", "lda z80_a|and #_notbitvalue%1|sta z80_a", A, A }, // added
- { "SET %s,A", "lda z80_a|ora #%1|sta z80_a", A, A }, // added
- { "RES %s,A", "lda z80_a|and #%1|sta z80_a", A, A }, // added
- { "RETI", "rti", 0, 0 },
- { "RET", "rts", 0, 0 },
- { "RET NZ", "beq *+3|rts", ZERO, 0 },
- { "RET NC", "bcc *+3|rts", CARRY, 0 },
- { "RET C", "bcs *+3|rts", CARRY, 0 },
- { "RET Z", "bne *+3|rts", ZERO, 0 },
- { "RET M", "bpl *+3|rts", SIGN, 0 },
- { "RET P", "bmi *+3|rts", SIGN, 0 },
- { "PUSH DE", "lda z80_e|pha|lda z80_d|pha", DE, SP },
- { "PUSH HL", "lda z80_l|pha|lda z80_h|pha", HL, SP },
- { "POP HL", "pla|sta z80_h|pla|sta z80_l", SP, HL },
- { "POP DE", "pla|sta z80_d|pla|sta z80_e", SP, DE },
- { "PUSH IX", "lda z80_ix|pha|lda z80_ix+1|pha", IX, SP },
- { "POP IX", "pla|sta z80_ix+1|pla|sta z80_ix", SP, IX },
- { "PUSH IY", "lda z80_iy|pha|lda z80_iy+1|pha", IY, SP },
- { "POP IY", "pla|sta z80_iy+1|pla|sta z80_iy", SP, IY },
- { "PUSH BC", "lda z80_c|pha|lda z80_b|pha", BC, SP },
- { "POP BC", "pla|sta z80_b|pla|sta z80_c", SP, BC },
- { "PUSH AF", "pha|php", A|FLAGS, SP },
- { "POP AF", "plp|pha", SP, A|FLAGS },
- { "LDIR", "jsr ldir", HL|DE|BC, HL|DE|BC|HFLAG|OVERFLOWFLAG|NFLAG },
- { "LDDR", "jsr lddr", HL|DE|BC, HL|DE|BC|HFLAG|OVERFLOWFLAG|NFLAG },
- { "EX AF,AF'", "ldx z80_ap|sta z80_ap|txa ; TODO: EX AF,AF'", A|FLAGS, A|FLAGS },
- { "EXX", "jsr exx ; TODO: EXX", HL|DE|BC, HL|DE|BC },
- { "EX (SP),HL", "jsr ex_sp_hl; TODO: EX (SP),HL", SP|HL, HL },
- { "SCF", "sec", 0, CARRY },
- { "NOP", "nop", 0, 0 },
- { "DAA", "; TODO: decimal mode", A|CARRY|HFLAG, A|CARRY|HFLAG|SIGN|ZERO|OVERFLOWFLAG },
- { "OUT (FE),A", "jsr out_fe", A, 0 },
- { "OUT (FD),A", "jsr out_fd", A, 0 },
- { "IN A,(FE)", "jsr in_a_fe", 0, A },
- { "IN A,(1F)", "jsr in_a_1f", 0, A },
- { "EI", "jsr ei", 0, 0 },
- { "DI", "jsr di", 0, 0 },
- { "DW ", "; .wo 0", 0, 0 },
- { "DW %s", ".wo %1", 0, 0 },
- { "DB %s", ".he %1", 0, 0 },
- { NULL, NULL, 0, 0 }
- };
- string C6502Translator::Translate()
- {
- string oCodeLine;
- string oLabel;
- string oInstruction;
- bool bParsed = false;
- string oZ80Code;
- string o6502CodeLine;
- string o6502Code;
- string oAllCode;
- int iPos, iPadSpaces = 8;
- int iPreviousInstructionPattern = -1;
- int iPattern;
- regex e ("\\b([ ]+)([^ ]*)");
- string fmt (" $2");
- char szArgument1[128], szArgument2[128];
- while ( GetNextLine( oCodeLine ) )
- {
- if ( oCodeLine.empty() )
- {
- // flush block
- oAllCode += oZ80Code + "\n" + o6502Code + "\n";
- oZ80Code.clear();
- o6502Code.clear();
- iPreviousInstructionPattern = -1;
- continue;
- }
- Replace(oCodeLine, "\t", string(iPadSpaces, ' '));
- oZ80Code += ";" + oCodeLine + "\n";
- if ( oCodeLine[0] == ';' )
- {
- // comment
- o6502Code += oCodeLine + "\n";
- continue;
- }
- if (oCodeLine.length() > 7 && oCodeLine.at(7) != ' ' )
- {
- // label definition without mnemonic
- o6502Code += oCodeLine + "\n";
- AddDefinedLabel( oCodeLine );
- continue;
- }
- oLabel = oCodeLine.substr(0, iPadSpaces);
- oLabel.erase(find_if(oLabel.rbegin(), oLabel.rend(),
- not1(ptr_fun<int, int>(isspace))).base(), oLabel.end()); // trim right
- if (oLabel.empty() || (oLabel.find(':') == string::npos))
- {
- oLabel.clear();
- iPos = iPadSpaces;
- o6502CodeLine = string(iPadSpaces, ' ');
- }
- else
- {
- o6502CodeLine = string_format("%-8s", oLabel.c_str());
- iPos = oLabel.size();
- oLabel.erase(remove(oLabel.begin(), oLabel.end(), ':'), oLabel.end()); // Remove
- AddDefinedLabel(oLabel);
- }
- oInstruction = oCodeLine.substr(iPos);
- char buf[128];
- char buf2[128];
- int blen = oInstruction.size() + 1;
- if (blen > 128) blen = 128;
- strncpy(&buf[0], oInstruction.c_str(), blen); buf[--blen]='\0';
- *regex_replace(&buf2[0], &buf[0], &buf[0]+strlen(buf), e, fmt) = '\0';
- oInstruction = string(buf2);
- ::transform(oInstruction.begin(), oInstruction.end(), oInstruction.begin(), ::toupper);
- Replace(oInstruction, ", ", ",");
- Replace(oInstruction, "[", "(");
- Replace(oInstruction, "]", ")");
- bParsed = false;
- for ( iPattern = 0; !bParsed && g_oCodePatterns[iPattern].szPattern != NULL; iPattern++ )
- {
- string pattern = g_oCodePatterns[iPattern].szPattern;
- //pattern.Replace("%02s", " %s");
- Replace(pattern, "%05s", " %s");
- Replace(pattern, "%1s", " %s");
- Replace(pattern, ", %s", ",%s");
- Replace(pattern, "( %", "(%");
- Replace(pattern, "$ %", "$%");
- bool test=(iPattern==143 && oInstruction.substr(0,2) == "CP");
- switch( CountParameters( pattern ) )
- {
- case 0:
- if ( oInstruction == g_oCodePatterns[iPattern].szPattern )
- {
- o6502CodeLine += g_oCodePatterns[iPattern].sz6502Code;
- bParsed = true;
- }
- break;
- case 1:
- if ( sscanf( oInstruction.c_str(), pattern.c_str(), szArgument1 ) == 1 &&
- FixArg( szArgument1 ) && ParsingOK( oInstruction, pattern.c_str(), szArgument1 ) )
- {
- o6502CodeLine += g_oCodePatterns[iPattern].sz6502Code;
- if ( g_oCodePatterns[iPattern].iFlag == FLAG_MAKE_1ST_PARAM_A_LABEL )
- {
- MakeParameterALabel( szArgument1 );
- string oArgument1(szArgument1);
- AddReferencedLabel(oArgument1);
- }
- string oArgument1(szArgument1);
- if ( oInstruction.substr(0,2) == "DB" )
- {
- oArgument1.erase(remove(oArgument1.begin(), oArgument1.end(), 'h'), oArgument1.end()); // Remove
- }
- Replace(o6502CodeLine, "%1", oArgument1);
- bParsed = true;
- }
- break;
- case 2:
- if ( sscanf( oInstruction.c_str(), pattern.c_str(), szArgument1, szArgument2 ) == 2 &&
- FixArg( szArgument1 ) && ParsingOK( oInstruction, pattern.c_str(), szArgument1, szArgument2 ) )
- {
- o6502CodeLine += g_oCodePatterns[iPattern].sz6502Code;
- string oArgument1(szArgument1);
- Replace(o6502CodeLine, "%1", oArgument1);
- string oArgument2(szArgument2);
- Replace(o6502CodeLine, "%2", oArgument2);
- bParsed = true;
- }
- break;
- }
- }
- if ( bParsed )
- {
- iPos = o6502CodeLine.find( '|' );
- if ( iPos != -1 )
- {
- o6502CodeLine.insert( iPos, " ; " + oInstruction );
- }
- else
- {
- o6502CodeLine += " ; " + oInstruction;
- }
- Replace(o6502CodeLine, "|", "\n ");
- iPattern -= 1;
- if ( (g_oCodePatterns[iPattern].iRead & A)
- && iPreviousInstructionPattern != -1
- && !(g_oCodePatterns[iPreviousInstructionPattern].iWrite & A)
- && !(g_oCodePatterns[iPreviousInstructionPattern].iRead & A)
- //&& !(g_oCodePatterns[iPreviousInstructionPattern].iWrite & BC|DE|HL|IX|IY)
- )
- {
- o6502CodeLine += "; Warning: A read but not set by previous instruction";
- }
- if ( (g_oCodePatterns[iPattern].iRead & A)
- && iPreviousInstructionPattern == -1
- )
- {
- o6502CodeLine += "; Warning: A read at the beginning of the block";
- }
- if ( (g_oCodePatterns[iPattern].iRead & A) && !oLabel.empty() )
- {
- o6502CodeLine += "; Warning: A read at jump target instruction";
- }
- if ( (g_oCodePatterns[iPattern].iRead & ZERO) && iPreviousInstructionPattern != -1 && !(g_oCodePatterns[iPreviousInstructionPattern].iWrite & ZERO))
- {
- o6502CodeLine += "; Warning: ZERO flag read but not set by previous instruction";
- }
- if ( (g_oCodePatterns[iPattern].iRead & SIGN) && iPreviousInstructionPattern != -1 && !(g_oCodePatterns[iPreviousInstructionPattern].iWrite & SIGN))
- {
- o6502CodeLine += "; Warning: SIGN flag read but not set by previous instruction";
- }
- if ( (g_oCodePatterns[iPattern].iRead & CARRY)
- && iPreviousInstructionPattern != -1
- && (strncmp( g_oCodePatterns[iPattern].szPattern, "JP", 2 ) == 0 || strncmp( g_oCodePatterns[iPattern].szPattern, "JR", 2 ) == 0 || strncmp( g_oCodePatterns[iPattern].szPattern, "RET", 3 ) == 0 || strncmp( g_oCodePatterns[iPattern].szPattern, "CALL", 4 ) == 0 ) )
- {
- if ( !(g_oCodePatterns[iPreviousInstructionPattern].iWrite & CARRY) )
- {
- o6502CodeLine += "; Warning: CARRY flag read but not set by previous instruction";
- }
- else if ( strncmp( g_oCodePatterns[iPreviousInstructionPattern].szPattern, "CP", 2 ) != 0
- && strncmp( g_oCodePatterns[iPreviousInstructionPattern].szPattern, "SUB", 3 ) != 0
- && strncmp( g_oCodePatterns[iPreviousInstructionPattern].szPattern, "SBC", 3 ) != 0
- )
- {
- o6502CodeLine += "; Warning: CARRY flag read but not set not by CP/SUB/SBC instruction, may need to invert";
- }
- }
- iPreviousInstructionPattern = iPattern;
- }
- else if (oInstruction.size() > 0)
- {
- // AfxMessageBox( "Syntax Error: " + oInstruction );
- o6502CodeLine = "; Syntax Error: " + oInstruction;
- }
- o6502Code += (o6502CodeLine + "\n");
- }
- oAllCode += oZ80Code + "\n" + o6502Code;
- oAllCode = AddReferencedNotDefinedLabels() + "\n\n" + oAllCode;
- return oAllCode;
- }
- int main(int argc, char* argv[])
- {
- int nRetCode = 0;
- string oCode;
- //
- try
- {
- string fName = "D:\\Source\\Repos\\pokeyellow\\home.asm";
- if (argc == 2) fName = argv[1];
- ifstream oFile;
- oFile.open(fName, ifstream::in);
- char c = oFile.get();
- while (oFile.good()) {
- oCode.push_back(c);
- c = oFile.get();
- }
- oFile.close();
- }
- catch(ios_base::failure f)
- {
- fprintf(stderr, "%s", f.what());
- }
- //
- //oCode = "@@73 LD (IX+09),C\n";
- C6502Translator oTranslator( oCode );
- string o6502Code = oTranslator.Translate();
- fprintf(stdout, "%s", o6502Code.c_str());
- return nRetCode;
- }
|