/* Indexed */
L = SkipSpace (L+1);
if (*L == '\0') {
- Error ("ASM code error: syntax error");
+ Error ("ASM code error: syntax error");
return 0;
} else {
Reg = toupper (*L);
if (E) {
/* Transfer the labels if we have any */
- unsigned LabelCount = CollCount (&S->Labels);
unsigned I;
+ unsigned LabelCount = CollCount (&S->Labels);
for (I = 0; I < LabelCount; ++I) {
- CollAppend (&E->Labels, CollAt (&S->Labels, I));
+ /* Get the label */
+ CodeLabel* L = CollAt (&S->Labels, I);
+ /* Mark it as defined */
+ L->Flags |= LF_DEF;
+ /* Move it to the code entry */
+ CollAppend (&E->Labels, L);
}
+
+ /* Delete the transfered labels */
CollDeleteAll (&S->Labels);
/* Add the entry to the list of code entries in this segment */
- CollAppend (&S->Entries, E);
+ CollAppend (&S->Entries, E);
}
}
-void AddCodeSegLabel (CodeSeg* S, const char* Name)
-/* Add a label for the next instruction to follow */
+CodeLabel* AddCodeLabel (CodeSeg* S, const char* Name)
+/* Add a code label for the next instruction to follow */
{
/* Calculate the hash from the name */
unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE;
/* 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);
}
void DelCodeSegAfter (CodeSeg* S, unsigned Last)
-/* Delete all entries after the given one */
+/* Delete all entries including the given one */
{
- unsigned I;
-
/* Get the number of entries in this segment */
unsigned Count = CollCount (&S->Entries);
- /* ### We need some more cleanup here wrt labels */
+ /* Must not be called with count zero */
+ CHECK (Count > 0 && Count >= Last);
/* Remove all entries after the given one */
- for (I = Count-1; I > Last; --I) {
- FreeCodeEntry (CollAt (&S->Entries, I));
- CollDelete (&S->Entries, I);
- }
+ while (Last < Count) {
+
+ /* Get the next entry */
+ CodeEntry* E = CollAt (&S->Entries, Count-1);
+
+ /* We have to transfer all labels to the code segment label pool */
+ unsigned LabelCount = CollCount (&E->Labels);
+ while (LabelCount--) {
+ CodeLabel* L = CollAt (&E->Labels, LabelCount);
+ L->Flags &= ~LF_DEF;
+ CollAppend (&S->Labels, L);
+ }
+ CollDeleteAll (&E->Labels);
- /* Delete all waiting labels */
- CollDeleteAll (&S->Labels);
+ /* Remove the code entry */
+ FreeCodeEntry (CollAt (&S->Entries, Count-1));
+ CollDelete (&S->Entries, Count-1);
+ --Count;
+ }
}
if (strcmp (Name, L->Name) == 0) {
/* Found */
break;
- }
+ }
L = L->Next;
}
return L;
/* Get a pointer to the next entry */
CodeEntry* E = CollAt (&S->Entries, I);
- /* If this entry has zero labels, continue with the next one */
- unsigned LabelCount = CollCount (&E->Labels);
- if (LabelCount == 0) {
- 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.
- */
- RefLab = CollAt (&E->Labels, 0);
-
- /* Walk through the remaining labels and change references to these
- * labels to a reference to the one and only label. Delete the labels
- * that are no longer used. To increase performance, walk backwards
- * through the list.
- */
- for (J = LabelCount-1; J >= 1; --J) {
-
- unsigned K;
-
- /* Get the next label */
- CodeLabel* L = CollAt (&E->Labels, J);
-
- /* Walk through all instructions referencing this label */
- unsigned RefCount = CollCount (&L->JumpFrom);
- for (K = 0; K < RefCount; ++K) {
-
- /* Get the next instrcuction that references this label */
- CodeEntry* E = CollAt (&L->JumpFrom, K);
-
- /* Change the reference */
- CHECK (E->JumpTo == L);
- E->JumpTo = RefLab;
- CollAppend (&RefLab->JumpFrom, E);
-
- }
-
- /* Delete the label */
- FreeCodeLabel (L);
-
- /* Remove it from the list */
- CollDelete (&E->Labels, J);
-
+ /* If this entry has zero labels, continue with the next one */
+ unsigned LabelCount = CollCount (&E->Labels);
+ if (LabelCount == 0) {
+ 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.
+ */
+ RefLab = CollAt (&E->Labels, 0);
+
+ /* Walk through the remaining labels and change references to these
+ * labels to a reference to the one and only label. Delete the labels
+ * that are no longer used. To increase performance, walk backwards
+ * through the list.
+ */
+ for (J = LabelCount-1; J >= 1; --J) {
+
+ unsigned K;
+
+ /* Get the next label */
+ CodeLabel* L = CollAt (&E->Labels, J);
+
+ /* Walk through all instructions referencing this label */
+ unsigned RefCount = CollCount (&L->JumpFrom);
+ for (K = 0; K < RefCount; ++K) {
+
+ /* Get the next instrcuction that references this label */
+ CodeEntry* E = CollAt (&L->JumpFrom, K);
+
+ /* Change the reference */
+ CHECK (E->JumpTo == L);
+ E->JumpTo = RefLab;
+ CollAppend (&RefLab->JumpFrom, E);
+
+ }
+
+ /* 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
}
- /* 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.
+ /* 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.
*/
- if (CollCount (&RefLab->JumpFrom) == 0) {
- /* Delete the label */
- FreeCodeLabel (RefLab);
- /* Remove it from the list */
- CollDelete (&E->Labels, 0);
- }
+#if 0
+ if ((RefLab->Flags & LF_EXT) == 0 && CollCount (&RefLab->JumpFrom) == 0) {
+ /* Delete the label */
+ FreeCodeLabel (RefLab);
+ /* Remove it from the list */
+ CollDelete (&E->Labels, 0);
+ }
+#endif
}
}
/* Mapper table, mnemonic --> opcode */
static const OPCDesc OPCTable[OPC_COUNT] = {
- { "adc", OPC_ADC, CI_USE_A | CI_CHG_A },
- { "and", OPC_AND, CI_USE_A | CI_CHG_A },
- { "asl", OPC_ASL, CI_USE_A | CI_CHG_A },
- { "bcc", OPC_BCC, CI_BRA },
- { "bcs", OPC_BCS, CI_BRA },
- { "beq", OPC_BEQ, CI_BRA },
- { "bit", OPC_BIT, CI_USE_A },
- { "bmi", OPC_BMI, CI_BRA },
- { "bne", OPC_BNE, CI_BRA },
- { "bpl", OPC_BPL, CI_BRA },
- { "bra", OPC_BRA, CI_BRA },
- { "brk", OPC_BRK, CI_BRA },
- { "bvc", OPC_BVC, CI_BRA },
- { "bvs", OPC_BVS, CI_BRA },
- { "clc", OPC_CLC, CI_CHG_NONE },
- { "cld", OPC_CLD, CI_CHG_NONE },
- { "cli", OPC_CLI, CI_CHG_NONE },
- { "clv", OPC_CLV, CI_CHG_NONE },
- { "cmp", OPC_CMP, CI_USE_A },
- { "cpx", OPC_CPX, CI_USE_X },
- { "cpy", OPC_CPY, CI_USE_Y },
- { "dea", OPC_DEA, CI_USE_A | CI_CHG_A },
- { "dec", OPC_DEC, CI_NONE },
- { "dex", OPC_DEX, CI_USE_X | CI_CHG_X },
- { "dey", OPC_DEY, CI_USE_Y | CI_CHG_Y },
- { "eor", OPC_EOR, CI_USE_A | CI_CHG_A },
- { "ina", OPC_INA, CI_USE_A | CI_CHG_A },
- { "inc", OPC_INC, CI_NONE },
- { "inx", OPC_INX, CI_USE_X | CI_CHG_X },
- { "iny", OPC_INY, CI_USE_Y | CI_CHG_Y },
- { "jmp", OPC_JMP, CI_BRA },
- { "jsr", OPC_JSR, CI_BRA },
- { "lda", OPC_LDA, CI_CHG_A },
- { "ldx", OPC_LDX, CI_CHG_X },
- { "ldy", OPC_LDY, CI_CHG_Y },
- { "lsr", OPC_LSR, CI_USE_A | CI_CHG_A },
- { "nop", OPC_NOP, CI_NONE },
- { "ora", OPC_ORA, CI_USE_A | CI_CHG_A },
- { "pha", OPC_PHA, CI_USE_A },
- { "php", OPC_PHP, CI_NONE },
- { "phx", OPC_PHX, CI_USE_X },
- { "phy", OPC_PHY, CI_USE_Y },
- { "pla", OPC_PLA, CI_CHG_A },
- { "plp", OPC_PLP, CI_NONE },
- { "plx", OPC_PLX, CI_CHG_X },
- { "ply", OPC_PLY, CI_CHG_Y },
- { "rol", OPC_ROL, CI_USE_A | CI_CHG_A },
- { "ror", OPC_ROR, CI_USE_A | CI_CHG_A },
- { "rti", OPC_RTI, CI_NONE },
- { "rts", OPC_RTS, CI_NONE },
- { "sbc", OPC_SBC, CI_USE_A | CI_CHG_A },
- { "sec", OPC_SEC, CI_NONE },
- { "sed", OPC_SED, CI_NONE },
- { "sei", OPC_SEI, CI_NONE },
- { "sta", OPC_STA, CI_USE_A },
- { "stx", OPC_STX, CI_USE_X },
- { "sty", OPC_STY, CI_USE_Y },
- { "tax", OPC_TAX, CI_USE_A | CI_CHG_X },
- { "tay", OPC_TAY, CI_USE_A | CI_CHG_Y },
- { "trb", OPC_TRB, CI_USE_A },
- { "tsb", OPC_TSB, CI_USE_A },
- { "tsx", OPC_TSX, CI_CHG_X },
- { "txa", OPC_TXA, CI_USE_X | CI_CHG_A },
- { "txs", OPC_TXS, CI_USE_X },
- { "tya", OPC_TYA, CI_USE_Y | CI_CHG_A }
+ { "adc", OPC_ADC, 0, CI_USE_A | CI_CHG_A },
+ { "and", OPC_AND, 0, CI_USE_A | CI_CHG_A },
+ { "asl", OPC_ASL, 0, CI_USE_A | CI_CHG_A },
+ { "bcc", OPC_BCC, 2, CI_BRA },
+ { "bcs", OPC_BCS, 2, CI_BRA },
+ { "beq", OPC_BEQ, 2, CI_BRA },
+ { "bit", OPC_BIT, 0, CI_USE_A },
+ { "bmi", OPC_BMI, 2, CI_BRA },
+ { "bne", OPC_BNE, 2, CI_BRA },
+ { "bpl", OPC_BPL, 2, CI_BRA },
+ { "bra", OPC_BRA, 2, CI_BRA },
+ { "brk", OPC_BRK, 1, CI_NONE },
+ { "bvc", OPC_BVC, 2, CI_BRA },
+ { "bvs", OPC_BVS, 2, CI_BRA },
+ { "clc", OPC_CLC, 1, CI_CHG_NONE },
+ { "cld", OPC_CLD, 1, CI_CHG_NONE },
+ { "cli", OPC_CLI, 1, CI_CHG_NONE },
+ { "clv", OPC_CLV, 1, CI_CHG_NONE },
+ { "cmp", OPC_CMP, 0, CI_USE_A },
+ { "cpx", OPC_CPX, 0, CI_USE_X },
+ { "cpy", OPC_CPY, 0, CI_USE_Y },
+ { "dea", OPC_DEA, 1, CI_USE_A | CI_CHG_A },
+ { "dec", OPC_DEC, 0, CI_NONE },
+ { "dex", OPC_DEX, 1, CI_USE_X | CI_CHG_X },
+ { "dey", OPC_DEY, 1, CI_USE_Y | CI_CHG_Y },
+ { "eor", OPC_EOR, 0, CI_USE_A | CI_CHG_A },
+ { "ina", OPC_INA, 1, CI_USE_A | CI_CHG_A },
+ { "inc", OPC_INC, 0, CI_NONE },
+ { "inx", OPC_INX, 1, CI_USE_X | CI_CHG_X },
+ { "iny", OPC_INY, 1, CI_USE_Y | CI_CHG_Y },
+ { "jcc", OPC_JCC, 5, CI_BRA },
+ { "jcs", OPC_JCS, 5, CI_BRA },
+ { "jeq", OPC_JEQ, 5, CI_BRA },
+ { "jmi", OPC_JMI, 5, CI_BRA },
+ { "jmp", OPC_JMP, 3, CI_BRA },
+ { "jne", OPC_JNE, 5, CI_BRA },
+ { "jpl", OPC_JPL, 5, CI_BRA },
+ { "jsr", OPC_JSR, 3, CI_BRA },
+ { "jvc", OPC_JVC, 5, CI_BRA },
+ { "jvs", OPC_JVS, 5, CI_BRA },
+ { "lda", OPC_LDA, 0, CI_CHG_A },
+ { "ldx", OPC_LDX, 0, CI_CHG_X },
+ { "ldy", OPC_LDY, 0, CI_CHG_Y },
+ { "lsr", OPC_LSR, 0, CI_USE_A | CI_CHG_A },
+ { "nop", OPC_NOP, 1, CI_NONE },
+ { "ora", OPC_ORA, 0, CI_USE_A | CI_CHG_A },
+ { "pha", OPC_PHA, 1, CI_USE_A },
+ { "php", OPC_PHP, 1, CI_NONE },
+ { "phx", OPC_PHX, 1, CI_USE_X },
+ { "phy", OPC_PHY, 1, CI_USE_Y },
+ { "pla", OPC_PLA, 1, CI_CHG_A },
+ { "plp", OPC_PLP, 1, CI_NONE },
+ { "plx", OPC_PLX, 1, CI_CHG_X },
+ { "ply", OPC_PLY, 1, CI_CHG_Y },
+ { "rol", OPC_ROL, 0, CI_USE_A | CI_CHG_A },
+ { "ror", OPC_ROR, 0, CI_USE_A | CI_CHG_A },
+ { "rti", OPC_RTI, 1, CI_NONE },
+ { "rts", OPC_RTS, 1, CI_NONE },
+ { "sbc", OPC_SBC, 0, CI_USE_A | CI_CHG_A },
+ { "sec", OPC_SEC, 1, CI_NONE },
+ { "sed", OPC_SED, 1, CI_NONE },
+ { "sei", OPC_SEI, 1, CI_NONE },
+ { "sta", OPC_STA, 0, CI_USE_A },
+ { "stx", OPC_STX, 0, CI_USE_X },
+ { "sty", OPC_STY, 0, CI_USE_Y },
+ { "tax", OPC_TAX, 1, CI_USE_A | CI_CHG_X },
+ { "tay", OPC_TAY, 1, CI_USE_A | CI_CHG_Y },
+ { "trb", OPC_TRB, 0, CI_USE_A },
+ { "tsb", OPC_TSB, 0, CI_USE_A },
+ { "tsx", OPC_TSX, 1, CI_CHG_X },
+ { "txa", OPC_TXA, 1, CI_USE_X | CI_CHG_A },
+ { "txs", OPC_TXS, 1, CI_USE_X },
+ { "tya", OPC_TYA, 1, CI_USE_Y | CI_CHG_A }
};
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
unsigned GetInsnSize (opc_t OPC, am_t AM)
/* Return the size of the given instruction */
{
- /* On the 6502 (and 65C02), the instruction size is determined only by the
- * addressing mode.
- */
+ /* Get the opcode desc and check the size given there */
+ const OPCDesc* D = &OPCTable[OPC];
+ if (D->Size != 0) {
+ return D->Size;
+ }
+
+ /* Check the addressing mode. */
switch (AM) {
case AM_IMP: return 1;
case AM_ACC: return 1;
case AM_ZPX_IND: return 2;
case AM_ZP_INDY: return 2;
case AM_ZP_IND: return 2;
- case AM_BRA: return 2;
default: FAIL ("Invalid addressing mode");
}
}