<bf/Note:/ This does not work in conjunction with <tt/.FEATURE
loose_string_term/, since in this case the input would be ambiguous.
+ <tag><tt>org_per_seg</tt><label id="org_per_seg"></tag>
+
+ This feature makes relocatable/absolute mode local to the current segment.
+ Using <tt><ref id=".ORG" name=".ORG"></tt> when <tt/org_per_seg/ is in
+ effect will only enable absolute mode for the current segment. Dito for
+ <tt><ref id=".RELOC" name=".RELOC"></tt>.
+
<tag><tt>pc_assignment</tt></tag>
Allow assignments to the PC symbol (`*' or `$' if <tt/dollar_is_pc/
assembled. Use <tt><ref id=".RELOC" name=".RELOC"></tt> to switch back to
relocatable code.
- Please note that you <em/do not need/ this command in most cases. Placing
+ By default, absolute/relocatable mode is global (valid even when switching
+ segments). Using <tt>.FEATURE <ref id="org_per_seg" name="org_per_seg"></tt>
+ it can be made segment local.
+
+ Please note that you <em/do not need/ <tt/.ORG/ in most cases. Placing
code at a specific address is the job of the linker, not the assembler, so
there is usually no reason to assemble code to a specific address.
- You may not switch segments while inside a section of absolute code.
-
Example:
<tscreen><verb>
/* */
/* */
/* */
-/* (C) 1998-2006 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
{
ExprNode* Root;
- if (RelocMode) {
+ if (GetRelocMode ()) {
/* Create SegmentBase + Offset */
Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
GenLiteralExpr (GetPC ()));
* (Val - PC - Offs) - Seg
*/
Root = GenLiteralExpr (Val - GetPC () - Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root->Right = GenLiteralExpr (GetPC () + Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
"at_in_identifiers",
"dollar_in_identifiers",
"leading_dot_in_identifiers",
+ "org_per_seg",
"pc_assignment",
"missing_char_term",
"ubiquitous_idents",
case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break;
case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break;
case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break;
+ case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break;
case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break;
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break;
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break;
- default: /* Keep gcc silent */ break;
+ default: /* Keep gcc silent */ break;
}
/* Return the value found */
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 2000-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
typedef enum {
- FEAT_UNKNOWN = -1,
+ FEAT_UNKNOWN = -1,
FEAT_DOLLAR_IS_PC,
FEAT_LABELS_WITHOUT_COLONS,
FEAT_LOOSE_STRING_TERM,
FEAT_AT_IN_IDENTIFIERS,
FEAT_DOLLAR_IN_IDENTIFIERS,
FEAT_LEADING_DOT_IN_IDENTIFIERS,
+ FEAT_ORG_PER_SEG,
FEAT_PC_ASSIGNMENT,
FEAT_MISSING_CHAR_TERM,
FEAT_UBIQUITOUS_IDENTS,
/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned char Listing = 0; /* Create listing file */
unsigned char LineCont = 0; /* Allow line continuation */
-/* Emulation features */
+/* Emulation features */
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */
unsigned char NoColonLabels = 0; /* Allow labels without a colon */
unsigned char LooseStringTerm = 0; /* Allow ' as string terminator */
unsigned char PCAssignment = 0; /* Allow "* = $XXX" or "$ = $XXX" */
unsigned char MissingCharTerm = 0; /* Allow lda #'a (no closing term) */
unsigned char UbiquitousIdents = 0; /* Allow ubiquitous identifiers */
+unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
/* Misc stuff */
const char Copyright[] = "(C) Copyright 1998-2005 Ullrich von Bassewitz";
/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
extern unsigned char PCAssignment; /* Allow "* = $XXX" or "$ = $XXX" */
extern unsigned char MissingCharTerm; /* Allow lda #'a (no closing term) */
extern unsigned char UbiquitousIdents; /* Allow ubiquitous identifiers */
+extern unsigned char OrgPerSeg; /* Make .org local to current seg */
/* Misc stuff */
extern const char Copyright[]; /* Copyright string */
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 2000-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
L->FragList = 0;
L->FragLast = 0;
L->PC = GetPC ();
- L->Reloc = RelocMode;
+ L->Reloc = GetRelocMode ();
L->File = File;
L->Depth = Depth;
L->Output = (ListingEnabled > 0);
/* Set the values for this line */
CHECK (L != 0);
L->PC = GetPC ();
- L->Reloc = RelocMode;
+ L->Reloc = GetRelocMode ();
L->Output = (ListingEnabled > 0);
L->ListBytes = (unsigned char) ListBytes;
} while (L->Next != LineLast);
/* Set the values for this line */
CHECK (LineCur != 0);
LineCur->PC = GetPC ();
- LineCur->Reloc = RelocMode;
+ LineCur->Reloc = GetRelocMode ();
LineCur->Output = (ListingEnabled > 0);
LineCur->ListBytes = (unsigned char) ListBytes;
}
/* */
/* */
/* */
-/* (C) 1998-2005, Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
if (PC < 0 || PC > 0xFFFFFF) {
Error ("Range error");
} else {
- SetAbsPC (PC);
+ EnterAbsoluteMode (PC);
}
}
/* */
/* */
/* */
-/* (C) 1998-2005, Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
Error ("Range error");
return;
}
- SetAbsPC (PC);
+ EnterAbsoluteMode (PC);
}
static void DoReloc (void)
/* Enter relocatable mode */
{
- RelocMode = 1;
+ EnterRelocMode ();
}
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
-/* Are we in absolute mode or in relocatable mode? */
-int RelocMode = 1;
-unsigned long AbsPC = 0; /* PC if in absolute mode */
+/* If OrgPerSeg is false, all segments share the RelocMode flag and a PC
+ * used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg
+ */
+static int RelocMode = 1;
+static unsigned long AbsPC = 0; /* PC if in absolute mode */
/* Segment initializer macro */
#define SEG(segdef, num, prev) \
- { prev, 0, 0, 0, num, 0, 0, segdef }
+ { prev, 0, 0, 0, num, 0, 1, 0, 0, segdef }
/* Definitions for predefined segments */
SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, ADDR_SIZE_ABS);
S->FragCount = 0;
S->Num = SegmentCount++;
S->Align = 0;
+ S->RelocMode = 1;
S->PC = 0;
+ S->AbsPC = 0;
S->Def = NewSegDef (Name, AddrSize);
/* Insert it into the segment list */
/* Increment the program counter */
ActiveSeg->PC += F->Len;
- if (!RelocMode) {
- AbsPC += F->Len;
+ if (OrgPerSeg) {
+ /* Relocatable mode is switched per segment */
+ if (!ActiveSeg->RelocMode) {
+ ActiveSeg->AbsPC += F->Len;
+ }
+ } else {
+ /* Relocatable mode is switched globally */
+ if (!RelocMode) {
+ AbsPC += F->Len;
+ }
}
/* Return the fragment */
unsigned long GetPC (void)
/* Get the program counter of the current segment */
{
- return RelocMode? ActiveSeg->PC : AbsPC;
+ if (OrgPerSeg) {
+ /* Relocatable mode is switched per segment */
+ return ActiveSeg->RelocMode? ActiveSeg->PC : ActiveSeg->AbsPC;
+ } else {
+ /* Relocatable mode is switched globally */
+ return RelocMode? ActiveSeg->PC : AbsPC;
+ }
+}
+
+
+
+void EnterAbsoluteMode (unsigned long PC)
+/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
+ * this will either switch the mode globally or for the current segment.
+ */
+{
+ if (OrgPerSeg) {
+ /* Relocatable mode is switched per segment */
+ ActiveSeg->RelocMode = 0;
+ ActiveSeg->AbsPC = PC;
+ } else {
+ /* Relocatable mode is switched globally */
+ RelocMode = 0;
+ AbsPC = PC;
+ }
+}
+
+
+
+int GetRelocMode (void)
+/* Return true if we're currently in relocatable mode */
+{
+ if (OrgPerSeg) {
+ /* Relocatable mode is switched per segment */
+ return ActiveSeg->RelocMode;
+ } else {
+ /* Relocatable mode is switched globally */
+ return RelocMode;
+ }
}
-void SetAbsPC (unsigned long PC)
-/* Set the program counter in absolute mode */
+void EnterRelocMode (void)
+/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
+ * switch the mode globally or for the current segment.
+ */
{
- RelocMode = 0;
- AbsPC = PC;
+ if (OrgPerSeg) {
+ /* Relocatable mode is switched per segment */
+ ActiveSeg->RelocMode = 1;
+ } else {
+ /* Relocatable mode is switched globally */
+ RelocMode = 1;
+ }
}
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned long FragCount; /* Number of fragments */
unsigned Num; /* Segment number */
unsigned Align; /* Segment alignment */
- unsigned long PC;
+ int RelocMode; /* Relocatable mode if OrgPerSeg */
+ unsigned long PC; /* PC if in relocatable mode */
+ unsigned long AbsPC; /* PC if in local absolute mode */
+ /* (OrgPerSeg is true) */
SegDef* Def; /* Segment definition (name and type) */
};
-/* Are we in absolute mode or in relocatable mode? */
-extern int RelocMode;
-
/* Definitions for predefined segments */
extern SegDef NullSegDef;
extern SegDef ZeropageSegDef;
unsigned long GetPC (void);
/* Get the program counter of the current segment */
-void SetAbsPC (unsigned long AbsPC);
-/* Set the program counter in absolute mode */
+int GetRelocMode (void);
+/* Return true if we're currently in relocatable mode */
+
+void EnterAbsoluteMode (unsigned long AbsPC);
+/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
+ * this will either switch the mode globally or for the current segment.
+ */
+
+void EnterRelocMode (void);
+/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
+ * switch the mode globally or for the current segment.
+ */
void SegCheck (void);
/* Check the segments for range and other errors */