qasm/asm.h

302 lines
6.4 KiB
C
Raw Normal View History

2019-11-11 23:56:03 +00:00
#pragma once
#include "app.h"
#define OPHANDLER(ACB) std::bind(ACB, this, std::placeholders::_1, std::placeholders::_2)
#define MODE_6502 0
#define MODE_65C02 1
#define MODE_65816 2
#define SYNTAX_MERLIN 0
#define SYNTAX_APW 1
#define SYNTAX_ORCA 2
#define OP_6502 0x01
#define OP_65C02 0x02
#define OP_65816 0x04
#define OP_PSUEDO 0x08
#define OP_SPECIAL 0x20
#define OP_CLASS0 0x0000
#define OP_CLASS1 0x0100
#define OP_CLASS2 0x0200
#define OP_CLASS3 0x0300
#define OP_CLASS4 0x0400
#define OP_STD (0x1000 | OP_CLASS1 | OP_6502)
#define OP_ASL (0x2000 | OP_CLASS2 | OP_6502)
#define OP_STX (0x3000 | OP_CLASS2 | OP_6502)
#define OP_C0 (0x4000 | OP_CLASS0 | OP_6502)
enum asmErrors
{
errNone,
errWarn,
errIncomplete,
errFatal,
errBadAddressMode,
errBadOpcode,
errIncompatibleOpcode,
errBadByteCount,
2019-11-12 03:51:26 +00:00
errBadBranch,
errUnimplemented,
errForwardReference,
2019-11-12 08:15:47 +00:00
errNoRedefinition,
2019-11-12 18:13:15 +00:00
errBadOperand,
errDupSymbol,
2019-11-11 23:56:03 +00:00
errMAX
};
#ifdef ADD_ERROR_STRINGS
const std::string errStrings[errMAX + 1] =
{
2019-11-11 23:56:03 +00:00
"No Error",
"Warning",
"Unfinished Opcode",
"Fatal",
"Unsupported Addressing Mode",
"Unknown Opcode",
2019-11-12 03:51:26 +00:00
"Opcode not available under CPU mode",
2019-11-11 23:56:03 +00:00
"Byte output differs between passes",
2019-11-12 08:15:47 +00:00
"Relative branch offset too large",
2019-11-12 03:51:26 +00:00
"Unimplemented Instruction",
2019-11-12 08:15:47 +00:00
"Forward Reference to symbol",
"Unable to redefine symbol",
2019-11-12 18:13:15 +00:00
"Unable to evaluate",
"Duplicate Symbol",
2019-11-12 08:15:47 +00:00
""
2019-11-11 23:56:03 +00:00
};
#else
2019-11-12 18:13:15 +00:00
extern const std::string errStrings[errMAX];
2019-11-11 23:56:03 +00:00
extern uint8_t opCodeCompatibility[256];
#endif
enum
{
syn_err = -1, // error - not recognized
syn_none = 0, // should never be returned 0
syn_implied, // no operand 1
syn_s, // expr,s 2
syn_sy, // (expr,s),y 3
syn_imm, // #expr 4
syn_diix, // (expr,x) 5
syn_diiy, // (expr),y 6
syn_di, // (expr) 7
syn_iyl, // [expr],y 8
syn_dil, // [expr] 9
syn_absx, // expr,x 10
syn_absy, // expr,y 11
syn_bm, // block move 12
syn_abs, // expr 13
syn_MAX
};
#define FLAG_LONGADDR 0x01
2019-11-13 04:32:10 +00:00
class TOriginSection
{
public:
uint32_t origin;
uint32_t currentpc;
uint32_t totalbytes;
};
2019-11-11 23:56:03 +00:00
class MerlinLine
{
public:
uint8_t syntax;
std::string lable;
std::string printlable;
2019-11-11 23:56:03 +00:00
std::string opcode;
std::string opcodelower;
std::string operand;
std::string operand_expr;
2019-11-12 03:51:26 +00:00
std::string operand_expr2;
2019-11-11 23:56:03 +00:00
std::string comment;
std::string addrtext;
2019-11-12 08:15:47 +00:00
uint8_t linemx;
bool showmx;
2019-11-12 03:51:26 +00:00
uint32_t lineno;
2019-11-11 23:56:03 +00:00
uint32_t flags;
uint16_t opflags;
2019-11-12 03:51:26 +00:00
int32_t startpc;
2019-11-11 23:56:03 +00:00
uint32_t addressmode;
2019-11-12 03:51:26 +00:00
int32_t expr_value;
2019-11-11 23:56:03 +00:00
uint32_t errorcode;
2019-11-12 18:13:15 +00:00
std::string errorText;
2019-11-11 23:56:03 +00:00
uint16_t pass0bytect;
uint16_t bytect;
uint16_t outbytect;
std::vector<uint8_t> outbytes;
public:
MerlinLine();
MerlinLine(std::string line);
void clear();
void set(std::string line);
void print(uint32_t lineno);
void setError(uint32_t ecode);
};
class TFileProcessor
{
protected:
uint8_t syntax;
2019-11-12 03:51:26 +00:00
uint64_t starttime;
2019-11-11 23:56:03 +00:00
public:
uint32_t errorct;
2019-11-11 23:56:03 +00:00
TFileProcessor();
virtual ~TFileProcessor();
virtual int processfile(std::string &p);
virtual void init(void);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
virtual void errorOut(uint16_t code);
};
class TMerlinConverter : public TFileProcessor
{
protected:
uint8_t tabs[10];
std::vector<MerlinLine> lines;
2019-11-13 04:32:10 +00:00
public:
TMerlinConverter();
virtual ~TMerlinConverter();
virtual void init(void);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
};
2019-11-11 23:56:03 +00:00
class TSymbol;
typedef int (*TOpCB)(MerlinLine &line, TSymbol &sym);
typedef std::function<int (MerlinLine &line, TSymbol &sym)> TOpCallback;
class TSymbol
{
public:
std::string namelc;
std::string name;
std::string text;
2019-11-11 23:56:03 +00:00
uint32_t value;
uint16_t stype;
uint8_t opcode;
2019-11-12 08:15:47 +00:00
bool used;
2019-11-11 23:56:03 +00:00
TOpCallback cb;
Poco::HashMap<std::string, TSymbol>locals;
TSymbol()
{
clear();
2019-11-11 23:56:03 +00:00
};
void clear(void)
{
value = 0;
used = false;
text = "";
name = "";
namelc = "";
stype = 0;
opcode = 0;
locals.clear();
}
2019-11-11 23:56:03 +00:00
};
class TPsuedoOp;
2019-11-11 23:56:03 +00:00
class T65816Asm : public TFileProcessor
{
public:
// options
2019-11-11 23:56:03 +00:00
bool casesen;
bool listing;
bool showmx;
bool trackrep;
uint8_t mx;
uint8_t cpumode; // 0=6502, 1=65C02, 2=65816
bool passcomplete;
bool relocatable;
2019-11-12 03:51:26 +00:00
bool skiplist; // used if lst is on, but LST opcode turns it off
2019-11-11 23:56:03 +00:00
uint32_t lineno;
2019-11-13 04:32:10 +00:00
//uint32_t origin;
//uint32_t currentpc;
2019-11-12 08:15:47 +00:00
std::string savepath;
2019-11-11 23:56:03 +00:00
TSymbol *currentsym;
std::vector<MerlinLine> lines;
Poco::HashMap<std::string, TSymbol>opcodes;
Poco::HashMap<std::string, TSymbol> macros;
Poco::HashMap<std::string, TSymbol> symbols;
Poco::HashMap<std::string, TSymbol> variables;
2019-11-13 04:32:10 +00:00
TOriginSection PC;
std::stack<TOriginSection> PCstack;
TPsuedoOp *psuedoops;
2019-11-11 23:56:03 +00:00
uint16_t pass;
T65816Asm();
virtual ~T65816Asm();
virtual void init(void);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
void insertOpcodes(void);
void pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallback cb);
int callOpCode(std::string op, MerlinLine &line);
TSymbol *findSymbol(std::string sym);
TSymbol *addSymbol(std::string sym, uint32_t val, bool replace);
TSymbol *findVariable(std::string sym);
TSymbol *addVariable(std::string sym, std::string val, bool replace);
2019-11-11 23:56:03 +00:00
void initpass(void);
2019-11-12 08:15:47 +00:00
void showSymbolTable(bool alpha);
void showVariables(void);
2019-11-11 23:56:03 +00:00
int evaluate(std::string expr, int64_t &value);
int parseOperand(MerlinLine &line);
int getAddrMode(MerlinLine &line);
void setOpcode(MerlinLine &line, uint8_t op);
int doPSEUDO(MerlinLine &line, TSymbol &sym);
int doEND(MerlinLine &line, TSymbol &sym);
int doBase6502(MerlinLine &line, TSymbol &sym);
int doBRANCH(MerlinLine &line, TSymbol &sym);
int doJMP(MerlinLine &line, TSymbol &sym);
int doAddress(MerlinLine &line, TSymbol &sym);
int doNoPattern(MerlinLine &line, TSymbol &sym);
2019-11-12 03:51:26 +00:00
int doMVN(MerlinLine &line, TSymbol &sym);
2019-11-12 08:15:47 +00:00
int doPER(MerlinLine &line, TSymbol &sym);
2019-11-11 23:56:03 +00:00
int doEQU(MerlinLine &line, TSymbol &sym);
int doXC(MerlinLine &line, TSymbol &sym);
int doMX(MerlinLine &line, TSymbol &sym);
int doBYTE(MerlinLine &line, TSymbol &sym);
int doUNK(MerlinLine &line, TSymbol &sym);
};
class T65816Link : public TFileProcessor
{
public:
T65816Link();
virtual ~T65816Link();
virtual void init(void);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
};