// secondPass.c // Functions for the 'second pass' of the SplitBit Assembler. // Written by Anachronaut // 10/25/2024 #ifndef SECONDPASS_H #define SECONDPASS_H #include #include #include "Assm-util.h" // Every label in a program and in everything it includes shares one table, because they // share one namespace: a name may only be defined once across the whole assembly. So this // is not the size of one file but the size of a program and its libraries together, and // CosmOS with its four libraries went past 256 while still being a small system. // // AND PAST 1024 the day the shell learned to finish a word somebody had started. Doubled // rather than nudged: a ceiling reached once is a ceiling that will be reached again, and // the table is pointers into source that is already in memory - 2048 of them is sixteen // kilobytes on a host with gigabytes of it. #define MAX_LABELS 2048 #define MAX_VECTORS 256 typedef struct { char* label; uint16_t address; int type; // Where the name was written. Only the symbol file reads these, and it is the source // of the whole feature: an address tells you a routine exists and a file and line tell // you where to go and read it. // // NEITHER IS OWNED HERE. fileName points at the copy the include list keeps, the same // storage every intermediateElement points at, and the include list outlives the label // table - assemblerCleanup frees the labels first. So freeLabelList must not free it. const char* fileName; int lineNumber; } Label; // Every label and the address it was given, in address order, so that a tally of // addresses can be turned back into a list of routine names. void writeSymbolFile(const char *path); // One line of the Vector Segment, once it has been worked out. typedef struct { char* name; // What it was called, or NULL for a device, which is named by its port. uint8_t index; // Which vector in its table. uint16_t base; // Which table: software or hardware. uint16_t handler; // Where the handler ended up. int declaredOnly; // Named and numbered, with nobody implementing it here. } VectorEntry; void freeLabelList(); void freeVectorList(); // Reads the Vector Segment: allocates a number to every named vector, works out which // vector each device line means, and resolves the handlers. Runs after the labels are // known, because a handler is named by its label. void populateVectorTable(intermediateElement *intermediateArray, int arraySize); // Turns each vector name used as an operand of SWI into the number it was given. void fillInVectorReferences(intermediateElement *intermediateArray, int arraySize); int vectorCount(); void populateLabelTable(intermediateElement *intermediateArray, int arraySize); void fillInLabelAddresses(intermediateElement *intermediateArray, int arraySize); void populateOutputBuffers(intermediateElement *intermediateArray, int arraySize, uint8_t *Program, int *programCount, uint8_t *Data, int *dataCount); void writeOutputFile(const char *outputFileName, uint8_t *Program, int programCount, uint8_t *Data, int dataCount); #endif