Merge pull request #20 from marketideas/sgq_qasm_main

Sgq qasm main
This commit is contained in:
marketideas 2019-11-19 13:45:40 -08:00 committed by GitHub
commit 661de97c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 58 deletions

37
README
View File

@ -1,29 +1,38 @@
Merlin Compatible assembler/linker (and more) for linux
This project is FAR from complete...as I have just gotten it to compile all 256 65816 opcodes.
The program will read/compile linux based Merlin syntax files (.s), as well as original Merlin 8/16/16+ files in Merlin format
(high bit set), compressed spaces, and only a <CR> to end lines. I plan on adding a mode that will process and convert to linux style so
files can be converted for easy editing under linux.
Merlin32 is great, but there are aspects of it that I don't like (always outputting assembly status and creating .txt file listings, etc)
Update (11/19/2019) - All code generating opcodes/psuedo-ops complete.
Along time ago, in the mid 1980's I wrote a Merlin compatible assembler and programming shell (with the help of Lane Roathe) for the Apple //GS
Recently, Lane sent me the source code to that assembler. Unfortunately, because of some of the features we added to the assembler, it will not
compile under Merlin or Merlin32. (We actually used qasm to build qasm).
The program will read/compile linux based Merlin syntax files (.s), as well as original Merlin
8/16/16+ files in Merlin format
(high bit set), compressed spaces, and only a <CR> to end lines. I plan on adding a mode that
will process and convert to linux style so files can be converted for easy editing under linux.
This project will be a linux compatible version, that will compile/link the original source. However, due to speed and everything 'linux'
I doubt the original will be used much.
Merlin32 is great, but there are aspects of it that I don't like (always outputting assembly
status and creating .txt file listings, etc)
I also would like to interface with the CiderPress library to allow output from the assembler/linker to write files directly to Prodos
based .2MG (or other) images. That way, after a compile, the code under test can be immediately run from a GS emulator.
Along time ago, in the mid 1980's I wrote a Merlin compatible assembler and programming shell
(with the help of Lane Roathe) for the Apple //GS
Recently, Lane sent me the source code to that assembler. Unfortunately, because of some of the
features we added to the assembler, it will not compile under Merlin or Merlin32. (We actually used
qasm to build qasm).
This project will be a linux compatible version, that will compile/link the original source.
However, due to speed and everything 'linux' I doubt the original will be used much.
I also would like to interface with the CiderPress library to allow output from the assembler/linker
to write files directly to Prodos based .2MG (or other) images. That way, after a compile, the code
under test can be immediately run from a GS emulator.
This early version relies on the Poco Foundation libraries. You must have these installed.
Additionally, this repo relies on another repo here called 'libpal'. Both repositories must be cloned at the same level.
Additionally, this repo relies on another repo here called 'libpal'. Both repositories must
be cloned at the same level.
libpal does not have to be built. The 'qasm' compile will build all of those source files.
'cmake' is used to build the Makefiles. There is a generic Makefile in the base directory that does all of the 'cmake' stuff for you.
(in a 'build' directory)
'cmake' is used to build the Makefiles. There is a generic Makefile in the base directory that does
all of the 'cmake' stuff for you. (in a 'build' directory)
For example:
mkdir workdir

70
asm.cpp
View File

@ -205,7 +205,7 @@ void CLASS::print(uint32_t lineno)
{
pcol += printf(" ");
}
if (isDebug() > 2)
if (isDebug() > 1)
{
pcol += printf("%s ", operand.c_str());
}
@ -1325,40 +1325,56 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
}
}
switch (line.expr_shift)
if (line.addressmode == syn_imm)
{
case '<':
line.expr_value &= 0xFF;
line.flags |= FLAG_DP;
break;
case '>':
line.expr_value >>= 8;
line.expr_value &= 0xFFFF;
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
//printf("immediate mode\n");
switch (line.expr_shift)
{
case '<':
line.expr_value &= 0xFF;
break;
case '>':
line.expr_value >>= 8;
line.expr_value &= 0xFFFF;
break;
case '^':
line.expr_value = (line.expr_value >> 16) & 0xFFFF;
break;
case '|':
break;
}
}
else
{
switch (line.expr_shift)
{
case '<':
line.flags |= FLAG_DP;
break;
case '>':
if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
// bug in M32 or not, do what it does
line.flags |= FLAG_FORCEABS;
}
else
{
line.flags |= FLAG_FORCELONG;
}
break;
case '|':
line.flags |= FLAG_FORCEABS;
}
break;
case '^':
line.expr_value = (line.expr_value >> 16) & 0xFFFF;
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
line.flags |= FLAG_FORCEABS;
}
break;
case '|':
if ((line.syntax & SYNTAX_MERLIN32) != SYNTAX_MERLIN32)
{
line.flags |= FLAG_FORCELONG;
}
break;
break;
case '^':
//line.flags |= FLAG_FORCELONG;
break;
}
}
if (line.expr_value >= 0x100)
{
line.flags |= FLAG_FORCEABS;
}
auto itr = opcodes.find(Poco::toUpper(op));
if (itr != opcodes.end())
{

View File

@ -95,17 +95,15 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym)
{
res = -1;
if (syntax==SYNTAX_MERLIN)
{
char buff[32];
sprintf(buff,"$%08X",line.expr_value);
std::string s1=buff;
s = addVariable(line.lable, s1, true);
}
else
{
s = addVariable(line.lable, line.operand, true);
}
#if 1
char buff[32];
sprintf(buff, "$%08X", line.expr_value);
std::string s1 = buff;
s = addVariable(line.lable, s1, true);
#else
// do this if you want to do this more as a #define
s = addVariable(line.lable, line.operand, true);
#endif
if (s != NULL)
{
res = 0;
@ -295,6 +293,19 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym)
res = 1 + sym.stype;
if (pass > 0)
{
switch(line.expr_shift)
{
case '^':
line.expr_value=(line.expr_value>>16)&0xFFFF;
break;
case '<':
line.expr_value=(line.expr_value)&0xFF;
break;
case '>':
line.expr_value=(line.expr_value>>8)&0xFFFF;
break;
}
//line.setError(errIncomplete);
setOpcode(line, sym.opcode);
for (i = 0; i < (res - 1); i++)
@ -770,13 +781,13 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym)
{
lastcarry = false;
}
else if (sym.opcode==0xFB) // XCE
else if (sym.opcode == 0xFB) // XCE
{
if (trackrep)
{
if (lastcarry)
{
mx=0x03;
mx = 0x03;
}
}
}

View File

@ -839,6 +839,18 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
a.PC.currentpc = a.PC.orgsave;
line.startpc = a.PC.orgsave;
}
#if 0
// Merlin32 seems to have a bug where ORG seems like it can only be 16 bits
if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32)
{
// so clear the bank word in all variables
a.PC.orgsave &= 0xFFFF;
a.PC.currentpc&=0xFFFF;
line.startpc &=0xFFFF;
}
#endif
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_SAV:

View File

@ -4,10 +4,10 @@ logdir=/var/log/mylog
logfile=mylog.log
[option]
debug=1
;==debug must be an integer. Code can use this as a level
;debug=0
nocolor=false
;syntax=merlin32
;debug must be an integer. Code can use this as a level
[application]
timezone=America/Los_Angeles
@ -33,8 +33,7 @@ merlinerrors=true
symcolumns=3
[reformat]
tabs=12; 18; 30
;tabs=0;0;0
tabs=12;18;30