mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Add new SKIP range
git-svn-id: svn://svn.cc65.org/cc65/trunk@2412 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
fd2fa25f28
commit
1b311d932d
@ -270,9 +270,9 @@ following attributes are recognized:
|
|||||||
|
|
||||||
<tag><tt>INPUTSIZE</tt></tag>
|
<tag><tt>INPUTSIZE</tt></tag>
|
||||||
|
|
||||||
INPUTSIZE is followed by a numerical value that gives the amount of data
|
<tt/INPUTSIZE/ is followed by a numerical value that gives the amount of
|
||||||
to read from the input file. Data beyond <tt/INPUTOFFS+INPUTSIZE/ is
|
data to read from the input file. Data beyond <tt/INPUTOFFS + INPUTSIZE/
|
||||||
ignored.
|
is ignored.
|
||||||
|
|
||||||
|
|
||||||
<tag><tt>OUTPUTNAME</tt></tag>
|
<tag><tt>OUTPUTNAME</tt></tag>
|
||||||
@ -363,6 +363,14 @@ following attributes are recognized:
|
|||||||
|
|
||||||
<tag><tt>TEXTTABLE</tt></tag>
|
<tag><tt>TEXTTABLE</tt></tag>
|
||||||
The range consists of readable text.
|
The range consists of readable text.
|
||||||
|
|
||||||
|
<tag><tt>SKIP</tt></tag>
|
||||||
|
The range is simply ignored when generating the output file. Please note
|
||||||
|
that this means that reassembling the output file will <em/not/ generate
|
||||||
|
the original file, not only because the missing piece in between, but also
|
||||||
|
because the following code will located on wrong addresses. Output
|
||||||
|
generated with <tt/SKIP/ ranges will need manual rework.
|
||||||
|
|
||||||
</descrip>
|
</descrip>
|
||||||
|
|
||||||
</descrip>
|
</descrip>
|
||||||
|
@ -260,17 +260,28 @@ void DefOutOfRangeLabels (void)
|
|||||||
SeparatorLine ();
|
SeparatorLine ();
|
||||||
|
|
||||||
/* Low range */
|
/* Low range */
|
||||||
for (Addr = 0; Addr < CodeStart; ++Addr) {
|
Addr = 0;
|
||||||
|
while (Addr < CodeStart) {
|
||||||
if (MustDefLabel (Addr)) {
|
if (MustDefLabel (Addr)) {
|
||||||
DefineConst (Addr);
|
DefineConst (Addr);
|
||||||
}
|
}
|
||||||
|
++Addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip areas in code range */
|
||||||
|
while (Addr <= CodeEnd) {
|
||||||
|
if ((AttrTab[Addr] & atStyleMask) == atSkip && MustDefLabel (Addr)) {
|
||||||
|
DefineConst (Addr);
|
||||||
|
}
|
||||||
|
++Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* High range */
|
/* High range */
|
||||||
for (Addr = CodeEnd+1; Addr < 0x10000; ++Addr) {
|
while (Addr < 0x10000) {
|
||||||
if (MustDefLabel (Addr)) {
|
if (MustDefLabel (Addr)) {
|
||||||
DefineConst (Addr);
|
DefineConst (Addr);
|
||||||
}
|
}
|
||||||
|
++Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SeparatorLine ();
|
SeparatorLine ();
|
||||||
|
@ -57,6 +57,7 @@ typedef enum attr_t {
|
|||||||
atAddrTab = 0x07,
|
atAddrTab = 0x07,
|
||||||
atRtsTab = 0x08,
|
atRtsTab = 0x08,
|
||||||
atTextTab = 0x09,
|
atTextTab = 0x09,
|
||||||
|
atSkip = 0x0A, /* Skip code completely */
|
||||||
|
|
||||||
/* Label flags */
|
/* Label flags */
|
||||||
atNoLabel = 0x00, /* No label for this address */
|
atNoLabel = 0x00, /* No label for this address */
|
||||||
|
@ -63,6 +63,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void AddAttr (const char* Name, unsigned* Set, unsigned Attr)
|
||||||
|
/* Add an attribute to the set and check that it is not given twice */
|
||||||
|
{
|
||||||
|
if (*Set & Attr) {
|
||||||
|
/* Attribute is already in the set */
|
||||||
|
InfoError ("%s given twice", Name);
|
||||||
|
}
|
||||||
|
*Set |= Attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void GlobalSection (void)
|
static void GlobalSection (void)
|
||||||
/* Parse a global section */
|
/* Parse a global section */
|
||||||
{
|
{
|
||||||
@ -96,7 +108,7 @@ static void GlobalSection (void)
|
|||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoAssureInt ();
|
InfoAssureInt ();
|
||||||
InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS);
|
InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS);
|
||||||
Comments = InfoIVal;
|
Comments = InfoIVal;
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -139,7 +151,7 @@ static void GlobalSection (void)
|
|||||||
case INFOTOK_OUTPUTNAME:
|
case INFOTOK_OUTPUTNAME:
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoAssureStr ();
|
InfoAssureStr ();
|
||||||
if (OutFile) {
|
if (OutFile) {
|
||||||
InfoError ("Output file name already given");
|
InfoError ("Output file name already given");
|
||||||
}
|
}
|
||||||
OutFile = xstrdup (InfoSVal);
|
OutFile = xstrdup (InfoSVal);
|
||||||
@ -147,7 +159,7 @@ static void GlobalSection (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case INFOTOK_PAGELENGTH:
|
case INFOTOK_PAGELENGTH:
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoAssureInt ();
|
InfoAssureInt ();
|
||||||
if (InfoIVal != 0) {
|
if (InfoIVal != 0) {
|
||||||
InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
|
InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
|
||||||
@ -188,14 +200,15 @@ static void RangeSection (void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const IdentTok TypeDefs[] = {
|
static const IdentTok TypeDefs[] = {
|
||||||
{ "CODE", INFOTOK_CODE },
|
|
||||||
{ "BYTETABLE", INFOTOK_BYTETAB },
|
|
||||||
{ "DBYTETABLE", INFOTOK_DBYTETAB },
|
|
||||||
{ "WORDTABLE", INFOTOK_WORDTAB },
|
|
||||||
{ "DWORDTABLE", INFOTOK_DWORDTAB },
|
|
||||||
{ "ADDRTABLE", INFOTOK_ADDRTAB },
|
{ "ADDRTABLE", INFOTOK_ADDRTAB },
|
||||||
|
{ "BYTETABLE", INFOTOK_BYTETAB },
|
||||||
|
{ "CODE", INFOTOK_CODE },
|
||||||
|
{ "DBYTETABLE", INFOTOK_DBYTETAB },
|
||||||
|
{ "DWORDTABLE", INFOTOK_DWORDTAB },
|
||||||
{ "RTSTABLE", INFOTOK_RTSTAB },
|
{ "RTSTABLE", INFOTOK_RTSTAB },
|
||||||
|
{ "SKIP", INFOTOK_SKIP },
|
||||||
{ "TEXTTABLE", INFOTOK_TEXTTAB },
|
{ "TEXTTABLE", INFOTOK_TEXTTAB },
|
||||||
|
{ "WORDTABLE", INFOTOK_WORDTAB },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -207,7 +220,8 @@ static void RangeSection (void)
|
|||||||
tType = 0x04,
|
tType = 0x04,
|
||||||
tName = 0x08,
|
tName = 0x08,
|
||||||
tNeeded = (tStart | tEnd | tType)
|
tNeeded = (tStart | tEnd | tType)
|
||||||
} Attributes = tNone;
|
};
|
||||||
|
unsigned Attributes = tNone;
|
||||||
|
|
||||||
/* Locals - initialize to avoid gcc warnings */
|
/* Locals - initialize to avoid gcc warnings */
|
||||||
unsigned Start = 0;
|
unsigned Start = 0;
|
||||||
@ -231,51 +245,50 @@ static void RangeSection (void)
|
|||||||
switch (InfoTok) {
|
switch (InfoTok) {
|
||||||
|
|
||||||
case INFOTOK_END:
|
case INFOTOK_END:
|
||||||
|
AddAttr ("END", &Attributes, tEnd);
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoAssureInt ();
|
InfoAssureInt ();
|
||||||
InfoRangeCheck (0x0000, 0xFFFF);
|
InfoRangeCheck (0x0000, 0xFFFF);
|
||||||
End = InfoIVal;
|
End = InfoIVal;
|
||||||
Attributes |= tEnd;
|
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFOTOK_NAME:
|
case INFOTOK_NAME:
|
||||||
|
AddAttr ("NAME", &Attributes, tName);
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
if (Name) {
|
|
||||||
InfoError ("Name already given");
|
|
||||||
}
|
|
||||||
InfoAssureStr ();
|
InfoAssureStr ();
|
||||||
if (InfoSVal[0] == '\0') {
|
if (InfoSVal[0] == '\0') {
|
||||||
InfoError ("Name may not be empty");
|
InfoError ("Name may not be empty");
|
||||||
}
|
}
|
||||||
Name = xstrdup (InfoSVal);
|
Name = xstrdup (InfoSVal);
|
||||||
Attributes |= tName;
|
Attributes |= tName;
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFOTOK_START:
|
case INFOTOK_START:
|
||||||
|
AddAttr ("START", &Attributes, tStart);
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoAssureInt ();
|
InfoAssureInt ();
|
||||||
InfoRangeCheck (0x0000, 0xFFFF);
|
InfoRangeCheck (0x0000, 0xFFFF);
|
||||||
Start = InfoIVal;
|
Start = InfoIVal;
|
||||||
Attributes |= tStart;
|
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFOTOK_TYPE:
|
case INFOTOK_TYPE:
|
||||||
|
AddAttr ("TYPE", &Attributes, tType);
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "Type");
|
InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
|
||||||
switch (InfoTok) {
|
switch (InfoTok) {
|
||||||
case INFOTOK_CODE: Type = atCode; break;
|
|
||||||
case INFOTOK_BYTETAB: Type = atByteTab; break;
|
|
||||||
case INFOTOK_DBYTETAB: Type = atDByteTab; break;
|
|
||||||
case INFOTOK_WORDTAB: Type = atWordTab; break;
|
|
||||||
case INFOTOK_DWORDTAB: Type = atDWordTab; break;
|
|
||||||
case INFOTOK_ADDRTAB: Type = atAddrTab; break;
|
case INFOTOK_ADDRTAB: Type = atAddrTab; break;
|
||||||
|
case INFOTOK_BYTETAB: Type = atByteTab; break;
|
||||||
|
case INFOTOK_CODE: Type = atCode; break;
|
||||||
|
case INFOTOK_DBYTETAB: Type = atDByteTab; break;
|
||||||
|
case INFOTOK_DWORDTAB: Type = atDWordTab; break;
|
||||||
case INFOTOK_RTSTAB: Type = atRtsTab; break;
|
case INFOTOK_RTSTAB: Type = atRtsTab; break;
|
||||||
|
case INFOTOK_SKIP: Type = atSkip; break;
|
||||||
case INFOTOK_TEXTTAB: Type = atTextTab; break;
|
case INFOTOK_TEXTTAB: Type = atTextTab; break;
|
||||||
|
case INFOTOK_WORDTAB: Type = atWordTab; break;
|
||||||
}
|
}
|
||||||
Attributes |= tType;
|
|
||||||
InfoNextTok ();
|
InfoNextTok ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -238,8 +238,13 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||||||
/* Get the opcode description for the opcode byte */
|
/* Get the opcode description for the opcode byte */
|
||||||
const OpcDesc* D = &OpcTable[OPC];
|
const OpcDesc* D = &OpcTable[OPC];
|
||||||
|
|
||||||
/* If we have a label at this address, output the label */
|
/* Get the output style for the current PC */
|
||||||
if (MustDefLabel (PC)) {
|
attr_t Style = GetStyleAttr (PC);
|
||||||
|
|
||||||
|
/* If we have a label at this address, output the label, provided that
|
||||||
|
* we aren't in a skip area.
|
||||||
|
*/
|
||||||
|
if (Style != atSkip && MustDefLabel (PC)) {
|
||||||
DefLabel (GetLabel (PC));
|
DefLabel (GetLabel (PC));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +254,7 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||||||
* - ...if there is no label somewhere between the instruction bytes.
|
* - ...if there is no label somewhere between the instruction bytes.
|
||||||
* If any of these conditions is false, switch to data mode.
|
* If any of these conditions is false, switch to data mode.
|
||||||
*/
|
*/
|
||||||
if (GetStyleAttr (PC) == atDefault) {
|
if (Style == atDefault) {
|
||||||
if (D->Size > RemainingBytes) {
|
if (D->Size > RemainingBytes) {
|
||||||
MarkAddr (PC, atIllegal);
|
MarkAddr (PC, atIllegal);
|
||||||
} else if (D->Flags & flIllegal) {
|
} else if (D->Flags & flIllegal) {
|
||||||
@ -257,16 +262,16 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||||||
} else {
|
} else {
|
||||||
unsigned I;
|
unsigned I;
|
||||||
for (I = 1; I < D->Size; ++I) {
|
for (I = 1; I < D->Size; ++I) {
|
||||||
if (HaveLabel (PC+I)) {
|
if (HaveLabel (PC+I)) {
|
||||||
MarkAddr (PC, atIllegal);
|
MarkAddr (PC, atIllegal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disassemble the line */
|
/* Disassemble the line */
|
||||||
switch (GetStyleAttr (PC)) {
|
switch (Style) {
|
||||||
|
|
||||||
case atDefault:
|
case atDefault:
|
||||||
case atCode:
|
case atCode:
|
||||||
@ -302,6 +307,10 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||||||
TextTable ();
|
TextTable ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case atSkip:
|
||||||
|
++PC;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DataByteLine (1);
|
DataByteLine (1);
|
||||||
++PC;
|
++PC;
|
||||||
|
@ -87,6 +87,7 @@ typedef enum token_t {
|
|||||||
INFOTOK_ADDRTAB,
|
INFOTOK_ADDRTAB,
|
||||||
INFOTOK_RTSTAB,
|
INFOTOK_RTSTAB,
|
||||||
INFOTOK_TEXTTAB,
|
INFOTOK_TEXTTAB,
|
||||||
|
INFOTOK_SKIP,
|
||||||
|
|
||||||
/* Label section */
|
/* Label section */
|
||||||
INFOTOK_NAME,
|
INFOTOK_NAME,
|
||||||
|
Loading…
Reference in New Issue
Block a user