1113 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1113 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
#include "memory.h"
 | 
						|
#include "cpu.h"
 | 
						|
#include "assembler.h"
 | 
						|
#include "compiler.h"
 | 
						|
#include "optimiser.h"
 | 
						|
 | 
						|
 | 
						|
namespace Optimiser
 | 
						|
{
 | 
						|
    enum OptimiseTypes {StwLdwPair=0, StwLdPair, StwStHigh, ExtraLdw, ExtraLd, LdwPair, StwLdiAddw, StwLdwAddw, StwLdwAddwVar, StwLdiAndw, StwLdwAndw, StwLdwAndwVar, StwLdiXorw, 
 | 
						|
                        StwLdwXorw, StwLdwXorwVar, StwLdiOrw, StwLdwOrw, StwLdwOrwVar, LdwBeqStwTmp, LdwBeqStwVar, LdBeqStTmp, LdBeqStVar, PokeVar, DokeVar, StwPair, StwPairReg,
 | 
						|
                        ExtraStw, PeekArrayB, PeekArray, DeekArray, PokeArray, DokeArray, PokeVarArrayB, PokeVarArray, DokeVarArray, PokeTmpArrayB, PokeTmpArray, DokeTmpArray, 
 | 
						|
                        StwPokeArray, StwDokeArray, LdSubLoHi, LdiSubLoHi, LdwSubLoHi, AddiPair, AddiZero, SubiZero, NumOptimiseTypes};
 | 
						|
 | 
						|
    struct MatchSequence
 | 
						|
    {
 | 
						|
        int _firstIndex;
 | 
						|
        int _secondIndex;
 | 
						|
        std::vector<std::string> _sequence;
 | 
						|
    };
 | 
						|
 | 
						|
    std::vector<MatchSequence> matchSequences = 
 | 
						|
    {
 | 
						|
        // StwLdwPair
 | 
						|
        {0, 1, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x" }},
 | 
						|
 | 
						|
        // StwLdPair
 | 
						|
        {0, 1, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LD"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "0x" }},
 | 
						|
 | 
						|
        // StwStHigh
 | 
						|
        {0, 0, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "ST"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_" }},
 | 
						|
 | 
						|
        // ExtraLdw
 | 
						|
        {0, 1, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_"  }},
 | 
						|
 | 
						|
        // ExtraLd
 | 
						|
        {0, 1, {"ST" + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_",
 | 
						|
                "LD" + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_"  }},
 | 
						|
 | 
						|
        // LdwPair
 | 
						|
        {0, 1, {"LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x"  }},
 | 
						|
 | 
						|
        // StwLdiAddw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDI"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwAddw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwAddwVar
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdiAndw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDI"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "ANDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwAndw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "ANDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwAndwVar
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "ANDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdiXorw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDI"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "XORW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwXorw
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "XORW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwXorwVar
 | 
						|
        {0, 2, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "XORW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdiOrw
 | 
						|
        {0, 2, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDI" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "ORW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwOrw
 | 
						|
        {0, 2, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "ORW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x"}},
 | 
						|
 | 
						|
        // StwLdwOrwVar
 | 
						|
        {0, 2, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x", 
 | 
						|
                "LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "ORW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x"}},
 | 
						|
 | 
						|
        // LdwBeqStwTmp
 | 
						|
        {0, 2, {"LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x", 
 | 
						|
                "BEQ" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x"}},
 | 
						|
 | 
						|
        // LdwBeqStwVar
 | 
						|
        {0, 2, {"LDW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_", 
 | 
						|
                "BEQ" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_"}},
 | 
						|
 | 
						|
        // LdBeqStTmp
 | 
						|
        {0, 2, {"LD"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "0x", 
 | 
						|
                "BEQ" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "ST"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "0x"}},
 | 
						|
 | 
						|
        // LdBeqStVar
 | 
						|
        {0, 2, {"LD"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_", 
 | 
						|
                "BEQ" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "ST"  + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_"}},
 | 
						|
 | 
						|
        // PokeVar
 | 
						|
        {0, 2, {"LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "", 
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + ""}},
 | 
						|
 | 
						|
        // DokeVar
 | 
						|
        {0, 2, {"LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "", 
 | 
						|
                "DOKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + ""}},
 | 
						|
 | 
						|
        // StwPair
 | 
						|
        {0, 0, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x" }},
 | 
						|
 | 
						|
        // StwPairReg
 | 
						|
        {0, 0, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem"}},
 | 
						|
 | 
						|
        // ExtraStw
 | 
						|
        {0, 0, {"STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x", 
 | 
						|
                "STW" + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_"  }},
 | 
						|
 | 
						|
        // PeekArrayB
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x", 
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem", 
 | 
						|
                "PEEK" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + ""}},
 | 
						|
 | 
						|
        // PeekArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x", 
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem", 
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem", 
 | 
						|
                "PEEK" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + ""}},
 | 
						|
 | 
						|
        // DeekArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x", 
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem", 
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem", 
 | 
						|
                "DEEK" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + ""}},
 | 
						|
 | 
						|
        // PokeArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x", 
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem", 
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // DokeArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "DOKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // PokeVarArrayB
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // PokeVarArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // DokeVarArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "DOKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // PokeTmpArrayB
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // PokeTmpArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // DokeTmpArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDWI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "0x",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "ADDW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "mem",
 | 
						|
                "DOKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // StwPokeArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "POKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // StwDokeArray
 | 
						|
        {0, 0, {"STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "0x",
 | 
						|
                "DOKE" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "mem"}},
 | 
						|
 | 
						|
        // LdSubLoHi
 | 
						|
        {0, 0, {"LD"   + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LD"   + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "SUBW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "reg"}},
 | 
						|
 | 
						|
        // LdiSubLoHi
 | 
						|
        {0, 0, {"LDI"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LD"   + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "SUBW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "reg"}},
 | 
						|
 | 
						|
        // LdwSubLoHi
 | 
						|
        {0, 0, {"LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LD"   + std::string(OPCODE_TRUNC_SIZE - 2, ' ') + "_",
 | 
						|
                "STW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "LDW"  + std::string(OPCODE_TRUNC_SIZE - 3, ' ') + "reg",
 | 
						|
                "SUBW" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "reg"}},
 | 
						|
 | 
						|
        // AddiPair
 | 
						|
        {0, 0, {"ADDI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + "",
 | 
						|
                "ADDI" + std::string(OPCODE_TRUNC_SIZE - 4, ' ') + ""}},
 | 
						|
 | 
						|
        // AddiZero
 | 
						|
        {0, 0, {"ADDI" + std::string(OPCODE_TRUNC_SIZE - 4, ' '), ""}},
 | 
						|
 | 
						|
        // SubiZero
 | 
						|
        {0, 0, {"SUBI" + std::string(OPCODE_TRUNC_SIZE - 4, ' '), ""}},
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
    bool initialise(void)
 | 
						|
    {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    // Migrate internal label for an instruction that has been deleted, (use this function before the instruction is deleted)
 | 
						|
    bool migrateInternalLabel(int index, int oldLine, int newLine)
 | 
						|
    {
 | 
						|
        // If a label exists, move it to next available vasm line
 | 
						|
        if(Compiler::getCodeLines()[index]._vasm[oldLine]._internalLabel.size())
 | 
						|
        {
 | 
						|
            // Next available vasm line is part of a new BASIC line, so can't optimise
 | 
						|
            if(int(Compiler::getCodeLines()[index]._vasm.size()) <= newLine) return false;
 | 
						|
            Compiler::getCodeLines()[index]._vasm[newLine]._internalLabel = Compiler::getCodeLines()[index]._vasm[oldLine]._internalLabel;
 | 
						|
        }
 | 
						|
    
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    // Adjust label addresses for any labels with addresses higher than optimised vasm instruction address
 | 
						|
    void adjustLabelAddresses(int codeLineIndex, int vasmLineIndex, int offset)
 | 
						|
    {
 | 
						|
        // Loop through commented out code
 | 
						|
        do
 | 
						|
        {
 | 
						|
            if(vasmLineIndex >= int(Compiler::getCodeLines()[codeLineIndex]._vasm.size()))
 | 
						|
            {
 | 
						|
                if(++codeLineIndex >= int(Compiler::getCodeLines().size())) return;
 | 
						|
                vasmLineIndex = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        while(Compiler::getCodeLines()[codeLineIndex]._vasm.size() == 0);
 | 
						|
 | 
						|
        uint16_t optimisedAddress = Compiler::getCodeLines()[codeLineIndex]._vasm[vasmLineIndex]._address;
 | 
						|
 | 
						|
        for(int i=0; i<int(Compiler::getLabels().size()); i++)
 | 
						|
        {
 | 
						|
            if(Compiler::getLabels()[i]._address >= optimisedAddress)
 | 
						|
            {
 | 
						|
                Compiler::getLabels()[i]._address += int16_t(offset);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // Adjust vasm code addresses
 | 
						|
    void adjustVasmAddresses(int codeLineIndex, int vasmLineIndex, int offset)
 | 
						|
    {
 | 
						|
        // Loop through commented out code
 | 
						|
        do
 | 
						|
        {
 | 
						|
            if(vasmLineIndex >= int(Compiler::getCodeLines()[codeLineIndex]._vasm.size()))
 | 
						|
            {
 | 
						|
                if(++codeLineIndex >= int(Compiler::getCodeLines().size())) return;
 | 
						|
                vasmLineIndex = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        while(Compiler::getCodeLines()[codeLineIndex]._vasm.size() == 0);
 | 
						|
 | 
						|
        for(int i=codeLineIndex; i<int(Compiler::getCodeLines().size()); i++)
 | 
						|
        {
 | 
						|
            int start = (i == codeLineIndex) ? vasmLineIndex : 0;
 | 
						|
            for(int j=start; j<int(Compiler::getCodeLines()[i]._vasm.size()); j++)
 | 
						|
            {
 | 
						|
                Compiler::getCodeLines()[i]._vasm[j]._address += int16_t(offset);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void updateVasm(int codeLineIndex, int vasmLineIndex, const std::string& opcode, const std::string& operand)
 | 
						|
    {
 | 
						|
        Compiler::getCodeLines()[codeLineIndex]._vasm[vasmLineIndex]._opcode = opcode;
 | 
						|
        Compiler::getCodeLines()[codeLineIndex]._vasm[vasmLineIndex]._operand = operand;
 | 
						|
        Compiler::getCodeLines()[codeLineIndex]._vasm[vasmLineIndex]._code = opcode + std::string(OPCODE_TRUNC_SIZE - opcode.size(), ' ') + operand;
 | 
						|
        Compiler::getCodeLines()[codeLineIndex]._vasm[vasmLineIndex]._vasmSize = Assembler::getAsmOpcodeSize(opcode);
 | 
						|
    }
 | 
						|
 | 
						|
    void updateVasm(std::vector<Compiler::VasmLine>::iterator& it, int offset, const std::string& opcode, const std::string& operand)
 | 
						|
    {
 | 
						|
        (it + offset)->_opcode = opcode;
 | 
						|
        (it + offset)->_operand = operand;
 | 
						|
        (it + offset)->_code = opcode + std::string(OPCODE_TRUNC_SIZE - opcode.size(), ' ') + operand;
 | 
						|
        (it + offset)->_vasmSize = Assembler::getAsmOpcodeSize(opcode);
 | 
						|
    }
 | 
						|
 | 
						|
    bool optimiseCode(void)
 | 
						|
    {
 | 
						|
 | 
						|
RESTART_OPTIMISE:
 | 
						|
        for(int i=0; i<int(Compiler::getCodeLines().size()); i++)
 | 
						|
        {
 | 
						|
            for(int j=0; j<int(matchSequences.size()); j++)
 | 
						|
            {
 | 
						|
                for(auto itVasm=Compiler::getCodeLines()[i]._vasm.begin(); itVasm!=Compiler::getCodeLines()[i]._vasm.end();)
 | 
						|
                {
 | 
						|
                    bool linesDeleted = false;
 | 
						|
                    int vasmIndex = int(itVasm - Compiler::getCodeLines()[i]._vasm.begin());
 | 
						|
 | 
						|
                    // Can only optimise within a BASIC code line, (use multi-statements to optimise across lines)
 | 
						|
                    int vasmIndexMax = vasmIndex + int(matchSequences[j]._sequence.size()) - 1;
 | 
						|
                    if(vasmIndexMax >= int(Compiler::getCodeLines()[i]._vasm.size()))
 | 
						|
                    {
 | 
						|
                        ++itVasm;
 | 
						|
                        continue;
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Find opcode match
 | 
						|
                    bool foundOpcodeMatch = true;
 | 
						|
                    for(int k=vasmIndex; k<=vasmIndexMax; k++)
 | 
						|
                    {
 | 
						|
                        if(Compiler::getCodeLines()[i]._vasm[k]._code.find(matchSequences[j]._sequence[k - vasmIndex]) ==  std::string::npos)
 | 
						|
                        {
 | 
						|
                            foundOpcodeMatch = false;
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if(foundOpcodeMatch)
 | 
						|
                    {
 | 
						|
                        // First operand
 | 
						|
                        int firstIndex = matchSequences[j]._firstIndex;
 | 
						|
                        int firstLine = vasmIndex + firstIndex;
 | 
						|
                        std::string firstOperand = Compiler::getCodeLines()[i]._vasm[firstLine]._operand;
 | 
						|
 | 
						|
                        // Second operand
 | 
						|
                        int secondIndex = matchSequences[j]._secondIndex;
 | 
						|
                        int secondLine = vasmIndex + secondIndex;
 | 
						|
                        std::string secondOperand = Compiler::getCodeLines()[i]._vasm[secondLine]._operand;
 | 
						|
 | 
						|
/*************************************************************************************************************************************************************/
 | 
						|
/* Opcode matches required, operand matches required                                                                                                         */
 | 
						|
/*************************************************************************************************************************************************************/
 | 
						|
 | 
						|
                        // Find operand match, (temporary variables are a minimum of 4 chars, i.e. '0xd0')
 | 
						|
                        //if(firstOperand.substr(0, 4) == secondOperand.substr(0, 4))
 | 
						|
                        if(firstOperand == secondOperand)
 | 
						|
                        {
 | 
						|
                            switch(j)
 | 
						|
                            {
 | 
						|
                                // Match STW LDW, delete STW LDW
 | 
						|
                                //case StwLdPair:
 | 
						|
                                case StwLdwPair:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW ST, delete STW
 | 
						|
                                case StwStHigh:
 | 
						|
                                {
 | 
						|
                                    // Assume neither of these instructions can have a label
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -2);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -2);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW/ST LDW/LD, delete LDW/LD
 | 
						|
                                case ExtraLdw:
 | 
						|
                                case ExtraLd:
 | 
						|
                                {
 | 
						|
                                    // If the LDW has an internal label, then it probably can't be optimised away
 | 
						|
                                    if(!Compiler::getCodeLines()[i]._vasm[firstLine + 1]._internalLabel.size())
 | 
						|
                                    {
 | 
						|
                                        // Migrate internal label to next available instruction
 | 
						|
                                        if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                        // Delete LDW
 | 
						|
                                        linesDeleted = true;
 | 
						|
                                        itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                        adjustLabelAddresses(i, firstLine + 1, -2);
 | 
						|
                                        adjustVasmAddresses(i, firstLine + 1, -2);
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match LDW LDW, delete first LDW
 | 
						|
                                case LdwPair:
 | 
						|
                                {
 | 
						|
                                    // Migrate internal label from first LDW to second LDW
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 1)) break;
 | 
						|
 | 
						|
                                    // Delete first LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine + 1, -2);
 | 
						|
                                    adjustVasmAddresses(i, firstLine + 1, -2);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDI ADDW, copy LDI operand to ADDW operand, change ADDW to ADDI, delete STW LDW
 | 
						|
                                case StwLdiAddw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ADDW with ADDI and replace ADDW's operand with LDI's operand
 | 
						|
                                    std::string ldiOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ADDI", ldiOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDI
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ADDW, copy LDW operand to ADDW operand and delete STW LDW
 | 
						|
                                case StwLdwAddw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ADDW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ADDW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ADDW, copy LDW operand to ADDW operand and delete STW LDW, (LDW is a var)
 | 
						|
                                case StwLdwAddwVar:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ADDW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ADDW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDI ANDW, copy LDI operand to ANDW operand, change ANDW to ANDI, delete STW LDW
 | 
						|
                                case StwLdiAndw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ANDW with ANDI and replace ANDW's operand with LDI's operand
 | 
						|
                                    std::string ldiOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ANDI", ldiOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ANDW, copy LDW operand to ANDW operand and delete STW LDW
 | 
						|
                                case StwLdwAndw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ANDW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ANDW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ANDW, copy LDW operand to ANDW operand and delete STW LDW, (LDW is a var)
 | 
						|
                                case StwLdwAndwVar:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ANDW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ANDW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDI XORW, copy LDI operand to XORW operand, change XORW to XORI, delete STW LDW
 | 
						|
                                case StwLdiXorw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace XORW with XORI and replace XORW's operand with LDI's operand
 | 
						|
                                    std::string ldiOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "XORI", ldiOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW XORW, copy LDW operand to XORW operand and delete STW LDW
 | 
						|
                                case StwLdwXorw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace XORW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "XORW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW XORW, copy LDW operand to XORW operand and delete STW LDW, (LDW is a var)
 | 
						|
                                case StwLdwXorwVar:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace XORW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "XORW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDI ORW, copy LDI operand to ORW operand, change ORW to ORI, delete STW LDW
 | 
						|
                                case StwLdiOrw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ORW with ORI and replace ORW's operand with LDI's operand
 | 
						|
                                    std::string ldiOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ORI", ldiOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ORW, copy LDW operand to ORW operand and delete STW LDW
 | 
						|
                                case StwLdwOrw:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ORW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ORW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW and LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match STW LDW ORW, copy LDW operand to ORW operand and delete STW LDW, (LDW is a var)
 | 
						|
                                case StwLdwOrwVar:
 | 
						|
                                {
 | 
						|
                                    // Only one of these can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                    // Replace ORW's operand with LDW's operand
 | 
						|
                                    std::string ldwOperand = Compiler::getCodeLines()[i]._vasm[firstLine + 1]._operand;
 | 
						|
                                    updateVasm(i, firstLine + 2, "ORW", ldwOperand);
 | 
						|
 | 
						|
                                    // Delete STW LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                    adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match LDW/LD BEQ STW/ST, delete STW/ST
 | 
						|
                                case LdwBeqStwTmp:
 | 
						|
                                case LdwBeqStwVar:
 | 
						|
                                case LdBeqStTmp:
 | 
						|
                                case LdBeqStVar:
 | 
						|
                                {
 | 
						|
                                    // STW/ST can have an internal label
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 2, firstLine + 3)) break;
 | 
						|
 | 
						|
                                    // Delete STW/ST
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 2);
 | 
						|
                                    adjustLabelAddresses(i, firstLine + 2, -2);
 | 
						|
                                    adjustVasmAddresses(i, firstLine + 2, -2);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                // Match LDW POKE/DOKE LDW, delete second LDW if it matches with first LDW
 | 
						|
                                case PokeVar:
 | 
						|
                                case DokeVar:
 | 
						|
                                {
 | 
						|
                                    // Migrate second LDW's label, (if it has one)
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine + 2, firstLine + 3)) break;
 | 
						|
 | 
						|
                                    // Delete second LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 2);
 | 
						|
                                    adjustLabelAddresses(i, firstLine + 2, -2);
 | 
						|
                                    adjustVasmAddresses(i, firstLine + 2, -2);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
 | 
						|
                                default: break;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
/*************************************************************************************************************************************************************/
 | 
						|
/* Opcode matches required, operand matches NOT required                                                                                                     */
 | 
						|
/*************************************************************************************************************************************************************/
 | 
						|
                        switch(j)
 | 
						|
                        {
 | 
						|
                            // Extra STW, (doesn't require an operand match)
 | 
						|
                            case StwPair:
 | 
						|
                            case StwPairReg:
 | 
						|
                            case ExtraStw:
 | 
						|
                            {
 | 
						|
                                // Migrate internal label to next available instruction
 | 
						|
                                if(!migrateInternalLabel(i, firstLine, firstLine + 1)) break;
 | 
						|
 | 
						|
                                // Delete first STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                adjustLabelAddresses(i, firstLine, -2);
 | 
						|
                                adjustVasmAddresses(i, firstLine, -2);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match LDW STW LDWI ADDW PEEK end up with LDWI ADDW PEEK
 | 
						|
                            case PeekArrayB:
 | 
						|
                            {
 | 
						|
                                // Save previous line LDW, if opcode is not LDW then can't optimise
 | 
						|
                                if(firstLine - 1 < 0) break;
 | 
						|
                                Compiler::VasmLine savedLDW = Compiler::getCodeLines()[i]._vasm[firstLine - 1];
 | 
						|
                                if(savedLDW._opcode != "LDW") break;
 | 
						|
 | 
						|
                                // Migrate it's label if it has one
 | 
						|
                                if(!migrateInternalLabel(i, firstLine - 1, firstLine + 1)) break;
 | 
						|
 | 
						|
                                // Delete previous line LDW and first STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine - 1);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
 | 
						|
                                // Replace operand of ADDW with LDW's operand
 | 
						|
                                updateVasm(itVasm, 1, "ADDW", savedLDW._operand);
 | 
						|
                                adjustLabelAddresses(i, firstLine - 1, -4);
 | 
						|
                                adjustVasmAddresses(i, firstLine - 1, -4);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match LDW STW LDWI ADDW ADDW PEEK/DEEK end up with LDWI ADDW ADDW PEEK/DEEK
 | 
						|
                            case PeekArray:
 | 
						|
                            case DeekArray:
 | 
						|
                            {
 | 
						|
                                // Save previous line LDW, if opcode is not LDW then can't optimise
 | 
						|
                                if(firstLine - 1 < 0) break;
 | 
						|
                                Compiler::VasmLine savedLDW = Compiler::getCodeLines()[i]._vasm[firstLine - 1];
 | 
						|
                                if(savedLDW._opcode != "LDW") break;
 | 
						|
 | 
						|
                                // Migrate it's label if it has one
 | 
						|
                                if(!migrateInternalLabel(i, firstLine - 1, firstLine + 1)) break;
 | 
						|
 | 
						|
                                // Delete previous line LDW and first STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine - 1);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
 | 
						|
                                // Replace operand of both ADDW's with LDW's operand
 | 
						|
                                updateVasm(itVasm, 1, "ADDW", savedLDW._operand);
 | 
						|
                                updateVasm(itVasm, 2, "ADDW", savedLDW._operand);
 | 
						|
                                adjustLabelAddresses(i, firstLine - 1, -4);
 | 
						|
                                adjustVasmAddresses(i, firstLine - 1, -4);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match LD<X> STW LDWI STW LDW POKE/DOKE end up with LDWI STW LD<X> POKE/DOKE
 | 
						|
                            case PokeArray:
 | 
						|
                            case DokeArray:
 | 
						|
                            {
 | 
						|
                                uint16_t offset = 9;
 | 
						|
 | 
						|
                                // Save previous line LD<X>, if opcode is not some sort of LD then can't optimise
 | 
						|
                                if(firstLine - 1 < 0) break;
 | 
						|
                                Compiler::VasmLine savedLD = Compiler::getCodeLines()[i]._vasm[firstLine - 1];
 | 
						|
                                if(savedLD._opcode.find("LD") == std::string::npos) break;
 | 
						|
                                if(savedLD._opcode.find("LDWI") != std::string::npos) offset += 1;
 | 
						|
 | 
						|
                                // Discard it's label, (it's no longer needed), and adjust it's address
 | 
						|
                                if(!migrateInternalLabel(i, firstLine - 1, firstLine + 1)) break;
 | 
						|
                                savedLD._internalLabel = "";
 | 
						|
                                savedLD._address += offset; // LD<X> is moved 9bytes, LDWI is moved 10 bytes
 | 
						|
 | 
						|
                                // Delete previous line LD<X>, first STW and LDW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine - 1);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm + 2);
 | 
						|
 | 
						|
                                // Replace LDW with saved LD<X> and operand
 | 
						|
                                if(offset == 9)
 | 
						|
                                {
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.insert(itVasm, savedLD);
 | 
						|
                                    adjustLabelAddresses(i, firstLine - 1, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine - 1, -4);
 | 
						|
                                }
 | 
						|
                                // LDW is replaced with LDWI so push everything forward starting at the POKE/DOKE by 1 more byte
 | 
						|
                                else
 | 
						|
                                {
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.insert(itVasm, savedLD);
 | 
						|
                                    adjustLabelAddresses(i, firstLine - 1, -5);
 | 
						|
                                    adjustVasmAddresses(i, firstLine - 1, -5);
 | 
						|
                                    adjustLabelAddresses(i, firstLine + 2, 1);
 | 
						|
                                    adjustVasmAddresses(i, firstLine + 2, 1);
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match LD<X> STW LDW STW LDWI ADDW STW LDW POKE
 | 
						|
                            case PokeVarArrayB:
 | 
						|
                            case PokeTmpArrayB:
 | 
						|
                            {
 | 
						|
                                uint16_t offset = 15; // LD<X> is moved 15 bytes
 | 
						|
 | 
						|
                                // Save previous line LD<X>, if opcode is not some sort of LD then can't optimise first phase
 | 
						|
                                if(firstLine - 1 < 0) break;
 | 
						|
                                Compiler::VasmLine savedLD = Compiler::getCodeLines()[i]._vasm[firstLine - 1];
 | 
						|
                                if(savedLD._opcode == "LDWI") offset += 1;
 | 
						|
                                if(savedLD._opcode.find("LD") != std::string::npos)
 | 
						|
                                {
 | 
						|
                                    // Discard it's label, (it's no longer needed), and adjust it's address
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine - 1, firstLine + 3)) break;
 | 
						|
                                    savedLD._internalLabel = "";
 | 
						|
                                    savedLD._address += offset;
 | 
						|
 | 
						|
                                    // Delete previous line LD<X>, first STW and last LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine - 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm + 5); //points to last LDW
 | 
						|
 | 
						|
                                    // Replace LDW with saved LD<X> and operand
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.insert(itVasm, savedLD);
 | 
						|
                                    adjustLabelAddresses(i, firstLine - 1, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine - 1, -4);
 | 
						|
                                    firstLine = firstLine - 1;  // points to new first LDW
 | 
						|
 | 
						|
                                    if(offset != 15)
 | 
						|
                                    {
 | 
						|
                                        // adjust for LDWI
 | 
						|
                                        adjustLabelAddresses(i, firstLine + 6, 1);
 | 
						|
                                        adjustVasmAddresses(i, firstLine + 6, 1);
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                                else
 | 
						|
                                {
 | 
						|
                                    firstLine = firstLine + 1; // points to first LDW
 | 
						|
                                }
 | 
						|
 | 
						|
                                // Now optimise the first LDW and second STW for second phase
 | 
						|
                                Compiler::VasmLine savedLDW = Compiler::getCodeLines()[i]._vasm[firstLine];
 | 
						|
 | 
						|
                                // Delete first LDW and second STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
 | 
						|
                                // Replace operand of ADDW with LDW's operand
 | 
						|
                                updateVasm(itVasm, 1, "ADDW", savedLDW._operand);
 | 
						|
                                adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match STW LDW STW LDWI ADDW ADDW STW LDW POKE/DOKE
 | 
						|
                            case PokeVarArray:
 | 
						|
                            case PokeTmpArray:
 | 
						|
                            case DokeVarArray:
 | 
						|
                            case DokeTmpArray:
 | 
						|
                            {
 | 
						|
                                uint16_t offset = 17; // LD<X> is moved 17 bytes
 | 
						|
 | 
						|
                                // Save previous line LD<X>, if opcode is not some sort of LD then can't optimise first phase
 | 
						|
                                if(firstLine - 1 < 0) break;
 | 
						|
                                Compiler::VasmLine savedLD = Compiler::getCodeLines()[i]._vasm[firstLine - 1];
 | 
						|
                                if(savedLD._opcode == "LDWI") offset += 1;
 | 
						|
                                if(savedLD._opcode.find("LD") != std::string::npos)
 | 
						|
                                {
 | 
						|
                                    // Migrate LD<X>'s label to LDWI
 | 
						|
                                    if(!migrateInternalLabel(i, firstLine - 1, firstLine + 3)) break;
 | 
						|
                                    savedLD._internalLabel = "";
 | 
						|
                                    savedLD._address += offset;
 | 
						|
 | 
						|
                                    // Delete previous line LD<X>, first STW and last LDW
 | 
						|
                                    linesDeleted = true;
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine - 1);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm + 6); //points to last LDW, after LD<X> and STW were deleted
 | 
						|
 | 
						|
                                    // Replace LDW with saved LD<X> and operand
 | 
						|
                                    itVasm = Compiler::getCodeLines()[i]._vasm.insert(itVasm, savedLD);
 | 
						|
                                    adjustLabelAddresses(i, firstLine - 1, -4);
 | 
						|
                                    adjustVasmAddresses(i, firstLine - 1, -4);
 | 
						|
                                    firstLine = firstLine - 1;  // points to new first LDW
 | 
						|
 | 
						|
                                    if(offset != 17)
 | 
						|
                                    {
 | 
						|
                                        // adjust for LDWI
 | 
						|
                                        adjustLabelAddresses(i, firstLine + 7, 1);
 | 
						|
                                        adjustVasmAddresses(i, firstLine + 7, 1);
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                                else
 | 
						|
                                {
 | 
						|
                                    firstLine = firstLine + 1; // points to first LDW
 | 
						|
                                }
 | 
						|
 | 
						|
                                // Now optimise the first LDW and second STW for second phase
 | 
						|
                                Compiler::VasmLine savedLDW = Compiler::getCodeLines()[i]._vasm[firstLine];
 | 
						|
 | 
						|
                                // Delete first LDW and second STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
 | 
						|
                                // Replace operand of both ADDW's
 | 
						|
                                updateVasm(itVasm, 1, "ADDW", savedLDW._operand);
 | 
						|
                                updateVasm(itVasm, 2, "ADDW", savedLDW._operand);
 | 
						|
                                adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            case StwPokeArray:
 | 
						|
                            case StwDokeArray:
 | 
						|
                            {
 | 
						|
                                // Migrate internal label to next available instruction
 | 
						|
                                if(!migrateInternalLabel(i, firstLine, firstLine + 1)) break;
 | 
						|
 | 
						|
                                // Delete first STW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                adjustLabelAddresses(i, firstLine, -2);
 | 
						|
                                adjustVasmAddresses(i, firstLine, -2);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match LD/LDW STW LD STW LDW SUBW
 | 
						|
                            case LdSubLoHi:
 | 
						|
                            case LdiSubLoHi:
 | 
						|
                            case LdwSubLoHi:
 | 
						|
                            {
 | 
						|
                                // Save LD<X>
 | 
						|
                                Compiler::VasmLine savedLD = Compiler::getCodeLines()[i]._vasm[firstLine];
 | 
						|
 | 
						|
                                // Migrate LD<X>'s label to LD
 | 
						|
                                if(!migrateInternalLabel(i, firstLine, firstLine + 2)) break;
 | 
						|
                                savedLD._internalLabel = "";
 | 
						|
                                savedLD._address += 8; // LD<X> is moved 8 bytes
 | 
						|
 | 
						|
                                // Delete LD<X>, first STW and last LDW
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm);
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(itVasm + 2); //points to last LDW, after LD<X> and STW were deleted
 | 
						|
 | 
						|
                                // Replace LDW with saved LD<X> and operand
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.insert(itVasm, savedLD);
 | 
						|
                                adjustLabelAddresses(i, firstLine, -4);
 | 
						|
                                adjustVasmAddresses(i, firstLine, -4);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            // Match ADDI ADDI
 | 
						|
                            case AddiPair:
 | 
						|
                            {
 | 
						|
                                uint8_t addi0, addi1;
 | 
						|
 | 
						|
                                // Migrate second ADDI's label to next instruction
 | 
						|
                                if(!migrateInternalLabel(i, firstLine + 1, firstLine + 2)) break;
 | 
						|
 | 
						|
                                // Add operands together, replace first operand, delete 2nd opcode and operand
 | 
						|
                                Compiler::VasmLine vasm = Compiler::getCodeLines()[i]._vasm[firstLine];
 | 
						|
                                std::string operand = vasm._operand;
 | 
						|
                                Expression::stringToU8(operand, addi0);
 | 
						|
                                vasm = Compiler::getCodeLines()[i]._vasm[firstLine + 1];
 | 
						|
                                operand = vasm._operand;
 | 
						|
                                Expression::stringToU8(operand, addi1);
 | 
						|
 | 
						|
                                // Result can't fit in an ADDI operand so exit, (ADDI can't be -ve so result can't be -ve)
 | 
						|
                                uint16_t result = addi0 + addi1;
 | 
						|
                                if(result > 255) break;
 | 
						|
 | 
						|
                                // Delete second ADDI
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + firstLine + 1);
 | 
						|
 | 
						|
                                // Replace first ADDI's operand with sum of previous two ADDI's
 | 
						|
                                updateVasm(itVasm, -1, "ADDI", std::to_string(uint8_t(result)));
 | 
						|
                                adjustLabelAddresses(i, firstLine + 1, -2);
 | 
						|
                                adjustVasmAddresses(i, firstLine + 1, -2);
 | 
						|
                            }
 | 
						|
                            break;
 | 
						|
 | 
						|
                            default: break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Arithmetic with zero, (does it's own opcode match)
 | 
						|
                    if(j == AddiZero  ||  j == SubiZero)
 | 
						|
                    {
 | 
						|
                        std::string operand;
 | 
						|
                        size_t pos = itVasm->_code.find(matchSequences[j]._sequence[0]);
 | 
						|
                        if(pos != std::string::npos)
 | 
						|
                        {
 | 
						|
                            operand = itVasm->_code.substr(pos + matchSequences[j]._sequence[0].size());
 | 
						|
                            if(operand == "0" || operand == "0x00")
 | 
						|
                            {
 | 
						|
                                // Migrate internal label to next available instruction
 | 
						|
                                if(!migrateInternalLabel(i, vasmIndex, vasmIndex + 1)) break;
 | 
						|
 | 
						|
                                // Delete ADD/SUB
 | 
						|
                                linesDeleted = true;
 | 
						|
                                itVasm = Compiler::getCodeLines()[i]._vasm.erase(Compiler::getCodeLines()[i]._vasm.begin() + vasmIndex);
 | 
						|
                                adjustLabelAddresses(i, vasmIndex, -2);
 | 
						|
                                adjustVasmAddresses(i, vasmIndex, -2);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if(!linesDeleted)
 | 
						|
                    {
 | 
						|
                        // Only increment iterator if it has not been invalidated
 | 
						|
                        ++itVasm;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        // Optimising can cause new optimising opportunities to present, so restart
 | 
						|
                        goto RESTART_OPTIMISE;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
} |