+/* common */
+#include "check.h"
+
/* b6502 */
#include "codeseg.h"
#include "dataseg.h"
SymTable* SymTab;
SymEntry* Entry;
- /* Output the global code and data segments */
- MergeCodeLabels (CS);
+ /* Output the data segment (the global code segment should be empty) */
OutputDataSeg (F, DS);
- OutputCodeSeg (F, CS);
+ CHECK (GetCodeSegEntries (CS) == 0);
/* Output all global or referenced functions */
SymTab = GetGlobalSymTab ();
Entry = SymTab->SymHead;
while (Entry) {
- if (IsTypeFunc (Entry->Type) &&
- (Entry->Flags & SC_DEF) != 0 &&
+ if (IsTypeFunc (Entry->Type) &&
+ (Entry->Flags & SC_DEF) != 0 &&
(Entry->Flags & (SC_REF | SC_EXTERN)) != 0) {
/* Function which is defined and referenced or extern */
PrintFunctionHeader (F, Entry);
MergeCodeLabels (Entry->V.F.CS);
+ fprintf (F, "; Data segment for function %s:\n", Entry->Name);
OutputDataSeg (F, Entry->V.F.DS);
+ fprintf (F, "; Code segment for function %s:\n", Entry->Name);
OutputCodeSeg (F, Entry->V.F.CS);
}
Entry = Entry->NextSym;
case CF_STATIC:
/* Static memory cell */
- sprintf (lbuf, "L%04X+%u", (unsigned)(label & 0xFFFF), offs);
+ sprintf (lbuf, "%s+%u", LocalLabelName (label), offs);
break;
case CF_EXTERNAL:
-void g_usecode (void)
-/* Switch to the code segment */
-{
- UseSeg (SEG_CODE);
-}
-
-
-
void g_userodata (void)
/* Switch to the read only data segment */
{
-void g_defloclabel (unsigned label)
-/* Define a local label */
+void g_defcodelabel (unsigned label)
+/* Define a local code label */
{
- if (CurSeg == SEG_CODE) {
- AddLocCodeLabel (CS, LocalLabelName (label));
- } else {
- AddDataSegLine (DS, "%s:", LocalLabelName (label));
- }
+ AddCodeLabel (CS, LocalLabelName (label));
+}
+
+
+
+void g_defdatalabel (unsigned label)
+/* Define a local data label */
+{
+ AddDataSegLine (DS, "%s:", LocalLabelName (label));
}
/*****************************************************************************/
-/* Functions handling global labels */
+/* Functions handling global labels */
/*****************************************************************************/
void g_defgloblabel (const char* Name)
/* Define a global label with the given name */
{
- if (CurSeg == SEG_CODE) {
- /* ##### */
- char Buf[64];
- xsprintf (Buf, sizeof (Buf), "_%s", Name);
- AddExtCodeLabel (CS, Buf);
- } else {
- AddDataSegLine (DS, "_%s:", Name);
- }
+ /* Global labels are always data labels */
+ AddDataSegLine (DS, "_%s:", Name);
}
g_space (Bytes);
ldyconst (Bytes - 1);
ldxconst (Bytes);
- g_defloclabel (Label);
+ g_defcodelabel (Label);
AddCodeSegLine (CS, "lda regbank%+d,x", RegOffs-1);
AddCodeSegLine (CS, "sta (sp),y");
AddCodeSegLine (CS, "dey");
AddCodeSegLine (CS, "dex");
- AddCodeSegLine (CS, "bne L%04X", Label);
+ AddCodeSegLine (CS, "bne %s", LocalLabelName (Label));
}
unsigned Label = GetLocalLabel ();
ldyconst (StackOffs+Bytes-1);
ldxconst (Bytes);
- g_defloclabel (Label);
+ g_defcodelabel (Label);
AddCodeSegLine (CS, "lda (sp),y");
AddCodeSegLine (CS, "sta regbank%+d,x", RegOffs-1);
AddCodeSegLine (CS, "dey");
AddCodeSegLine (CS, "dex");
- AddCodeSegLine (CS, "bne L%04X", Label);
+ AddCodeSegLine (CS, "bne %s", LocalLabelName (Label));
}
}
case CF_INT:
if (flags & CF_CONST) {
if (val == 1) {
- label = GetLocalLabel ();
+ unsigned L = GetLocalLabel ();
AddCodeSegLine (CS, "inc %s", lbuf);
- AddCodeSegLine (CS, "bne L%04X", (int)label);
+ AddCodeSegLine (CS, "bne %s", LocalLabelName (L));
AddCodeSegLine (CS, "inc %s+1", lbuf);
- g_defloclabel (label);
+ g_defcodelabel (L);
AddCodeSegLine (CS, "lda %s", lbuf); /* Hmmm... */
AddCodeSegLine (CS, "ldx %s+1", lbuf);
} else {
AddCodeSegLine (CS, "adc %s", lbuf);
AddCodeSegLine (CS, "sta %s", lbuf);
if (val < 0x100) {
- label = GetLocalLabel ();
- AddCodeSegLine (CS, "bcc L%04X", (int)label);
+ unsigned L = GetLocalLabel ();
+ AddCodeSegLine (CS, "bcc %s", LocalLabelName (L));
AddCodeSegLine (CS, "inc %s+1", lbuf);
- g_defloclabel (label);
+ g_defcodelabel (L);
AddCodeSegLine (CS, "ldx %s+1", lbuf);
} else {
AddCodeSegLine (CS, "lda #$%02X", (unsigned char)(val >> 8));
AddCodeSegLine (CS, "sbc #$%02X", (unsigned char)val);
AddCodeSegLine (CS, "sta %s", lbuf);
if (val < 0x100) {
- label = GetLocalLabel ();
- AddCodeSegLine (CS, "bcs L%04X", (unsigned)label);
+ unsigned L = GetLocalLabel ();
+ AddCodeSegLine (CS, "bcs %s", LocalLabelName (L));
AddCodeSegLine (CS, "dec %s+1", lbuf);
- g_defloclabel (label);
+ g_defcodelabel (L);
AddCodeSegLine (CS, "ldx %s+1", lbuf);
} else {
AddCodeSegLine (CS, "lda %s+1", lbuf);
void g_restore (unsigned flags)
-/* Copy hold register to P. */
+/* Copy hold register to primary. */
{
/* Check the size and determine operation */
switch (flags & CF_TYPE) {
void g_test (unsigned flags)
-/* Force a test to set cond codes right */
+/* Test the value in the primary and set the condition codes */
{
switch (flags & CF_TYPE) {
void g_jump (unsigned Label)
/* Jump to specified internal label number */
{
- AddCodeSegLine (CS, "jmp L%04X", Label);
+ AddCodeSegLine (CS, "jmp %s", LocalLabelName (Label));
}
case CF_CHAR:
case CF_INT:
- AddCodeSegLine (CS, ".word $%04X, L%04X",
+ AddCodeSegLine (CS, ".word $%04X, %s",
(unsigned)(val & 0xFFFF),
- (unsigned)(label & 0xFFFF));
+ LocalLabelName (label));
break;
case CF_LONG:
AddCodeSegLine (CS, ".dword $%08lX", val);
- AddCodeSegLine (CS, ".word L%04X", label & 0xFFFF);
+ AddCodeSegLine (CS, ".word %s", LocalLabelName (label));
break;
default:
void g_truejump (unsigned flags, unsigned label)
/* Jump to label if zero flag clear */
{
- if (flags & CF_SHORT) {
- AddCodeSegLine (CS, "bne L%04X", label);
- } else {
- AddCodeSegLine (CS, "jne L%04X", label);
- }
+ AddCodeSegLine (CS, "jne %s", LocalLabelName (label));
}
void g_falsejump (unsigned flags, unsigned label)
/* Jump to label if zero flag set */
{
- if (flags & CF_SHORT) {
- AddCodeSegLine (CS, "beq L%04X", label);
- } else {
- AddCodeSegLine (CS, "jeq L%04X", label);
- }
+ AddCodeSegLine (CS, "jeq %s", LocalLabelName (label));
}
/* Generate the strlen code */
AddCodeSegLine (CS, "ldy #$FF");
- g_defloclabel (label);
+ g_defcodelabel (label);
AddCodeSegLine (CS, "iny");
AddCodeSegLine (CS, "lda %s,y", lbuf);
- AddCodeSegLine (CS, "bne L%04X", label);
+ AddCodeSegLine (CS, "bne %s", LocalLabelName (label));
AddCodeSegLine (CS, "tax");
AddCodeSegLine (CS, "tya");
AddCodeSegLine (CS, "sta ptr1");
AddCodeSegLine (CS, "stx ptr1+1");
AddCodeSegLine (CS, "ldy #$FF");
- g_defloclabel (label);
+ g_defcodelabel (label);
AddCodeSegLine (CS, "iny");
AddCodeSegLine (CS, "lda (ptr1),y");
- AddCodeSegLine (CS, "bne L%04X", label);
+ AddCodeSegLine (CS, "bne %s", LocalLabelName (label));
AddCodeSegLine (CS, "tax");
AddCodeSegLine (CS, "tya");
}
#define CF_TEST 0x0080 /* Test value */
#define CF_FIXARGC 0x0100 /* Function has fixed arg count */
#define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */
-#define CF_SHORT 0x0400 /* Use short addressing */
#define CF_REG 0x0800 /* Value is in primary register */
/* Type of static address */
void g_popseg (void);
/* Restore the old segments */
-void g_usecode (void);
-/* Switch to the code segment */
-
void g_userodata (void);
/* Switch to the read only data segment */
-void g_defloclabel (unsigned label);
-/* Define a local label */
+void g_defcodelabel (unsigned label);
+/* Define a local code label */
+
+void g_defdatalabel (unsigned label);
+/* Define a local data label */
void g_save (unsigned flags);
+/* Copy primary register to hold register. */
+
void g_restore (unsigned flags);
+/* Copy hold register to primary. */
void g_cmp (unsigned flags, unsigned long val);
/* Immidiate compare. The primary register will not be changed, Z flag
*/
void g_test (unsigned flags);
+/* Test the value in the primary and set the condition codes */
+
void g_push (unsigned flags, unsigned long val);
+/* Push the primary register or a constant value onto the stack */
+
void g_swap (unsigned flags);
+/* Swap the primary register and the top of the stack. flags give the type
+ * of *both* values (must have same size).
+ */
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
/* Call the specified subroutine name */
/* Label flags, bitmapped */
#define LF_DEF 0x0001U /* Label was defined */
-#define LF_EXT 0x0002U /* Label is external */
/* Label structure */
typedef struct CodeLabel CodeLabel;
}
/* If the instruction is a branch, check for the label and generate it
- * if it does not exist.
+ * if it does not exist. In case of a PC relative branch (*+x) we will
+ * not generate a label, because the target label will not be defined.
*/
Label = 0;
- if ((OPC->Info & CI_MASK_BRA) == CI_BRA) {
+ if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Expr[0] != '*') {
unsigned Hash;
- /* ### Check for local labels here */
+ /* Addressing mode must be alsobute or something is really wrong */
CHECK (AM == AM_ABS);
+
+ /* Addressing mode is a branch/jump */
AM = AM_BRA;
+
+ /* Generate the hash over the label, then search for the label */
Hash = HashStr (Expr) % CS_LABEL_HASH_SIZE;
Label = FindCodeLabel (S, Expr, Hash);
+
+ /* If we don't have the label, it's a forward ref - create it */
if (Label == 0) {
/* Generate a new label */
Label = NewCodeSegLabel (S, Expr, Hash);
-CodeLabel* AddCodeLabel (CodeSeg* S, const char* Name)
+void AddCodeLabel (CodeSeg* S, const char* Name)
/* Add a code label for the next instruction to follow */
{
/* Calculate the hash from the name */
/* We do now have a valid label. Remember it for later */
CollAppend (&S->Labels, L);
-
- /* Return the label */
- return L;
-}
-
-
-
-void AddExtCodeLabel (CodeSeg* S, const char* Name)
-/* Add an external code label for the next instruction to follow */
-{
- /* Add the code label */
- CodeLabel* L = AddCodeLabel (S, Name);
-
- /* Mark it as external label */
- L->Flags |= LF_EXT;
-}
-
-
-
-void AddLocCodeLabel (CodeSeg* S, const char* Name)
-/* Add a local code label for the next instruction to follow */
-{
- /* Add the code label */
- AddCodeLabel (S, Name);
}
continue;
}
- /* We have at least one label. Use the first one as reference label.
- * We don't have a notification for global labels for now, and using
- * the first one will also keep the global function labels, since these
- * are inserted at position 0.
- */
+ /* We have at least one label. Use the first one as reference label. */
RefLab = CollAt (&E->Labels, 0);
/* Walk through the remaining labels and change references to these
}
- /* If the label is not an external label, we may remove the
- * label completely.
- */
-#if 0
- if ((L->Flags & LF_EXT) == 0) {
- FreeCodeLabel (L);
- CollDelete (&E->Labels, J);
- }
-#endif
+ /* Remove the label completely. */
+ FreeCodeLabel (L);
+ CollDelete (&E->Labels, J);
}
- /* The reference label is the only remaining label. If it is not an
- * external label, check if there are any references to this label,
- * and delete it if this is not the case.
+ /* The reference label is the only remaining label. Check if there
+ * are any references to this label, and delete it if this is not
+ * the case.
*/
-#if 0
- if ((RefLab->Flags & LF_EXT) == 0 && CollCount (&RefLab->JumpFrom) == 0) {
+ if (CollCount (&RefLab->JumpFrom) == 0) {
/* Delete the label */
FreeCodeLabel (RefLab);
/* Remove it from the list */
CollDelete (&E->Labels, 0);
}
-#endif
}
}
void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
/* Add a line to the given code segment */
-void AddExtCodeLabel (CodeSeg* S, const char* Name);
-/* Add an external code label for the next instruction to follow */
-
-void AddLocCodeLabel (CodeSeg* S, const char* Name);
-/* Add a local code label for the next instruction to follow */
+void AddCodeLabel (CodeSeg* S, const char* Name);
+/* Add a code label for the next instruction to follow */
void AddCodeSegHint (CodeSeg* S, unsigned Hint);
/* Add a hint for the preceeding instruction */
}
/* Define the false jump label here */
- g_defloclabel (lab);
+ g_defcodelabel (lab);
/* Define the label */
lval->e_flags = E_MEXPR;
DoneLab = GetLocalLabel ();
g_getimmed (CF_INT | CF_CONST, 0, 0); /* Load FALSE */
g_falsejump (CF_NONE, DoneLab);
- g_defloclabel (TrueLab);
+ g_defcodelabel (TrueLab);
g_getimmed (CF_INT | CF_CONST, 1, 0); /* Load TRUE */
- g_defloclabel (DoneLab);
+ g_defcodelabel (DoneLab);
}
return k;
}
labt = GetLocalLabel ();
ConsumeColon ();
g_jump (labt);
- g_defloclabel (labf);
+ g_defcodelabel (labf);
expression1 (&lval3);
/* Check if any conversions are needed, if so, do them.
g_jump (labf); /* Jump around code */
/* The jump for expr2 goes here */
- g_defloclabel (labt);
+ g_defcodelabel (labt);
/* Create the typecast code for expr2 */
Mark2 = GetCodePos (); /* Remember position */
RemoveCode (Mark1); /* Remove code */
} else {
/* We have typecast code, output label */
- g_defloclabel (labf);
+ g_defcodelabel (labf);
labt = 0; /* Mark other label as invalid */
}
/* If we don't have the label defined until now, do it */
if (labt) {
- g_defloclabel (labt);
+ g_defcodelabel (labt);
}
/* Setup the target expression */
{
if (F->Reserved > 0) {
- /* Switch to the code segment */
- g_usecode ();
-
/* Create space on the stack */
g_space (F->Reserved);
#endif
/* Output the function exit code label */
- g_defloclabel (GetRetLab (CurrentFunc));
+ g_defcodelabel (GetRetLab (CurrentFunc));
/* Restore the register variables */
RestoreRegVars (!IsVoidFunc);
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF);
/* Emit the jump label */
- g_defloclabel (Entry->V.Label);
+ g_defcodelabel (Entry->V.Label);
/* Eat the ident and colon */
NextToken ();
}
/* Define the label */
- g_defloclabel (LiteralPoolLabel);
+ g_defdatalabel (LiteralPoolLabel);
/* Translate the buffer contents into the target charset */
TranslateLiteralPool (0);
/* Output the buffer data */
g_defbytes (LiteralPoolBuf, LiteralPoolOffs);
-
- /* Switch back to the code segment */
- g_usecode ();
}
/* Allocate previously reserved local space */
AllocLocalSpace (CurrentFunc);
- /* Switch to the code segment. */
- g_usecode ();
-
/* Skip the '=' */
NextToken ();
/* Define the variable label */
SymData = GetLocalLabel ();
- g_defloclabel (SymData);
+ g_defdatalabel (SymData);
/* Reserve space for the data */
g_res (Size);
struct expent lval;
- /* Switch to the code segment. */
- g_usecode ();
-
/* Skip the '=' */
NextToken ();
/* Define the variable label */
SymData = GetLocalLabel ();
- g_defloclabel (SymData);
+ g_defdatalabel (SymData);
/* Skip the '=' */
NextToken ();
/* Define the variable label */
SymData = GetLocalLabel ();
- g_defloclabel (SymData);
+ g_defdatalabel (SymData);
/* Reserve space for the data */
g_res (Size);
/* Be sure to allocate any reserved space for locals */
AllocLocalSpace (CurrentFunc);
- /* In case we switched away from code segment, switch back now */
- g_usecode ();
-
/* In case we've allocated local variables in this block, emit a call to
* the stack checking routine if stack checks are enabled.
*/
{ "jmp", OPC_JMP, 3, CI_BRA },
{ "jne", OPC_JNE, 5, CI_BRA },
{ "jpl", OPC_JPL, 5, CI_BRA },
- { "jsr", OPC_JSR, 3, CI_BRA },
+ { "jsr", OPC_JSR, 3, CI_NONE },
{ "jvc", OPC_JVC, 5, CI_BRA },
{ "jvs", OPC_JVS, 5, CI_BRA },
{ "lda", OPC_LDA, 0, CI_CHG_A },
/* Else clause present? */
if (curtok != TOK_ELSE) {
- g_defloclabel (flab1);
+ g_defcodelabel (flab1);
/* Since there's no else clause, we're not sure, if the a break
* statement is really executed.
*/
/* Mark the label as unused */
flab2 = 0;
}
- g_defloclabel (flab1);
+ g_defcodelabel (flab1);
gotbreak &= Statement ();
/* Generate the label for the else clause */
if (flab2) {
- g_defloclabel (flab2);
+ g_defcodelabel (flab2);
}
/* Done */
loop = GetLocalLabel ();
lab = GetLocalLabel ();
AddLoop (oursp, loop, lab, 0, 0);
- g_defloclabel (loop);
+ g_defcodelabel (loop);
if (wtype == 'w') {
/* While loop */
/* There is code inside the while loop */
Statement ();
g_jump (loop);
- g_defloclabel (lab);
+ g_defcodelabel (lab);
}
} else {
Consume (TOK_WHILE, "`while' expected");
test (loop, 1);
ConsumeSemi ();
- g_defloclabel (lab);
+ g_defcodelabel (lab);
}
DelLoop ();
/* If we have a cascade label, emit it */
if (NextLab) {
- g_defloclabel (NextLab);
+ g_defcodelabel (NextLab);
NextLab = 0;
}
/* Emit a code label if we have one */
if (CodeLab) {
- g_defloclabel (CodeLab);
+ g_defcodelabel (CodeLab);
CodeLab = 0;
}
* one, too.
*/
if (NextLab) {
- g_defloclabel (NextLab);
+ g_defcodelabel (NextLab);
}
- g_defloclabel (ExitLab);
+ g_defcodelabel (ExitLab);
/* End the loop */
DelLoop ();
}
ConsumeColon ();
} while (curtok == TOK_CASE || curtok == TOK_DEFAULT);
- g_defloclabel (label);
+ g_defcodelabel (label);
HaveBreak = 0;
}
if (curtok != TOK_RCURLY) {
}
/* Actual selector code goes here */
- g_defloclabel (lcase);
+ g_defcodelabel (lcase);
/* Create the call to the switch subroutine */
Flags = TypeOf (eval->e_tptr);
if (dlabel) {
g_jump (dlabel);
}
- g_defloclabel (lab);
+ g_defcodelabel (lab);
DelLoop ();
/* Free the allocated space for the labels */
expression (&lval1);
}
ConsumeSemi ();
- g_defloclabel (loop);
+ g_defcodelabel (loop);
if (curtok != TOK_SEMI) { /* exp2 */
boolexpr (&lval2);
g_truejump (CF_NONE, lstat);
g_jump (lstat);
}
ConsumeSemi ();
- g_defloclabel (linc);
+ g_defcodelabel (linc);
if (curtok != TOK_RPAREN) { /* exp3 */
expression (&lval3);
}
ConsumeRParen ();
g_jump (loop);
- g_defloclabel (lstat);
+ g_defcodelabel (lstat);
Statement ();
g_jump (linc);
- g_defloclabel (lab);
+ g_defcodelabel (lab);
DelLoop ();
}