/* * CiderPress * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. * See the file LICENSE for distribution terms. */ /* * Reformat assembly-language source code. */ #ifndef REFORMAT_ASM_H #define REFORMAT_ASM_H #include "ReformatBase.h" /* * Base class for assembly source conversion. * * We want to tab to certain offsets, either hard coded or found in the source * file. To make this work right we want to buffer each line of output. The * maximum line length is bounded by the editor. */ class ReformatAsm : public ReformatText { public: ReformatAsm(void) : fOutBuf(), fOutBufIndex(0) {} virtual ~ReformatAsm(void) {} void OutputStart(void) { fOutBufIndex = 0; memset(fOutBuf, ' ', kMaxLineLen); } void OutputFinish(void) { Output('\0'); } void Output(char ch) { if (fOutBufIndex < kMaxLineLen) fOutBuf[fOutBufIndex++] = ch; } void Output(const char* str) { int len = strlen(str); if (fOutBufIndex + len > kMaxLineLen) len = kMaxLineLen - fOutBufIndex; if (len > 0) { memcpy(fOutBuf + fOutBufIndex, str, len); fOutBufIndex += len; } } void OutputTab(int posn) { if (posn < kMaxLineLen && posn > fOutBufIndex) fOutBufIndex = posn; else Output(' '); // always at least one } const char* GetOutBuf(void) const { return fOutBuf; } private: enum { kMaxLineLen = 128, }; char fOutBuf[kMaxLineLen+1]; int fOutBufIndex; }; /* * Reformat an S-C Assembler listing into readable text. */ class ReformatSCAssem : public ReformatText { public: ReformatSCAssem(void) {} virtual ~ReformatSCAssem(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; /* this gets called by Integer BASIC converter */ static bool IsSCAssem(const ReformatHolder* pHolder); }; /* * Reformat Merlin listing to have tabs. */ class ReformatMerlin : public ReformatAsm { public: ReformatMerlin(void) {} virtual ~ReformatMerlin(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: static bool IsMerlin(const ReformatHolder* pHolder); }; /* * Reformat LISA v2 (DOS) sources. */ class ReformatLISA2 : public ReformatAsm { public: ReformatLISA2(void) {} virtual ~ReformatLISA2(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: bool IsLISA(const ReformatHolder* pHolder); enum { kOpTab = 9, kAdTab = 13, kComTab = 39, }; void ProcessLine(const uint8_t* buf); }; /* * Reformat LISA v3 (ProDOS) sources. */ class ReformatLISA3 : public ReformatAsm { public: ReformatLISA3(void) : fSymTab(NULL), fSymCount(0) {} virtual ~ReformatLISA3(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; static bool IsLISA(const ReformatHolder* pHolder); private: typedef enum OperandResult { kResultUnknown = 0, kResultFailed, kResultGotoOutOprtr, kResultGotoOutOprnd, } OperandResult; void ProcessLine(const uint8_t* codePtr, int len); void ConvertOperand(uint8_t mnemonic, const uint8_t** pCodePtr, int* pLen); OperandResult PrintNum(int adrsMode, uint8_t val, const uint8_t** pCodePtr, int* pLen); OperandResult PrintComplexOperand(uint8_t opr, const uint8_t** pCodePtr, int* pLen); void PrintSymEntry(int ent); void PrintMnemonic(uint8_t val); void PrintBin(uint8_t val); void PrintComment(int adrsMode, const uint8_t* ptr, int len); enum { kHeaderLen = 4, kOpTab = 9, kAdTab = 18, kComTab = 40, }; /* token constants, from LISA.MNEMONICS */ enum { kLCLTKN = 0xF0, kLBLTKN = 0xFA, // 0xFB used to indicate "second half" of symbol table kMACTKN = 0xFC, // 0xFD used to indicate "second half" of symbol table kCMNTTKN = 0xFE, kSN = 0x00, kSS = 0xB0, kGROUP1 = 0x00, kGROUP2 = 0x0b, kGROUP3 = 0x11, kGROUP4 = 0x24, kGROUP5 = 0x29, kGROUP6 = 0x34, kGROUP7 = 0x39, kGROUP8 = 0x3f, kGROUP9 = 0x4a, }; const uint8_t* fSymTab; uint16_t fSymCount; }; /* * Reformat LISA v4/v5 (ProDOS and GS/OS) sources. */ class ReformatLISA4 : public ReformatAsm { public: ReformatLISA4(void) : fSymTab(NULL), fSymCount(0), fOpTab(0), fAdTab(0), fComTab(0), fCpuType(0) {} virtual ~ReformatLISA4(void) { delete[] fSymTab; } virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; static bool IsLISA(const ReformatHolder* pHolder); private: enum { kHeaderLen = 16, }; /* token constants, from MNEMONICS.A */ enum { kBigndec4_tkn = 0x00, kBignhex4_tkn = 0x01, kBignbin4_tkn = 0x02, kBignhexs_tkn = 0x03, kBignstring_tkn = 0x04, kDec1_tkn = 0x1a, kDec2_tkn = 0x1b, kHex1_tkn = 0x1c, kHex2_tkn = 0x1d, kBin1_tkn = 0x1e, kBin2_tkn = 0x1f, kBign_tkn = 0x33, kDec3_tkn = 0x34, kHex3_tkn = 0x35, kBin3_tkn = 0x36, kcABS_tkn = 0x37, kcLONG_tkn = 0x38, kMVN_tkn = 0x41, kMVP_tkn = 0x42, kMacE_tkn = 0x5e, kStr31_tkn = 0x7f, kSS = 0x90, //kGROUP1_tkns = 0x01, //kGROUP2_tkns = 0x0c, kGROUP3_tkns = 0x12, //kGROUP4_tkns = 0x29, kGROUP5_tkns = 0x30, kGROUP6_tkns = 0x43, //kGROUP7_tkns = 0x4a, //kGROUP8_tkns = 0x51, //kGROUP9_tkns = 0x5f, kLocalTKN = 0xf0, kLabelTKN = 0xfa, kMacroTKN = 0xfc, kErrlnTKN = 0xfd, // "is BlankTKN by itself" kBlankTKN = 0xfd, kCommentTKN = 0xfe, kComntStarTKN = 0xfe, kComntSemiTKN = 0xff, }; typedef enum OperandResult { kResultUnknown = 0, kResultFailed, kResultGotoOutOprtr, kResultGotoOutOprnd, } OperandResult; void ProcessLine(const uint8_t* codePtr, int len); void ConvertOperand(uint8_t mnemonic, const uint8_t** pCodePtr, int* pLen); void PrintSymEntry(int ent); OperandResult PrintNum(uint8_t opr, const uint8_t** pCodePtr, int* pLen); OperandResult PrintComplexOperand(uint8_t opr, const uint8_t** pCodePtr, int* pLen); void PrintDec(int count, const uint8_t** pCodePtr, int* pLen); void PrintHex(int count, const uint8_t** pCodePtr, int* pLen); void PrintBin(int count, const uint8_t** pCodePtr, int* pLen); const uint8_t** fSymTab; uint16_t fSymCount; uint8_t fOpTab; uint8_t fAdTab; uint8_t fComTab; uint8_t fCpuType; }; #endif /*REFORMAT_ASM_H*/