#include #include #include #include #include "assemble.h" int assemble (FILE *f, long *start_address, long *end_address, long address, int pass, int verbose, unsigned char *codein, Label_Node *label_head, Command_Node *mnemonic_head) { char line[80], mnemonic[80], def_value[80], firstchar, tmp[80], item[30]; static OperandType operand; int i, j, numofwords, done, line_no, length, pos; LineType type; unsigned char output[30], *tmp2; unsigned char code[65535]; for (i=0; i<65535; i++) code[i] = 0xFF; done = 1; line_no = 0; for(;;) { if (done == 1) { fgets (line, 80, f); line_no++; if (feof (f)) { /* Copy back to buffer */ for (i=0; i<65535; i++) { *(codein + i) = code[i]; } return 1; } done = 0; } /* Get first printable character */ firstchar = getfirstchar(line); /* Parse Line */ numofwords = sscanf (line, "%s %s %s", mnemonic, operand.orig, def_value); for (i=0; i 0) printf ("Label: %s $%.4lX\n", mnemonic, address); } else if (verbose > 0) printf ("\n $%.4lX: %s\n", address, mnemonic); /* If there are further items on the line, * remove the label and reprocess */ if (numofwords == 1) done = 1; else for (i=0; i < strlen(mnemonic)+1; i++) line[i] = ' '; break; /************************************************************ * Handle #DEFINE * ************************************************************/ case DEFINE: if (pass == 1) { strcat (operand.orig, ":"); if (do_labels(label_head, operand.orig, get_value(&operand, def_value, label_head, pass, line_no)) != 0) { fprintf (stderr, "Duplicate #DEFINE %s at line %d\n", operand.orig, line_no); exit (EXIT_FAILURE); } else if (verbose > 0) printf ("Define: %s $%x\n", operand.orig, get_value(&operand, def_value, label_head, pass, line_no)); } done = 1; break; /************************************************************ * Data. Byte, word or long-word aligned * ************************************************************/ case DFB: case DFW: case DFL: strcpy (tmp, strstr(line, operand.orig)); tmp[strlen(tmp)-1] = '\0'; /* Clear item string */ for (j=0; j<30; j++) item[j] = '\0'; strcat (tmp, ","); length = 0; pos = 0; for (i=0; i 0) printf ("Item: '%s'\n", item); if (item[0] == '"') { /* Text item */ for (j=1; j<(strlen(item)-1); j++) { if (pass == 2 && verbose > 1) printf (" == $%.2X\n", item[j]); code[address++] = item[j]; if (type != DFB) { /* Word or long-word */ code[address++] = 0; if (type != DFW) { /* Longword */ code[address++] = 0; code[address++] = 0; } } } } else { /* Number / Label */ code[address++] = (get_value(&operand, item, label_head, pass, line_no) & 0xFF); if (type != DFB) { code[address++] = (get_value(&operand, item, label_head, pass, line_no) & 0xFF00) >> 8; if (type != DFW) { code[address++] = (get_value(&operand, item, label_head, pass, line_no) & 0xFF0000) >> 16; code[address++] = (get_value(&operand, item, label_head, pass, line_no) & 0xFF000000) >> 24; } } } for (j=0; j<30; j++) item[j] = '\0'; pos = 0; } } if (address > *end_address) *end_address = address; done = 1; break; /************************************************************ * Text strings '...' * ************************************************************/ case DFM: strcpy (tmp, strstr(line, operand.orig)); tmp[strlen(tmp)-1] = '\0'; if (verbose > 0) printf ("Item: '%s'\n", tmp); for (j=0; j 0) printf (" == $%.2X\n", tmp[j]); code[address++] = tmp[j]; } if (address > *end_address) *end_address = address; done = 1; break; /************************************************************ * Note Duff's Devious Device * ************************************************************/ case COMMAND_OPER: /* Figure out if we need to use relative addressing */ if (mnemonic[0] != 'B' || strcmp(mnemonic, "BIT") == 0) { operand = format_operand (operand, label_head, pass, line_no); } else do_branch (address, &operand, label_head, pass, line_no); /* Fall-through */ case COMMAND_NOOPER: if (type == COMMAND_NOOPER) { for (i=0; i *end_address) *end_address = address; } else { fprintf (stderr, "Illegal Addressing Mode %s at line %d\n\n", operand.addtype_text, line_no); exit (EXIT_FAILURE); } done = 1; break; /************************************************************/ case ADDRESS: if (pass == 1 && verbose > 0) printf ("\nChange Address: $%.4X\n\n", get_value(&operand, operand.orig, label_head, pass, line_no)); address = get_value(&operand, operand.orig, label_head, pass, line_no); done = 1; break; /************************************************************/ case AT_ADDRESS: for (i=0; i < strlen(line); i++) if (line[i] == '@' || line[i] == '=') line[i] = ' '; sscanf (line, "%s", tmp); if (pass == 2 && verbose > 0) printf ("\nChange Address: $%.4X\n\n", get_value(&operand, tmp, label_head, pass, line_no)); address = get_value(&operand, tmp, label_head, pass, line_no); done = 1; break; /************************************************************/ case COMMENT: done = 1; break; /************************************************************/ case BLANK: done = 1; break; /************************************************************/ case ILLEGAL: printf ("Illegal Mnemonic\n"); exit (EXIT_FAILURE); break; /************************************************************/ default: printf ("Not Recognised\n"); exit (EXIT_FAILURE); } } }