#include #include #include #include #include "assemble.h" OperandType format_operand (OperandType operand, Label_Node *head, int pass, int line) { AddressingType addtype; int hash, split; int i; char tmp[80], unformat[80]; char lastchar, firstchar; int length; /* make a copy of the original operand */ strcpy (tmp, operand.orig); strcpy (unformat, operand.orig); length = strlen(tmp); for (i=0; i' */ if (tmp[1] == '<' || firstchar == '<' || tmp[1] == '>' || firstchar == '>') split = 1; else split = 0; /* Assume a label */ addtype = LAB; /* If it only contains (a-z A-Z 0-9) assume it's a label */ /* Unless it's a single 'A' then it's Accumulator addressing */ /* If the operand only consists of a decimal number it will be */ /* assumed to be a label. get_value will handle this anyway */ if (strcmp(tmp, "A") == 0) addtype = ACC; else if (tmp[hash] != '$' && tmp[hash] != '%') { for (i=(hash + split); i < strlen (tmp); i++) { if (!isalnum(tmp[i])) { addtype = IMM; i = strlen(tmp); } } } else addtype = IMM; /* If it's a label, handle addressing modes and '<', '>' */ if (addtype == LAB) { operand.value = get_value (&operand, &unformat[hash], head, pass, line) & 0xffff; if (hash == 1) { addtype = IMM; } else { if (operand.value < 256) addtype = ZP; else addtype = ABS; } } else if (addtype != ACC) /* It's not a label. What is it? */ { /* printf ("%s\n", tmp); */ if (firstchar == '(' && strcmp(&tmp[length-3], "),Y") == 0) addtype = INDY; else if (firstchar == '(' && strcmp(&tmp[length-3], ",X)") == 0) addtype = INDX; else if (firstchar == '(' && lastchar == ')') addtype = IND; else if (firstchar == '#') addtype = IMM; else if (strcmp(&tmp[length-2], ",Y") == 0) { tmp[strlen(tmp)-2] = '\0'; operand.value = get_value(&operand, unformat, head, pass, line) & 0xffff; if (operand.value < 256) addtype = ZPY; else addtype = ABSY; } else if (strcmp(&tmp[length-2], ",X") == 0) { tmp[strlen(tmp)-2] = '\0'; operand.value = get_value(&operand, unformat, head, pass, line) & 0xffff; if (operand.value < 256) addtype = ZPX; else addtype = ABSX; } else { operand.value = get_value(&operand, unformat, head, pass, line) & 0xffff; if (operand.value < 256) addtype = ZP; else addtype = ABS; } } /* Okay, we know what type it is now. Fill in the blanks */ operand.addtype = addtype; switch (addtype) { case IMM: operand.value = get_value(&operand, &unformat[1], head, pass, line) & 0xff; sprintf (operand.formatted, "#$%.2lX", operand.value); strcpy (operand.addtype_text, "Immediate"); break; case ABS: sprintf (operand.formatted, "$%.4lX", operand.value); strcpy (operand.addtype_text, "Absolute"); break; case ZP: sprintf (operand.formatted, "$%.2lX", operand.value); strcpy (operand.addtype_text, "Zero Page"); break; case INDX: unformat[strlen(tmp)-3] = '\0'; operand.value = get_value(&operand, &unformat[1], head, pass, line) & 0xff; sprintf (operand.formatted, "($%.2lX,X)", operand.value); strcpy (operand.addtype_text, "(Indirect,X)"); break; case INDY: unformat[strlen(tmp)-3] = '\0'; operand.value = get_value(&operand, &unformat[1], head, pass, line) & 0xff; sprintf (operand.formatted, "($%.2lX),Y", operand.value); strcpy (operand.addtype_text, "(Indirect),Y"); break; case ZPX: sprintf (operand.formatted, "$%.2lX,X", operand.value); strcpy (operand.addtype_text, "Zero Page,X"); break; case ZPY: sprintf (operand.formatted, "$%.2lX,Y", operand.value); strcpy (operand.addtype_text, "Zero Page,Y"); break; case ABSX: sprintf (operand.formatted, "$%.4lX,X", operand.value); strcpy (operand.addtype_text, "Absolute,X"); break; case ABSY: sprintf (operand.formatted, "$%.4lX,Y", operand.value); strcpy (operand.addtype_text, "Absolute,Y"); break; case IND: unformat[strlen(tmp)-1] = '\0'; operand.value = get_value(&operand, &unformat[1], head, pass, line) & 0xffff; sprintf (operand.formatted, "($%.4lX)", operand.value); strcpy (operand.addtype_text, "(Indirect)"); break; case ACC: sprintf (operand.formatted, "A"); operand.value = 0; strcpy (operand.addtype_text, "Accumulator"); break; case LAB: break; case REL: break; case IMP: break; } return operand; } int get_value (OperandType *operand, char string[30], Label_Node *head, int pass, int line) { enum optype {TEXT, DECIMAL, HEX, BINARY, CHAR, CALC}; typedef enum optype OperativeType; OperativeType opertype; int i, split; long value; char part1[30], part2[30]; char op; for (i=0; i<=30; i++) part1[i] = part2[i] = '\0'; /* Funky recursive bit */ for (i=0; i') split = 1; else split = 0; /* If any characters are not 'A-Z' then it's not a label */ opertype = DECIMAL; if (string[0] == '$') opertype = HEX; else if (string[0] == '%') opertype = BINARY; else if (string[0] == '\'' && string[2] == '\'') opertype = CHAR; else { for (i = split; i < strlen(string); i++) { if (!isdigit(string[i])) opertype = TEXT; } } strcpy (operand->label, ""); switch (opertype) { case DECIMAL: value = strtol (&string[0], NULL, 10); break; case BINARY: value = strtol(&string[1], NULL, 2); break; case HEX: value = strtol(&string[1], NULL, 16); break; case CHAR: value = (unsigned char) string[1]; break; case TEXT: for (i=0; ilabel, string); value = find_label_element(head, &string[split]); if (value == 0x666666 && pass == 2) { fprintf (stderr, "Unknown label %s in line %d\n", &string[split], line); exit(EXIT_FAILURE); } if (string[0] == '<') value = value & 0x00ff; else if (string[0] == '>') value = (value & 0xff00) >> 8; break; default: value = 0x6666; } return value; }