diff --git a/AUTHORS b/AUTHORS index f8c27e6..7d19ede 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,4 +2,6 @@ Martin Aigner Christian Barthel Christoph Kirsch Michael Lippautz -Simone Oblasser \ No newline at end of file +Simone Oblasser +Tobias Seiler +Johannes Vollmer \ No newline at end of file diff --git a/selfie.c b/selfie.c index c2b5d87..9dc6325 100755 --- a/selfie.c +++ b/selfie.c @@ -16,7 +16,7 @@ // resolve self-reference in systems code which is seen as the key // challenge when teaching systems engineering, hence the name. // -// Selfie is a fully self-referential 4k-line C implementation of: +// Selfie is a fully self-referential 5k-line C implementation of: // // 1. a self-compiling compiler called cstarc that compiles // a tiny but powerful subset of C called C Star (C*) to @@ -26,14 +26,15 @@ // 3. a tiny C* library called libcstar utilized by cstarc and mipster. // // Selfie is kept minimal for simplicity and implemented in a single file. -// There is no linker, assembler, or debugger. However, there is minimal +// There is neither a linker nor an assembler. However, there is a simple +// profiler and disassembler and even a simple debugger as well as minimal // operating system support in the form of MIPS32 o32 system calls built -// into the emulator. Selfie is meant to be extended in numerous ways. +// into the emulator. // // C* is a tiny Turing-complete subset of C that includes dereferencing -// (the * operator) but excludes data structures, Boolean expressions, and -// many other features. There are only signed 32-bit integers and pointers, -// and character constants for constructing word-aligned strings manually. +// (the * operator) but excludes data structures, bitwise and Boolean +// operators, and many other features. There are only signed 32-bit +// integers and pointers as well as character and string constants. // This choice turns out to be helpful for students to understand the // true role of composite data structures such as arrays and records. // Bitwise operations are implemented in libcstar using signed integer @@ -63,6 +64,8 @@ // The design of the compiler is inspired by the Oberon compiler of // Professor Niklaus Wirth from ETH Zurich. +int *selfieName = (int*) 0; + // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- // --------------------- L I B R A R Y --------------------- @@ -80,40 +83,72 @@ int leftShift(int n, int b); int rightShift(int n, int b); int stringLength(int *s); -void reverseString(int *s); +void stringReverse(int *s); int stringCompare(int *s, int *t); + int atoi(int *s); -int* itoa(int n, int *s, int b, int a); +int* itoa(int n, int *s, int b, int a, int p); + +void putCharacter(int character); + void print(int *s); -void assignString(int *s, int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -int* createString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -void printString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -void memset(int *a, int size, int v); +void println(); + +void printCharacter(int character); +void printString(int *s); void exit(int code); int* malloc(int size); // ------------------------ GLOBAL CONSTANTS ----------------------- +int CHAR_EOF = -1; // end of file +int CHAR_TAB = 9; // ASCII code 9 = tabulator +int CHAR_LF = 10; // ASCII code 10 = line feed +int CHAR_CR = 13; // ASCII code 13 = carriage return +int CHAR_SPACE = ' '; +int CHAR_SEMICOLON = ';'; +int CHAR_PLUS = '+'; +int CHAR_DASH = '-'; +int CHAR_ASTERISK = '*'; +int CHAR_HASH = '#'; +int CHAR_SLASH = '/'; +int CHAR_UNDERSCORE = '_'; +int CHAR_EQUAL = '='; +int CHAR_LPARENTHESIS = '('; +int CHAR_RPARENTHESIS = ')'; +int CHAR_LBRACE = '{'; +int CHAR_RBRACE = '}'; +int CHAR_COMMA = ','; +int CHAR_LT = '<'; +int CHAR_GT = '>'; +int CHAR_EXCLAMATION = '!'; +int CHAR_PERCENTAGE = '%'; +int CHAR_SINGLEQUOTE = 39; // ASCII code 39 = ' +int CHAR_DOUBLEQUOTE = '"'; + int *power_of_two_table; int INT_MAX; // maximum numerical value of an integer int INT_MIN; // minimum numerical value of an integer -int CHAR_TAB; -int CHAR_LF; -int CHAR_CR; +int *character_buffer; // buffer for reading and writing characters +int *string_buffer; // buffer for string output +int *io_buffer; // buffer for binary I/O + +// 0 = O_RDONLY (0x0000) +int O_RDONLY = 0; + +// 577 = 0x0241 = O_CREAT (0x0040) | O_WRONLY (0x0001) | O_TRUNC (0x0200) +int O_CREAT_WRONLY_TRUNC = 577; // flags for opening write-only files -int *string_buffer; +// 420 = 00644 = S_IRUSR (00400) | S_IWUSR (00200) | S_IRGRP (00040) | S_IROTH (00004) +int S_IRUSR_IWUSR_IRGRP_IROTH = 420; // flags for rw-r--r-- file permissions + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *outputName = (int*) 0; +int outputFD = 1; // ------------------------- INITIALIZATION ------------------------ @@ -136,11 +171,12 @@ void initLibrary() { INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; INT_MIN = -INT_MAX - 1; - CHAR_TAB = 9; // ASCII code 9 = tabulator - CHAR_LF = 10; // ASCII code 10 = linefeed - CHAR_CR = 13; // ASCII code 13 = carriage return + character_buffer = malloc(1); + + // accommodate at least 32-bit numbers for itoa + string_buffer = malloc(33); - string_buffer = malloc(33*4); + io_buffer = malloc(4); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -154,370 +190,269 @@ void initLibrary() { // ----------------------------------------------------------------- void initScanner(); +void resetScanner(); + +void printSymbol(int symbol); +void printLineNumber(int* message); + +void syntaxErrorMessage(int *message); +void syntaxErrorCharacter(int character); + +void getCharacter(); -int findNextCharacter(); int isCharacterWhitespace(); -int isCharacterLetterOrDigitOrUnderscore(); -int isCharacterDigit(); +int findNextCharacter(); int isCharacterLetter(); +int isCharacterDigit(); +int isCharacterLetterOrDigitOrUnderscore(); +int isNotDoubleQuoteOrEOF(); int identifierStringMatch(int stringIndex); int identifierOrKeyword(); -int getSymbol(); -void syntaxWarn(int errCode); -void syntaxError(int errCode); +int getSymbol(); // ------------------------ GLOBAL CONSTANTS ----------------------- -int SYM_EOF; // end of file -int SYM_IDENTIFIER; // identifier -int SYM_INTEGER; // a number -int SYM_VOID; // VOID -int SYM_INT; // INT -int SYM_SEMICOLON; // ; -int SYM_IF; // IF -int SYM_ELSE; // ELSE -int SYM_PLUS; // + -int SYM_MINUS; // - -int SYM_ASTERISK; // * -int SYM_DIV; // / -int SYM_EQUAL; // == -int SYM_ASSIGN; // = -int SYM_LPARENTHESIS; // ( -int SYM_RPARENTHESIS; // ) -int SYM_LBRACE; // { -int SYM_RBRACE; // } -int SYM_WHILE; // WHILE -int SYM_RETURN; // RETURN -int SYM_COMMA; // , -int SYM_LT; // < -int SYM_LEQ; // <= -int SYM_GT; // > -int SYM_GEQ; // >= -int SYM_NOTEQ; // != -int SYM_MOD; // % -int SYM_CHARACTER; // char value - -int maxIdentifierLength; // maximum number of characters in an identifier -int maxIntegerLength; // maximum number of characters in an integer - -// Error-Token declaration -int ERR_EOF; -int ERR_UNKNOWN; -int ERR_EXPRESSION; -int ERR_TYPE; -int ERR_IDENTIFIER_OR_LPARENTHESIS; -int ERR_IDENTIFIER; -int ERR_ASSIGN; -int ERR_IDENTIFIER_OR_ASSIGN; -int ERR_IDENT_OR_CONST_OR_EXP; -int ERR_LBRACE_OR_SEMICOLON; -int ERR_PROCEDURE_OR_VARIABLE; -int ERR_UNDECLARED_VARIABLE; -int ERR_TYPE_MISMATCH; -int ERR_WRONG_RETURNTYPE; -int ERR_MAXCODELENGTH; -int ERR_MAXIDENTIFIERLENGTH; -int ERR_WRAPAROUND; -int ERR_STATEMENT; -int ERR_FILE_NOT_FOUND; -int ERR_ILLEGAL_DEREF; -int ERR_IDENTIFIER_OR_INTEGER; - -// strings for better error messages -int *error; -int *warning; -int *errNewline; -int *errLine; -int *errSymbol; -int *stringArray; +int SYM_EOF = -1; // end of file +int SYM_IDENTIFIER = 0; // identifier +int SYM_INTEGER = 1; // integer +int SYM_VOID = 2; // VOID +int SYM_INT = 3; // INT +int SYM_SEMICOLON = 4; // ; +int SYM_IF = 5; // IF +int SYM_ELSE = 6; // ELSE +int SYM_PLUS = 7; // + +int SYM_MINUS = 8; // - +int SYM_ASTERISK = 9; // * +int SYM_DIV = 10; // / +int SYM_EQUALITY = 11; // == +int SYM_ASSIGN = 12; // = +int SYM_LPARENTHESIS = 13; // ( +int SYM_RPARENTHESIS = 14; // ) +int SYM_LBRACE = 15; // { +int SYM_RBRACE = 16; // } +int SYM_WHILE = 17; // WHILE +int SYM_RETURN = 18; // RETURN +int SYM_COMMA = 19; // , +int SYM_LT = 20; // < +int SYM_LEQ = 21; // <= +int SYM_GT = 22; // > +int SYM_GEQ = 23; // >= +int SYM_NOTEQ = 24; // != +int SYM_MOD = 25; // % +int SYM_CHARACTER = 26; // character +int SYM_STRING = 27; // string + +int *SYMBOLS; // array of strings representing symbols + +int maxIdentifierLength = 64; // maximum number of characters in an identifier +int maxIntegerLength = 10; // maximum number of characters in an integer +int maxStringLength = 128; // maximum number of characters in a string // ------------------------ GLOBAL VARIABLES ----------------------- -int lineNumber; // Current Line Number for error reporting -int character; // most recently read character -int symbol; // most recently recognized symbol - -int *identifier; // stores scanned identifier -int *integer; // stores scanned integer as string - -int ivalue; // stores numerical value of scanned integer string - -int mayBeINTMINConstant; // support INT_MIN constant +int lineNumber = 1; // current Line Number for error reporting + +int *identifier = (int*) 0; // stores scanned identifier as string +int *integer = (int*) 0; // stores scanned integer as string +int *string = (int*) 0; // stores scanned string + +int constant = 0; // stores numerical value of scanned integer or character + +int initialValue = 0; // stores initial value of variable definitions + +int mayBeINTMINConstant = 0; // support INT_MIN constant +int isINTMINConstant = 0; + +int character; // most recently read character +int symbol; // most recently recognized symbol + +int *sourceName = (int*) 0; // name of source file +int sourceFD = 0; // file descriptor of open source file + +// ------------------------ OWN GLOBAL VARIABLES ----------------------------------- +// ready queue +int* ready_queue; +// process list +int* process_list; +// number of instructions for one process in one run +int numb_of_instr; +// Address of the actual running process +int* running_process; +// Address of the kernel process +int* kernel_process; +// Frame Table +int* frame_table; +// Number of ticks each Process can run +int ticks; +// Number of Processes +int number_of_processes; +// Number of Processes plus the kernel-process +int all_processes; +// id of the running process +int running_process_id; +// variable if kernel is booting +int booting; +// blocked queue +int* blocked_queue; +// Global lock +int* lock; +// Debugging Variable for locking which indicates the next Process who needs the lock +int debug_locking = 1; +// one page has 4 KB size +int PAGE_SIZE = 4096; +// one frame has 4 KB size +int FRAME_SIZE = 4096; +// Current frame number +int current_frame_number; + +int* prev_node; +int* prev_process; +int* next_node; +int* next_process; + +void create_ready_queue(int n, int m); +int* create_process(int new_pid, int* new_reg, int new_reg_hi, int new_reg_lo); +void create_frame_table(); +int* create_page_table(int* page_table); +int* initializeList(int *list); +int* addToList(int *list, int data); +void printListPID(int *list); +void printListPC(int *list); +int sizeOfList(int *list); +int getNodeFromList(int *list, int nthNode); +int* deleteFirstNodeFromList(int *list); +int* getNodeByIdFromProcessList(int id); +void schedule_and_switch(); // ------------------------- INITIALIZATION ------------------------ void initScanner () { - SYM_EOF = -1; // end of file - SYM_IDENTIFIER = 0; // identifier - SYM_INTEGER = 1; // a number - SYM_VOID = 2; // VOID - SYM_INT = 3; // INT - SYM_SEMICOLON = 4; // ; - SYM_IF = 5; // IF - SYM_ELSE = 6; // ELSE - SYM_PLUS = 7; // + - SYM_MINUS = 8; // - - SYM_ASTERISK = 9; // * - SYM_DIV = 10; // / - SYM_EQUAL = 11; // == - SYM_ASSIGN = 12; // = - SYM_LPARENTHESIS = 13; // ( - SYM_RPARENTHESIS = 14; // ) - SYM_LBRACE = 15; // { - SYM_RBRACE = 16; // } - SYM_WHILE = 17; // WHILE - SYM_RETURN = 18; // RETURN - SYM_COMMA = 19; // , - SYM_LT = 20; // < - SYM_LEQ = 21; // <= - SYM_GT = 22; // > - SYM_GEQ = 23; // >= - SYM_NOTEQ = 24; // != - SYM_MOD = 25; // % - SYM_CHARACTER = 26; // character value - - maxIdentifierLength = 64; - maxIntegerLength = 10; - - ERR_EOF = 40; //keep this b/c -1 is no valid array index - ERR_UNKNOWN = 41; - ERR_EXPRESSION = 42; - ERR_TYPE = 43; - ERR_IDENTIFIER_OR_LPARENTHESIS = 44; - ERR_IDENTIFIER = 45; - ERR_ASSIGN = 46; - ERR_IDENTIFIER_OR_ASSIGN = 47; - ERR_IDENT_OR_CONST_OR_EXP = 48; - ERR_LBRACE_OR_SEMICOLON = 49; - ERR_PROCEDURE_OR_VARIABLE = 50; - ERR_UNDECLARED_VARIABLE = 51; - ERR_TYPE_MISMATCH = 52; - ERR_WRONG_RETURNTYPE = 53; - ERR_MAXCODELENGTH = 54; - ERR_MAXIDENTIFIERLENGTH = 55; - ERR_WRAPAROUND = 56; - ERR_STATEMENT = 57; - ERR_FILE_NOT_FOUND = 58; - ERR_ILLEGAL_DEREF = 59; - ERR_IDENTIFIER_OR_INTEGER = 60; - - // ------------ "ERROR: " ------------ - error = createString('E','R','R','O','R',':',' ',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "WARNING: " ------------ - warning = createString('W','A','R','N','I','N','G',':',' ',0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "/n" ------------ - errNewline = createString(10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ", line " ------------ - errLine = createString(',',' ','l','i','n','e',' ',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ", current symbol: " ------------ - errSymbol = createString(',',' ','c','u','r','r','e','n','t',' ','s','y','m','b','o','l',':',' ',0,0); - - // -------------------- ERROR TOKENS -------------------- - - stringArray = (int*)malloc(4*70); - - // ------------ "unknown" ------------ - *(stringArray + ERR_UNKNOWN) = (int)createString('u','n','k','n','o','w','n',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "expression" ------------ - *(stringArray + ERR_EXPRESSION) = (int)createString('e','x','p','r','e','s','s','i','o','n',0,0,0,0,0,0,0,0,0,0); - - // ------------ "while" ------------ - *(stringArray + SYM_WHILE) = (int)createString('w','h','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "if" ------------ - *(stringArray + SYM_IF) = (int)createString('i','f',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "return" ------------ - *(stringArray + SYM_RETURN) = (int)createString('r','e','t','u','r','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "type" ------------ - *(stringArray + ERR_TYPE) = (int)createString('t','y','p','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "(" ------------ - *(stringArray + SYM_LPARENTHESIS) = (int)createString('(',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ")" ------------ - *(stringArray + SYM_RPARENTHESIS) = (int)createString(')',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "{" ------------ - *(stringArray + SYM_LBRACE) = (int)createString('{',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "}" ------------ - *(stringArray + SYM_RBRACE) = (int)createString('}',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ";" ------------ - *(stringArray + SYM_SEMICOLON) = (int)createString(';',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "ident or (" ------------ - *(stringArray + ERR_IDENTIFIER_OR_LPARENTHESIS) = (int)createString('i','d','e','n','t',' ','o','r',' ','(',0,0,0,0,0,0,0,0,0,0); - - // ------------ "identifier" ------------ - *(stringArray + ERR_IDENTIFIER) = (int)createString('i','d','e','n','t','i','f','i','e','r',0,0,0,0,0,0,0,0,0,0); - - // ------------ "assign" ------------ - *(stringArray + ERR_ASSIGN) = (int)createString('a','s','s','i','g','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "ident or assign" ------------ - *(stringArray + ERR_IDENTIFIER_OR_ASSIGN) = (int)createString('i','d','e','n','t',' ','o','r',' ','a','s','s','i','g','n',0,0,0,0,0); - - // ------------ "ident, const or exp" ------------ - *(stringArray + ERR_IDENT_OR_CONST_OR_EXP) = (int)createString('i','d','e','n','t',',',' ','c','o','n','s','t',' ','o','r',' ','e','x','p',0); - - // ------------ "( or ;" ------------ - *(stringArray + ERR_LBRACE_OR_SEMICOLON) = (int)createString('(',' ','o','r',' ',';',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "procedure or var"------------ - *(stringArray + ERR_PROCEDURE_OR_VARIABLE) = (int)createString('p','r','o','c','e','d','u','r','e',' ','o','r',' ','v','a','r',0,0,0,0); - - // ------------ "eof" ------------ - *(stringArray + ERR_EOF) = (int)createString('e','o','f',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "undeclared var"------------ - *(stringArray + ERR_UNDECLARED_VARIABLE) = (int)createString('u','n','d','e','c','l','a','r','e','d',' ','v','a','r',0,0,0,0,0,0); - - // ------------ "type mismatch" ------------ - *(stringArray + ERR_TYPE_MISMATCH) = (int)createString('t','y','p','e',' ','m','i','s','m','a','t','c','h',0,0,0,0,0,0,0); - - // ------------ "wrong return type" ------------ - *(stringArray + ERR_WRONG_RETURNTYPE) = (int)createString('w','r','o','n','g',' ','r','e','t','u','r','n',' ','t','y','p','e',0,0,0); - - // ------------ "statement" ------------ - *(stringArray + ERR_STATEMENT) = (int)createString('s','t','a','t','e','m','e','n','t',0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "wraparound" ------------ - *(stringArray + ERR_WRAPAROUND) = (int)createString('w','r','a','p','a','r','o','u','n','d',0,0,0,0,0,0,0,0,0,0); - - // ------------ "maxcodelength" ------------ - *(stringArray + ERR_MAXCODELENGTH) = (int)createString('m','a','x','c','o','d','e','l','e','n','g','t','h',0,0,0,0,0,0,0); - - // ------------ "maxidentlength" ------------ - *(stringArray + ERR_MAXIDENTIFIERLENGTH) = (int)createString('m','a','x','i','d','e','n','t','l','e','n','g','t','h',0,0,0,0,0,0); - - // ------------ "file not found" ------------ - *(stringArray + ERR_FILE_NOT_FOUND) = (int)createString('f','i','l','e',' ','n','o','t',' ','f','o','u','n','d',0,0,0,0,0,0); - - // ------------ "else" ------------ - *(stringArray + SYM_ELSE) = (int)createString('e','l','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "void" ------------ - *(stringArray + SYM_VOID) = (int)createString('v','o','i','d',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "int" ------------ - *(stringArray + SYM_INT) = (int)createString('i','n','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - + SYMBOLS = malloc(28*4); + + *(SYMBOLS + SYM_IDENTIFIER) = (int) "identifier"; + *(SYMBOLS + SYM_INTEGER) = (int) "integer"; + *(SYMBOLS + SYM_VOID) = (int) "void"; + *(SYMBOLS + SYM_INT) = (int) "int"; + *(SYMBOLS + SYM_SEMICOLON) = (int) ";"; + *(SYMBOLS + SYM_IF) = (int) "if"; + *(SYMBOLS + SYM_ELSE) = (int) "else"; + *(SYMBOLS + SYM_PLUS) = (int) "+"; + *(SYMBOLS + SYM_MINUS) = (int) "-"; + *(SYMBOLS + SYM_ASTERISK) = (int) "*"; + *(SYMBOLS + SYM_DIV) = (int) "/"; + *(SYMBOLS + SYM_EQUALITY) = (int) "=="; + *(SYMBOLS + SYM_ASSIGN) = (int) "="; + *(SYMBOLS + SYM_LPARENTHESIS) = (int) "("; + *(SYMBOLS + SYM_RPARENTHESIS) = (int) ")"; + *(SYMBOLS + SYM_LBRACE) = (int) "{"; + *(SYMBOLS + SYM_RBRACE) = (int) "}"; + *(SYMBOLS + SYM_WHILE) = (int) "while"; + *(SYMBOLS + SYM_RETURN) = (int) "return"; + *(SYMBOLS + SYM_COMMA) = (int) ","; + *(SYMBOLS + SYM_LT) = (int) "<"; + *(SYMBOLS + SYM_LEQ) = (int) "<="; + *(SYMBOLS + SYM_GT) = (int) ">"; + *(SYMBOLS + SYM_GEQ) = (int) ">="; + *(SYMBOLS + SYM_NOTEQ) = (int) "!="; + *(SYMBOLS + SYM_MOD) = (int) "%"; + *(SYMBOLS + SYM_CHARACTER) = (int) "character"; + *(SYMBOLS + SYM_STRING) = (int) "string"; + + character = CHAR_EOF; + symbol = SYM_EOF; +} + +void resetScanner() { lineNumber = 1; - character = getchar(); - symbol = -1; - - identifier = 0; - integer = 0; - ivalue = 0; - - mayBeINTMINConstant = 0; + getCharacter(); + getSymbol(); } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void initSymbolTable(); +void resetGlobalSymbolTable(); -void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int class, int type); -int *getSymbolTableEntry(int *ident, int *symbol_table); +void createSymbolTableEntry(int which, int *string, int data, int class, int type, int value); +int* getSymbolTableEntry(int *string, int class, int *symbol_table); -int *getNext(int *entry); -int *getIdentifier(int *entry); +int* getNext(int *entry); +int* getString(int *entry); int getData(int *entry); int getClass(int *entry); int getType(int *entry); +int getValue(int *entry); int getRegister(int *entry); void setNext(int *entry, int *next); -void setIdentifier(int *entry, int *identifier); +void setString(int *entry, int *identifier); void setData(int *entry, int data); void setClass(int *entry, int class); void setType(int *entry, int type); +void setValue(int *entry, int value); void setRegister(int *entry, int reg); // ------------------------ GLOBAL CONSTANTS ----------------------- // classes -int UNKNOWN; // 0 -int CONSTANT; // 1 -int VARIABLE; // 2 -int FUNCTION; // 3 +int VARIABLE = 1; +int FUNCTION = 2; +int STRING = 3; // types -int INT_T; // 1 -int INTSTAR_T; // 2 -int VOID_T; // 3 +int INT_T = 1; +int INTSTAR_T = 2; +int VOID_T = 3; // symbol tables -int GLOBAL_TABLE; -int LOCAL_TABLE; +int GLOBAL_TABLE = 1; +int LOCAL_TABLE = 2; // ------------------------ GLOBAL VARIABLES ----------------------- -// table pointer -int *global_symbol_table; -int *local_symbol_table; +// table pointers +int *global_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; // ------------------------- INITIALIZATION ------------------------ -void initSymbolTable() { - // classes - UNKNOWN = 0; - CONSTANT = 1; - VARIABLE = 2; - FUNCTION = 3; - - // types - INT_T = 1; - INTSTAR_T = 2; - VOID_T = 3; - - // symbol tables - GLOBAL_TABLE = 1; - LOCAL_TABLE = 2; - - // table pointer - global_symbol_table = 0; - local_symbol_table = 0; +void resetGlobalSymbolTable() { + global_symbol_table = (int*) 0; } // ----------------------------------------------------------------- // ---------------------------- PARSER ----------------------------- // ----------------------------------------------------------------- -void initParser(); - int isNotRbraceOrEOF(); -int isVariableOrProcedure(); int isExpression(); -int isPlusOrMinus(); int isStarOrDivOrModulo(); +int isPlusOrMinus(); +int isComparison(); -int waitForStatement(); -int waitForVariable(); -int waitForFactor(); +int lookForFactor(); +int lookForStatement(); +int lookForType(); -void save_registers(); -void restore_registers(int numberOfRegisters); +void save_temporaries(); +void restore_temporaries(int numberOfTemporaries); + +void syntaxErrorSymbol(int expected); +void syntaxErrorUnexpected(); +int* putType(int type); +void typeWarning(int expected, int found); int* getVariable(int *variable); int load_variable(int *variable); void load_integer(); +void load_string(); int help_call_codegen(int *entry, int *procedure); void help_procedure_prologue(int localVariables); -void help_procedure_epilogue(int parameters, int functionStart, int functionType); +void help_procedure_epilogue(int parameters); int gr_call(int *procedure); int gr_factor(); @@ -528,37 +463,22 @@ void gr_while(); void gr_if(); void gr_return(int returnType); void gr_statement(); -int gr_variable(); +int gr_type(); +void gr_variable(int offset); +void gr_initialization(int *name, int offset, int type); void gr_procedure(int *procedure, int returnType); void gr_cstar(); -// ------------------------ GLOBAL CONSTANTS ----------------------- - -int maxCodeLength; - // ------------------------ GLOBAL VARIABLES ----------------------- -int allocatedRegisters; // number of allocated registers -int allocatedGlobalVariables; // number of global variables - -int codeLength; -int returnBranches; -int *currentFuncName; // holds the name of currently parsed function - -// ------------------------- INITIALIZATION ------------------------ +int allocatedTemporaries = 0; // number of allocated temporaries -void -initParser() { - // set maximum code length for emitting code - maxCodeLength = 32000; +int allocatedMemory = 0; // number of bytes for global variables and strings - allocatedRegisters = 0; - allocatedGlobalVariables = 0; +int mainJumpAddress = 0; // address of main function +int returnBranches = 0; // fixup chain for return statements - codeLength = 0; - returnBranches = 0; - currentFuncName = 0; -} +int *currentProcedureName = (int*) 0; // name of currently parsed procedure // ----------------------------------------------------------------- // ---------------------- MACHINE CODE LIBRARY --------------------- @@ -567,6 +487,12 @@ initParser() { void emitLeftShiftBy(int b); void emitMainEntry(); +// ----------------------------------------------------------------- +// --------------------------- COMPILER ---------------------------- +// ----------------------------------------------------------------- + +void compile(); + // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- // ------------------- I N T E R F A C E ------------------- @@ -577,36 +503,84 @@ void emitMainEntry(); // ---------------------------- REGISTER --------------------------- // ----------------------------------------------------------------- +void initRegister(); + +void printRegister(int reg); + // ------------------------ GLOBAL CONSTANTS ----------------------- -int REG_ZR; -int REG_V0; -int REG_A0; -int REG_A1; -int REG_A2; -int REG_A3; -int REG_RR; -int REG_K1; -int REG_GP; -int REG_SP; -int REG_FP; -int REG_LINK; +int REG_ZR = 0; +int REG_AT = 1; +int REG_V0 = 2; +int REG_V1 = 3; +int REG_A0 = 4; +int REG_A1 = 5; +int REG_A2 = 6; +int REG_A3 = 7; +int REG_T0 = 8; +int REG_T1 = 9; +int REG_T2 = 10; +int REG_T3 = 11; +int REG_T4 = 12; +int REG_T5 = 13; +int REG_T6 = 14; +int REG_T7 = 15; +int REG_S0 = 16; +int REG_S1 = 17; +int REG_S2 = 18; +int REG_S3 = 19; +int REG_S4 = 20; +int REG_S5 = 21; +int REG_S6 = 22; +int REG_S7 = 23; +int REG_T8 = 24; +int REG_T9 = 25; +int REG_K0 = 26; +int REG_K1 = 27; +int REG_GP = 28; +int REG_SP = 29; +int REG_FP = 30; +int REG_RA = 31; + +int *REGISTERS; // array of strings representing registers // ------------------------- INITIALIZATION ------------------------ void initRegister() { - REG_ZR = 0; - REG_V0 = 2; - REG_A0 = 4; - REG_A1 = 5; - REG_A2 = 6; - REG_A3 = 7; - REG_RR = 26; - REG_K1 = 27; - REG_GP = 28; - REG_SP = 29; - REG_FP = 30; - REG_LINK = 31; + REGISTERS = malloc(32*4); + + *(REGISTERS + REG_ZR) = (int) "$zero"; + *(REGISTERS + REG_AT) = (int) "$at"; + *(REGISTERS + REG_V0) = (int) "$v0"; + *(REGISTERS + REG_V1) = (int) "$v1"; + *(REGISTERS + REG_A0) = (int) "$a0"; + *(REGISTERS + REG_A1) = (int) "$a1"; + *(REGISTERS + REG_A2) = (int) "$a2"; + *(REGISTERS + REG_A3) = (int) "$a3"; + *(REGISTERS + REG_T0) = (int) "$t0"; + *(REGISTERS + REG_T1) = (int) "$t1"; + *(REGISTERS + REG_T2) = (int) "$t2"; + *(REGISTERS + REG_T3) = (int) "$t3"; + *(REGISTERS + REG_T4) = (int) "$t4"; + *(REGISTERS + REG_T5) = (int) "$t5"; + *(REGISTERS + REG_T6) = (int) "$t6"; + *(REGISTERS + REG_T7) = (int) "$t7"; + *(REGISTERS + REG_S0) = (int) "$s0"; + *(REGISTERS + REG_S1) = (int) "$s1"; + *(REGISTERS + REG_S2) = (int) "$s2"; + *(REGISTERS + REG_S3) = (int) "$s3"; + *(REGISTERS + REG_S4) = (int) "$s4"; + *(REGISTERS + REG_S5) = (int) "$s5"; + *(REGISTERS + REG_S6) = (int) "$s6"; + *(REGISTERS + REG_S7) = (int) "$s7"; + *(REGISTERS + REG_T8) = (int) "$t8"; + *(REGISTERS + REG_T9) = (int) "$t9"; + *(REGISTERS + REG_K0) = (int) "$k0"; + *(REGISTERS + REG_K1) = (int) "$k1"; + *(REGISTERS + REG_GP) = (int) "$gp"; + *(REGISTERS + REG_SP) = (int) "$sp"; + *(REGISTERS + REG_FP) = (int) "$fp"; + *(REGISTERS + REG_RA) = (int) "$ra"; } // ----------------------------------------------------------------- @@ -632,6 +606,9 @@ int signExtend(int immediate); void initDecoder(); +void printOpcode(int opcode); +void printFunction(int function); + void decode(); void decodeRFormat(); void decodeIFormat(); @@ -639,81 +616,78 @@ void decodeJFormat(); // ------------------------ GLOBAL CONSTANTS ----------------------- -int OP_SPECIAL; -int FCT_SYSCALL; -int FCT_MFHI; -int FCT_MFLO; -int FCT_MULTU; -int FCT_DIVU; -int OP_ADDIU; -int FCT_ADDU; -int FCT_SUBU; -int OP_LW; -int OP_SW; -int OP_BEQ; -int OP_BNE; -int FCT_SLT; -int FCT_NOP; -int FCT_JR; -int OP_JAL; -int OP_J; -int FCT_TEQ; +int OP_SPECIAL = 0; +int OP_J = 2; +int OP_JAL = 3; +int OP_BEQ = 4; +int OP_BNE = 5; +int OP_ADDIU = 9; +int OP_LW = 35; +int OP_SW = 43; + +int *OPCODES; // array of strings representing MIPS opcodes + +int FCT_NOP = 0; +int FCT_JR = 8; +int FCT_SYSCALL = 12; +int FCT_MFHI = 16; +int FCT_MFLO = 18; +int FCT_MULTU = 25; +int FCT_DIVU = 27; +int FCT_ADDU = 33; +int FCT_SUBU = 35; +int FCT_SLT = 42; +int FCT_TEQ = 52; + +int *FUNCTIONS; // array of strings representing MIPS functions // ------------------------ GLOBAL VARIABLES ----------------------- -int opcode; -int rs; -int rt; -int rd; -int immediate; -int function; -int instr_index; +int opcode = 0; +int rs = 0; +int rt = 0; +int rd = 0; +int immediate = 0; +int function = 0; +int instr_index = 0; // ------------------------- INITIALIZATION ------------------------ void initDecoder() { - OP_SPECIAL = 0; - FCT_NOP = 0; - OP_JAL = 3; - OP_J = 2; - OP_BEQ = 4; - OP_BNE = 5; - OP_ADDIU = 9; - FCT_JR = 8; - FCT_SYSCALL = 12; - FCT_MFHI = 16; - FCT_MFLO = 18; - FCT_MULTU = 25; - FCT_DIVU = 27; - FCT_ADDU = 33; - FCT_SUBU = 35; - OP_LW = 35; - FCT_SLT = 42; - OP_SW = 43; - FCT_TEQ = 52; - - opcode = 0; - rs = 0; - rt = 0; - rd = 0; - immediate = 0; - function = 0; - instr_index = 0; + OPCODES = malloc(44*4); + + *(OPCODES + OP_SPECIAL) = (int) "nop"; + *(OPCODES + OP_J) = (int) "j"; + *(OPCODES + OP_JAL) = (int) "jal"; + *(OPCODES + OP_BEQ) = (int) "beq"; + *(OPCODES + OP_BNE) = (int) "bne"; + *(OPCODES + OP_ADDIU) = (int) "addiu"; + *(OPCODES + OP_LW) = (int) "lw"; + *(OPCODES + OP_SW) = (int) "sw"; + + FUNCTIONS = malloc(53*4); + + *(FUNCTIONS + FCT_NOP) = (int) "nop"; + *(FUNCTIONS + FCT_JR) = (int) "jr"; + *(FUNCTIONS + FCT_SYSCALL) = (int) "syscall"; + *(FUNCTIONS + FCT_MFHI) = (int) "mfhi"; + *(FUNCTIONS + FCT_MFLO) = (int) "mflo"; + *(FUNCTIONS + FCT_MULTU) = (int) "multu"; + *(FUNCTIONS + FCT_DIVU) = (int) "divu"; + *(FUNCTIONS + FCT_ADDU) = (int) "addu"; + *(FUNCTIONS + FCT_SUBU) = (int) "subu"; + *(FUNCTIONS + FCT_SLT) = (int) "slt"; + *(FUNCTIONS + FCT_TEQ) = (int) "teq"; } // ----------------------------------------------------------------- -// ---------------------------- MEMORY ----------------------------- +// ----------------------------- CODE ------------------------------ // ----------------------------------------------------------------- -void allocateMachineMemory(int size); - -// ------------------------ GLOBAL VARIABLES ----------------------- - -int *memory; // machine memory +int loadBinary(int addr); +void storeBinary(int addr, int instruction); -// ----------------------------------------------------------------- -// ---------------------------- BINARY ----------------------------- -// ----------------------------------------------------------------- +void storeInstruction(int addr, int instruction); void emitInstruction(int instruction); void emitRFormat(int opcode, int rs, int rt, int rd, int function); @@ -724,15 +698,36 @@ void fixup_relative(int fromAddress); void fixup_absolute(int fromAddress, int toAddress); void fixlink_absolute(int fromAddress, int toAddress); -void emitBinary(); -int loadBinary(int *filename); +int copyStringToBinary(int *s, int a); + +void emitGlobalsStrings(); + +void emit(); +void load(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int maxBinaryLength = 131072; // 128KB + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *binary = (int*) 0; // binary of emitted instructions + +int binaryLength = 0; // length of binary in bytes incl. globals & strings + +int codeLength = 0; // length of code portion of binary in bytes + +int *binaryName = (int*) 0; // file name of binary + +int *sourceLineNumber = (int*) 0; // source line number per emitted instruction + +int *assemblyName = (int*) 0; // name of assembly file +int assemblyFD = 0; // file descriptor of open assembly file // ----------------------------------------------------------------- // --------------------------- SYSCALLS ---------------------------- // ----------------------------------------------------------------- -void initSyscalls(); - void emitExit(); void syscall_exit(); @@ -748,30 +743,35 @@ void syscall_open(); void emitMalloc(); void syscall_malloc(); -void emitGetchar(); -void syscall_getchar(); - void emitPutchar(); -// ------------------------ GLOBAL CONSTANTS ----------------------- +void emitSchedYield(); +void syscall_sched_yield(); -int SYSCALL_EXIT; -int SYSCALL_READ; -int SYSCALL_WRITE; -int SYSCALL_OPEN; -int SYSCALL_MALLOC; -int SYSCALL_GETCHAR; +void emitSwitch(); +void syscall_switch(); -// ------------------------- INITIALIZATION ------------------------ +void emitMlock(); +void syscall_mlock(); -void initSyscalls() { - SYSCALL_EXIT = 4001; - SYSCALL_READ = 4003; - SYSCALL_WRITE = 4004; - SYSCALL_OPEN = 4005; - SYSCALL_MALLOC = 5001; - SYSCALL_GETCHAR = 5002; -} +void emitMunlock(); +void syscall_munlock(); + +void emitGetpid(); +void syscall_getpid(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; +int SYSCALL_MALLOC = 5001; +int SYSCALL_SCHED_YIELD = 5003; +int SYSCALL_SWITCH = 5004; +int SYSCALL_MLOCK = 5005; +int SYSCALL_MUNLOCK = 5006; +int SYSCALL_GETPID = 5007; // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -779,6 +779,45 @@ void initSyscalls() { // ----------------------------------------------------------------- // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +void initMemory(int bytes); + +int tlb(int vaddr); + +int loadMemory(int vaddr); +void storeMemory(int vaddr, int data); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int MEGABYTE = 1048576; + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int memorySize = 0; // size of memory in bytes + +int *memory = (int*) 0; // mipster memory + +// Initializing the size of the virtual memory +int virtual_memory_size = 0; + +// ------------------------- INITIALIZATION ------------------------ + +void initMemory(int megabytes) { + if (megabytes < 0) + megabytes = 64; + else if (megabytes > 1024) + megabytes = 1024; + + // Initializing the physical memory + memorySize = megabytes * 1024 * 1024; + memory = malloc(memorySize); + + virtual_memory_size = 4 * 1024 * 1024; +} + // ----------------------------------------------------------------- // ------------------------- INSTRUCTIONS -------------------------- // ----------------------------------------------------------------- @@ -791,7 +830,6 @@ void op_beq(); void op_bne(); void op_addiu(); void fct_jr(); -void op_lui(); void fct_mfhi(); void fct_mflo(); void fct_multu(); @@ -808,136 +846,112 @@ void op_teq(); // ----------------------------------------------------------------- void initInterpreter(); +void resetInterpreter(); -void exception_handler(int enumber); - -int addressTranslation(int vaddr); +void printException(int enumber); -void pre_debug(); -void post_debug(); +void exception_handler(int enumber); void fetch(); void execute(); -void run(); +void run(int argc, int* argv) ; -void debug_boot(int memorySize); -int* parse_args(int argc, int *argv, int *cstar_argv); void up_push(int value); int up_malloc(int size); -int up_copyCString(int *s); +int up_copyString(int *s); void up_copyArguments(int argc, int *argv); -int main_emulator(int argc, int *argv, int *cstar_argv); +void copyBinaryToMemory(); + +int addressWithMaxCounter(int *counters, int max); +int fixedPointRatio(int a, int b); + +int printCounters(int total, int *counters, int max); +void printProfile(int *message, int total, int *counters); + +void disassemble(int argc, int* argv); +void emulate(int argc, int *argv); // ------------------------ GLOBAL CONSTANTS ----------------------- -int *register_strings; // static strings for register names -int *op_strings; // static strings for debug_disassemble -int *fct_strings; +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; +int debug_sched_yield = 1; +int debug_switch = 1; -int debug_registers; -int debug_syscalls; -int debug_load; -int debug_disassemble; +int EXCEPTION_SIGNAL = 1; +int EXCEPTION_ADDRESSERROR = 2; +int EXCEPTION_UNKNOWNINSTRUCTION = 3; +int EXCEPTION_HEAPOVERFLOW = 4; +int EXCEPTION_UNKNOWNSYSCALL = 5; +int EXCEPTION_UNKNOWNFUNCTION = 6; -int EXCEPTION_SIGNAL; -int EXCEPTION_ADDRESSERROR; -int EXCEPTION_UNKNOWNINSTRUCTION; -int EXCEPTION_HEAPOVERFLOW; -int EXCEPTION_UNKNOWNSYSCALL; -int EXCEPTION_UNKNOWNFUNCTION; +int *EXCEPTIONS; // array of strings representing exceptions // ------------------------ GLOBAL VARIABLES ----------------------- int *registers; // general purpose registers -int pc; // program counter -int ir; // instruction record +int pc = 0; // program counter +int ir = 0; // instruction record + +int reg_hi = 0; // hi register for multiplication/division +int reg_lo = 0; // lo register for multiplication/division + +int halt = 0; // flag for halting mipster + +int interpret = 0; + +int debug = 0; + +int calls = 0; // total number of executed procedure calls +int *callsPerAddress = (int*) 0; // number of executed calls of each procedure -int reg_hi; // hi register for multiplication/division -int reg_lo; // lo register for multiplication/division +int loops = 0; // total number of executed loop iterations +int *loopsPerAddress = (int*) 0; // number of executed iterations of each loop + +int loads = 0; // total number of executed memory loads +int *loadsPerAddress = (int*) 0; // number of executed loads per load operation + +int stores = 0; // total number of executed memory stores +int *storesPerAddress = (int*) 0; // number of executed stores per store operation // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { - register_strings = (int*)malloc(4*32); - op_strings = (int*)malloc(4*64); - fct_strings = (int*)malloc(4*64); - - *(register_strings + 0) = (int)createString('z','e','r','o',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 1) = (int)createString('a','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 2) = (int)createString('v','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 3) = (int)createString('v','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 4) = (int)createString('a','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 5) = (int)createString('a','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 6) = (int)createString('a','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 7) = (int)createString('a','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 8) = (int)createString('t','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 9) = (int)createString('t','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 10) = (int)createString('t','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 11) = (int)createString('t','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 12) = (int)createString('t','4',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 13) = (int)createString('t','5',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 14) = (int)createString('t','6',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 15) = (int)createString('t','7',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 16) = (int)createString('s','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 17) = (int)createString('s','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 18) = (int)createString('s','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 19) = (int)createString('s','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 20) = (int)createString('s','4',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 21) = (int)createString('s','5',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 22) = (int)createString('s','6',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 23) = (int)createString('s','7',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 24) = (int)createString('t','8',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 25) = (int)createString('t','9',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 26) = (int)createString('k','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 27) = (int)createString('k','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 28) = (int)createString('g','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 29) = (int)createString('s','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 30) = (int)createString('f','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 31) = (int)createString('r','a',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - *(fct_strings + 0) = (int)createString('n','o','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 8) = (int)createString('j','r',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 12) = (int)createString('s','y','s','c','a','l','l',0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 16) = (int)createString('m','f','h','i',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 18) = (int)createString('m','f','l','o',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 25) = (int)createString('m','u','l','t','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 27) = (int)createString('d','i','v','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 33) = (int)createString('a','d','d','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 35) = (int)createString('s','u','b','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 42) = (int)createString('s','l','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 52) = (int)createString('t','e','q',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - *(op_strings + 0) = (int)createString('n','o','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 3) = (int)createString('j','a','l',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 2) = (int)createString('j',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 4) = (int)createString('b','e','q',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 5) = (int)createString('b','n','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 9) = (int)createString('a','d','d','i','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 15) = (int)createString('l','u','i',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 35) = (int)createString('l','w',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 43) = (int)createString('s','w',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - debug_registers = 0; - debug_syscalls = 0; - debug_load = 0; - debug_disassemble = 0; - - EXCEPTION_SIGNAL = 1; - EXCEPTION_ADDRESSERROR = 2; - EXCEPTION_UNKNOWNINSTRUCTION = 3; - EXCEPTION_HEAPOVERFLOW = 4; - EXCEPTION_UNKNOWNSYSCALL = 5; - EXCEPTION_UNKNOWNFUNCTION = 6; - - registers = (int*)malloc(32*4); + EXCEPTIONS = malloc(7*4); + + *(EXCEPTIONS + EXCEPTION_SIGNAL) = (int) "signal"; + *(EXCEPTIONS + EXCEPTION_ADDRESSERROR) = (int) "address error"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNINSTRUCTION) = (int) "unknown instruction"; + *(EXCEPTIONS + EXCEPTION_HEAPOVERFLOW) = (int) "heap overflow"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNSYSCALL) = (int) "unknown syscall"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNFUNCTION) = (int) "unknown function"; + + registers = malloc(32*4); +} +void resetInterpreter() { pc = 0; - ir = 0; reg_hi = 0; reg_lo = 0; + + if (interpret) { + calls = 0; + callsPerAddress = malloc(maxBinaryLength); + + loops = 0; + loopsPerAddress = malloc(maxBinaryLength); + + loads = 0; + loadsPerAddress = malloc(maxBinaryLength); + + stores = 0; + storesPerAddress = malloc(maxBinaryLength); + } } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -972,78 +986,130 @@ int rightShift(int n, int b) { else if (n >= 0) return n / twoToThePowerOf(b); else - // works even if n == INT_MIN + // works even if n == INT_MIN: + // shift right n with msb reset and then restore msb return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + (INT_MAX / twoToThePowerOf(b) + 1); } +int loadCharacter(int *s, int i) { + // assert: i >= 0 + int a; + + a = i / 4; + + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); +} + +int* storeCharacter(int *s, int i, int c) { + // assert: i >= 0, all characters are 7-bit + int a; + + a = i / 4; + + *(s + a) = (*(s + a) - leftShift(loadCharacter(s, i), (i % 4) * 8)) + leftShift(c, (i % 4) * 8); + + return s; +} + int stringLength(int *s) { int i; i = 0; - while (*(s+i) != 0) + while (loadCharacter(s, i) != 0) i = i + 1; return i; } -void reverseString(int *s) { - int tmp; +void stringReverse(int *s) { int i; int j; + int tmp; i = 0; j = stringLength(s) - 1; while (i < j) { - tmp = *(s+i); - *(s+i) = *(s+j); - *(s+j) = tmp; + tmp = loadCharacter(s, i); + + storeCharacter(s, i, loadCharacter(s, j)); + storeCharacter(s, j, tmp); + i = i + 1; j = j - 1; } } -int stringCompare(int* s, int* t) { +int stringCompare(int *s, int *t) { + int i; + + i = 0; + while (1) - if (*s == 0) - if (*t == 0) + if (loadCharacter(s, i) == 0) + if (loadCharacter(t, i) == 0) return 1; else return 0; - else if (*s == *t) { - s = s + 1; - t = t + 1; - } else + else if (loadCharacter(s, i) == loadCharacter(t, i)) + i = i + 1; + else return 0; } -int atoi(int* s) { +int atoi(int *s) { + int i; int n; + int c; + + i = 0; n = 0; - while (*s != 0) { - n = n * 10 + *s - '0'; - s = s + 1; + c = loadCharacter(s, i); + + while (c != 0) { + c = c - '0'; + + if (c < 0) + return -1; + else if (c > 9) + return -1; + + n = n * 10 + c; + + i = i + 1; + + c = loadCharacter(s, i); + + if (n < 0) { + if (n != INT_MIN) + return -1; + else if (c != 0) + return -1; + } } return n; } -int* itoa(int n, int *s, int b, int a) { +int* itoa(int n, int *s, int b, int a, int p) { // assert: b in {2,4,8,10,16} int i; int sign; + int msb; i = 0; sign = 0; + msb = 0; + if (n == 0) { - *s = '0'; + storeCharacter(s, 0, '0'); i = 1; } else if (n < 0) { @@ -1051,108 +1117,167 @@ int* itoa(int n, int *s, int b, int a) { if (b == 10) { if (n == INT_MIN) { - *s = '8'; // rightmost decimal digit of 32-bit INT_MIN + // rightmost decimal digit of 32-bit INT_MIN + storeCharacter(s, 0, '8'); + // avoids overflow n = -(n / 10); - i = i + 1; + i = 1; } else n = -n; } else { if (n == INT_MIN) { - *s = '0'; // rightmost non-decimal digit of INT_MIN + // rightmost non-decimal digit of INT_MIN + storeCharacter(s, 0, '0'); + // avoids setting n to 0 n = (rightShift(INT_MIN, 1) / b) * 2; - i = i + 1; - } else - n = rightShift(leftShift(n, 1), 1); + i = 1; + } else { + // reset msb, restore below + n = rightShift(leftShift(n, 1), 1); + msb = 1; + } } + + // assert: n > 0 } while (n != 0) { - *(s+i) = n % b; + if (p > 0) + if (i == p) { + storeCharacter(s, i, '.'); // set point of fixed point number - if (*(s+i) > 9) - *(s+i) = *(s+i) - 10 + 'A'; + i = i + 1; + p = 0; + } + + if (n % b > 9) + storeCharacter(s, i, n % b - 10 + 'A'); else - *(s+i) = *(s+i) + '0'; + storeCharacter(s, i, n % b + '0'); n = n / b; i = i + 1; - if (i == 1) { - if (sign) { - if (b != 10) - n = n + (rightShift(INT_MIN, 1) / b) * 2; - } + if (msb == 1) { + // restore msb from above + n = n + (rightShift(INT_MIN, 1) / b) * 2; + msb = 0; } } - if (b != 10) { + if (p > 0) { + while (i < p) { + storeCharacter(s, i, '0'); // no point yet, fill with 0s + + i = i + 1; + } + + storeCharacter(s, i, '.'); // set point + storeCharacter(s, i + 1, '0'); // leading 0 + + i = i + 2; + p = 0; + } + + if (b == 10) { + if (sign) { + storeCharacter(s, i, '-'); // negative decimal numbers start with - + + i = i + 1; + } + while (i < a) { - *(s+i) = '0'; // align with zeros + storeCharacter(s, i, ' '); // align with spaces i = i + 1; } - } else if (sign) { - *(s+i) = '-'; + } else { + while (i < a) { + storeCharacter(s, i, '0'); // align with 0s - i = i + 1; + i = i + 1; + } + + if (b == 8) { + storeCharacter(s, i, '0'); // octal numbers start with 00 + storeCharacter(s, i + 1, '0'); + + i = i + 2; + } else if (b == 16) { + storeCharacter(s, i, 'x'); // hexadecimal numbers start with 0x + storeCharacter(s, i + 1, '0'); + + i = i + 2; + } } - *(s+i) = 0; // null terminated string + storeCharacter(s, i, 0); // null terminated string - reverseString(s); + stringReverse(s); return s; } -void print(int *s) { - while (*s != 0) { - putchar(*s); - s = s + 1; +void putCharacter(int character) { + if (outputFD == 1) + putchar(character); + else { + *character_buffer = character; + + if (write(outputFD, character_buffer, 1) != 1) { + outputFD = 1; + + print(selfieName); + print((int*) ": could not write character to output file "); + print(outputName); + println(); + + exit(-1); + } } } -void assignString(int *s, int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { +void print(int *s) { + int i; - *(s+0) = c0; *(s+1) = c1; *(s+2) = c2; *(s+3) = c3; *(s+4) = c4; - *(s+5) = c5; *(s+6) = c6; *(s+7) = c7; *(s+8) = c8; *(s+9) = c9; - *(s+10) = c10; *(s+11) = c11; *(s+12) = c12; *(s+13) = c13; *(s+14) = c14; - *(s+15) = c15; *(s+16) = c16; *(s+17) = c17; *(s+18) = c18; *(s+19) = c19; - *(s+20) = 0; -} + i = 0; -int* createString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { - int* s; + while (loadCharacter(s, i) != 0) { + putCharacter(loadCharacter(s, i)); - s = (int*)malloc(21*4); - assignString(s, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, - c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); - return s; + i = i + 1; + } +} + +void println() { + putCharacter(CHAR_LF); } -void printString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { +void printCharacter(int character) { + putCharacter(CHAR_SINGLEQUOTE); - assignString(string_buffer, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, - c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + if (character == CHAR_EOF) + print((int*) "end of file"); + else if (character == CHAR_TAB) + print((int*) "tabulator"); + else if (character == CHAR_LF) + print((int*) "line feed"); + else if (character == CHAR_CR) + print((int*) "carriage return"); + else + putCharacter(character); - print(string_buffer); + putCharacter(CHAR_SINGLEQUOTE); } -void memset(int *a, int size, int v) { - while (size > 0) { - size = size - 1; - *(a+size) = v; - } +void printString(int *s) { + putCharacter(CHAR_DOUBLEQUOTE); + + print(s); + + putCharacter(CHAR_DOUBLEQUOTE); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -1165,20 +1290,94 @@ void memset(int *a, int size, int v) { // ---------------------------- SCANNER ---------------------------- // ----------------------------------------------------------------- -int findNextCharacter() { - int inComment; +void printSymbol(int symbol) { + putCharacter(CHAR_DOUBLEQUOTE); - inComment = 0; + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); + + putCharacter(CHAR_DOUBLEQUOTE); +} + +void printLineNumber(int* message) { + print(selfieName); + print((int*) ": "); + print(message); + print((int*) " in "); + print(sourceName); + print((int*) " in line "); + print(itoa(lineNumber, string_buffer, 10, 0, 0)); + print((int*) ": "); +} + +void syntaxErrorMessage(int *message) { + printLineNumber((int*) "error"); + + print(message); + + println(); +} + +void syntaxErrorCharacter(int expected) { + printLineNumber((int*) "error"); + + printCharacter(expected); + print((int*) " expected but "); + + printCharacter(character); + print((int*) " found"); + + println(); +} + +void getCharacter() { + int numberOfReadBytes; + + numberOfReadBytes = read(sourceFD, character_buffer, 1); + + if (numberOfReadBytes == 1) + character = *character_buffer; + else if (numberOfReadBytes == 0) + character = CHAR_EOF; + else { + print(selfieName); + print((int*) ": could not read character from input file "); + print(sourceName); + println(); + + exit(-1); + } +} + +int isCharacterWhitespace() { + if (character == CHAR_SPACE) + return 1; + else if (character == CHAR_TAB) + return 1; + else if (character == CHAR_LF) + return 1; + else if (character == CHAR_CR) + return 1; + else + return 0; +} + +int findNextCharacter() { + int inComment; + + inComment = 0; while (1) { if (inComment) { - character = getchar(); + getCharacter(); if (character == CHAR_LF) inComment = 0; else if (character == CHAR_CR) inComment = 0; - else if (character == SYM_EOF) + else if (character == CHAR_EOF) return character; } else if (isCharacterWhitespace()) { @@ -1187,15 +1386,17 @@ int findNextCharacter() { else if (character == CHAR_CR) lineNumber = lineNumber + 1; - character = getchar(); + getCharacter(); + + } else if (character == CHAR_HASH) { + getCharacter(); - } else if (character == '#') { - character = getchar(); inComment = 1; - } else if (character == '/') { - character = getchar(); - if (character == '/') + } else if (character == CHAR_SLASH) { + getCharacter(); + + if (character == CHAR_SLASH) inComment = 1; else { symbol = SYM_DIV; @@ -1207,26 +1408,17 @@ int findNextCharacter() { } } -int isCharacterWhitespace() { - if (character == ' ') - return 1; - else if (character == CHAR_TAB) - return 1; - else if (character == CHAR_LF) - return 1; - else if (character == CHAR_CR) - return 1; - else - return 0; -} - -int isCharacterLetterOrDigitOrUnderscore() { - if (isCharacterLetter()) - return 1; - else if(isCharacterDigit()) - return 1; - else if(character == '_') - return 1; +int isCharacterLetter() { + if (character >= 'a') + if (character <= 'z') + return 1; + else + return 0; + else if (character >= 'A') + if (character <= 'Z') + return 1; + else + return 0; else return 0; } @@ -1241,23 +1433,28 @@ int isCharacterDigit() { return 0; } -int isCharacterLetter() { - if (character >= 'a') - if (character <= 'z') - return 1; - else - return 0; - else if (character >= 'A') - if (character <= 'Z') - return 1; - else - return 0; +int isCharacterLetterOrDigitOrUnderscore() { + if (isCharacterLetter()) + return 1; + else if (isCharacterDigit()) + return 1; + else if (character == CHAR_UNDERSCORE) + return 1; else return 0; } -int identifierStringMatch(int stringIndex) { - return stringCompare(identifier, (int*)(*(stringArray + stringIndex))); +int isNotDoubleQuoteOrEOF() { + if (character == CHAR_DOUBLEQUOTE) + return 0; + else if (character == CHAR_EOF) + return 0; + else + return 1; +} + +int identifierStringMatch(int keyword) { + return stringCompare(identifier, (int*) *(SYMBOLS + keyword)); } int identifierOrKeyword() { @@ -1282,216 +1479,260 @@ int getSymbol() { symbol = SYM_EOF; - if (findNextCharacter() == SYM_EOF) + if (findNextCharacter() == CHAR_EOF) return SYM_EOF; else if (symbol == SYM_DIV) // check here because / was recognized instead of // return SYM_DIV; if (isCharacterLetter()) { - identifier = (int*)malloc((maxIdentifierLength+1) * 4); + identifier = malloc(maxIdentifierLength + 1); + i = 0; while (isCharacterLetterOrDigitOrUnderscore()) { - if (i+1 > maxIdentifierLength) { - syntaxError(ERR_MAXIDENTIFIERLENGTH); // identifier too long + if (i >= maxIdentifierLength) { + syntaxErrorMessage((int*) "identifier too long"); exit(-1); } - *(identifier+i) = character; + + storeCharacter(identifier, i, character); + i = i + 1; - character = getchar(); + + getCharacter(); } - *(identifier+i) = 0; // null terminated string + storeCharacter(identifier, i, 0); // null terminated string + symbol = identifierOrKeyword(); } else if (isCharacterDigit()) { - integer = (int*)malloc((maxIntegerLength+1) * 4); + integer = malloc(maxIntegerLength + 1); + i = 0; while (isCharacterDigit()) { - if (i+1 > maxIntegerLength) { - syntaxError(ERR_WRAPAROUND); // integer too long + if (i >= maxIntegerLength) { + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } - *(integer+i) = character; + + storeCharacter(integer, i, character); + i = i + 1; - character = getchar(); + + getCharacter(); } - *(integer+i) = 0; // null terminated string - ivalue = atoi(integer); + storeCharacter(integer, i, 0); // null terminated string - if (ivalue < 0) { - if (ivalue == INT_MIN) { - if (mayBeINTMINConstant == 0) { - syntaxError(ERR_WRAPAROUND); + constant = atoi(integer); + + if (constant < 0) { + if (constant == INT_MIN) { + if (mayBeINTMINConstant) + isINTMINConstant = 1; + else { + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } } else { - syntaxError(ERR_WRAPAROUND); + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } } symbol = SYM_INTEGER; - } else if (character == ';') { - character = getchar(); + } else if (character == CHAR_SINGLEQUOTE) { + getCharacter(); + + constant = 0; + + if (character == CHAR_EOF) { + syntaxErrorMessage((int*) "reached end of file looking for a character constant"); + + exit(-1); + } else + constant = character; + + getCharacter(); + + if (character == CHAR_SINGLEQUOTE) + getCharacter(); + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + exit(-1); + } else + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + symbol = SYM_CHARACTER; + + } else if (character == CHAR_DOUBLEQUOTE) { + getCharacter(); + + string = malloc(maxStringLength + 1); + + i = 0; + + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } + + storeCharacter(string, i, character); + + i = i + 1; + + getCharacter(); + } + + if (character == CHAR_DOUBLEQUOTE) + getCharacter(); + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); + + exit(-1); + } + + storeCharacter(string, i, 0); // null terminated string + + symbol = SYM_STRING; + + } else if (character == CHAR_SEMICOLON) { + getCharacter(); + symbol = SYM_SEMICOLON; - } else if (character == '+') { - character = getchar(); + } else if (character == CHAR_PLUS) { + getCharacter(); + symbol = SYM_PLUS; - } else if (character == '-') { - character = getchar(); + } else if (character == CHAR_DASH) { + getCharacter(); + symbol = SYM_MINUS; - } else if (character == '*') { - character = getchar(); + } else if (character == CHAR_ASTERISK) { + getCharacter(); + symbol = SYM_ASTERISK; - } else if (character == '=') { - character = getchar(); - if (character == '=') { - character = getchar(); - symbol = SYM_EQUAL; + } else if (character == CHAR_EQUAL) { + getCharacter(); + + if (character == CHAR_EQUAL) { + getCharacter(); + + symbol = SYM_EQUALITY; } else symbol = SYM_ASSIGN; - } else if (character == '(') { - character = getchar(); + } else if (character == CHAR_LPARENTHESIS) { + getCharacter(); + symbol = SYM_LPARENTHESIS; - } else if (character == ')') { - character = getchar(); + } else if (character == CHAR_RPARENTHESIS) { + getCharacter(); + symbol = SYM_RPARENTHESIS; - } else if (character == '{') { - character = getchar(); + } else if (character == CHAR_LBRACE) { + getCharacter(); + symbol = SYM_LBRACE; - } else if (character == '}') { - character = getchar(); + } else if (character == CHAR_RBRACE) { + getCharacter(); + symbol = SYM_RBRACE; - } else if (character == ',') { - character = getchar(); + } else if (character == CHAR_COMMA) { + getCharacter(); + symbol = SYM_COMMA; - } else if (character == '<') { - character = getchar(); - if (character == '=') { - character = getchar(); + } else if (character == CHAR_LT) { + getCharacter(); + + if (character == CHAR_EQUAL) { + getCharacter(); + symbol = SYM_LEQ; } else symbol = SYM_LT; - } else if (character == '>') { - character = getchar(); - if (character == '=') { - character = getchar(); - symbol = SYM_GEQ; - } else - symbol = SYM_GT; - - } else if (character == '!') { - character = getchar(); - if (character == '=') { - character = getchar(); - symbol = SYM_NOTEQ; - } else - syntaxError(ERR_UNKNOWN); + } else if (character == CHAR_GT) { + getCharacter(); - } else if (character == '%') { - character = getchar(); - symbol = SYM_MOD; + if (character == CHAR_EQUAL) { + getCharacter(); - } else if (character == 39) { // ' - character = getchar(); - ivalue = character; // any ascii character - character = getchar(); - if (character == 39) { // ' - character = getchar(); - symbol = SYM_CHARACTER; + symbol = SYM_GEQ; } else - syntaxError(ERR_UNKNOWN); - } else { - syntaxError(ERR_UNKNOWN); - exit(-1); // unknown character - } - - return symbol; -} - -void syntaxWarn(int errCode) { - int *numberBuffer; - - numberBuffer = (int*)malloc(4*10); - - print(warning); - - print((int*)(*(stringArray+errCode))); - - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); - - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + symbol = SYM_GT; - print(errNewline); -} + } else if (character == CHAR_EXCLAMATION) { + getCharacter(); -void syntaxError(int errCode) { - int *numberBuffer; + if (character == CHAR_EQUAL) + getCharacter(); + else + syntaxErrorCharacter(CHAR_EQUAL); - numberBuffer = (int*)malloc(4*10); + symbol = SYM_NOTEQ; - print(error); + } else if (character == CHAR_PERCENTAGE) { + getCharacter(); - print((int*)(*(stringArray+errCode))); + symbol = SYM_MOD; - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); + } else { + printLineNumber((int*) "error"); + print((int*) "found unknown character "); + printCharacter(character); - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + println(); - print(errNewline); + exit(-1); + } - getSymbol(); + return symbol; } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int class, int type) { - int* newEntry; +void createSymbolTableEntry(int whichTable, int *string, int data, int class, int type, int value) { + int *newEntry; - // symbolTable: - // +----+------------+ - // | 0 | ptr to next| - // | 1 | identifier | - // | 2 | data | VARIABLE: offset/FUNCTION: code address - // | 3 | class | - // | 4 | type | - // | 5 | register | - // +----+------------+ + // symbol table entry: + // +----+----------+ + // | 0 | next | pointer to next entry + // | 1 | string | identifier string, string constant + // | 2 | data | VARIABLE: offset, FUNCTION: address, STRING: offset + // | 3 | class | VARIABLE, FUNCTION, STRING + // | 4 | type | INT_T, INTSTAR_T, VOID_T + // | 5 | value | VARIABLE: constant value + // | 6 | register | REG_GP, REG_FP + // +----+----------+ - newEntry = (int*)malloc(6 * 4); + newEntry = malloc(7 * 4); - // store pointer to identifier - // cast only works if size of int and int* is equivalent - setIdentifier(newEntry, ident); + setString(newEntry, string); setData(newEntry, data); setClass(newEntry, class); setType(newEntry, type); + setValue(newEntry, value); // create entry at head of symbol table - // cast only works if size of int and int* is equivalent - if (which_symbol_table == GLOBAL_TABLE) { + if (whichTable == GLOBAL_TABLE) { setRegister(newEntry, REG_GP); setNext(newEntry, global_symbol_table); global_symbol_table = newEntry; @@ -1502,24 +1743,26 @@ void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int cl } } -int* getSymbolTableEntry(int *ident, int *symbol_table) { - while ((int)symbol_table != 0) { - if (stringCompare(ident, getIdentifier(symbol_table))) - return symbol_table; - else - // keep looking - // cast only works if size of int and int* is equivalent - symbol_table = getNext(symbol_table); +int* getSymbolTableEntry(int *string, int class, int *symbol_table) { + while ((int) symbol_table != 0) { + if (stringCompare(string, getString(symbol_table))) + if (class == getClass(symbol_table)) + return symbol_table; + + // keep looking + symbol_table = getNext(symbol_table); } - return 0; + return (int*) 0; } int* getNext(int *entry) { + // cast only works if size of int and int* is equivalent return (int*) *entry; } -int* getIdentifier(int *entry) { +int* getString(int *entry) { + // cast only works if size of int and int* is equivalent return (int*) *(entry + 1); } @@ -1535,15 +1778,21 @@ int getType(int *entry) { return *(entry + 4); } -int getRegister(int *entry) { +int getValue(int *entry) { return *(entry + 5); } +int getRegister(int *entry) { + return *(entry + 6); +} + void setNext(int *entry, int *next) { + // cast only works if size of int and int* is equivalent *entry = (int) next; } -void setIdentifier(int *entry, int *identifier) { +void setString(int *entry, int *identifier) { + // cast only works if size of int and int* is equivalent *(entry + 1) = (int) identifier; } @@ -1559,8 +1808,12 @@ void setType(int *entry, int type) { *(entry + 4) = type; } +void setValue(int *entry, int value) { + *(entry + 5) = value; +} + void setRegister(int *entry, int reg) { - *(entry + 5) = reg; + *(entry + 6) = reg; } // ----------------------------------------------------------------- @@ -1568,23 +1821,14 @@ void setRegister(int *entry, int reg) { // ----------------------------------------------------------------- int isNotRbraceOrEOF() { - if (symbol == SYM_EOF) + if (symbol == SYM_RBRACE) return 0; - else if(symbol == SYM_RBRACE) + else if(symbol == SYM_EOF) return 0; else return 1; } -int isVariableOrProcedure() { - if (symbol == SYM_INT) - return 1; - else if (symbol == SYM_VOID) - return 1; - else - return 0; -} - int isExpression() { if (symbol == SYM_MINUS) return 1; @@ -1596,16 +1840,18 @@ int isExpression() { return 1; else if (symbol == SYM_ASTERISK) return 1; + else if (symbol == SYM_STRING) + return 1; else if (symbol == SYM_CHARACTER) return 1; else return 0; } -int isPlusOrMinus() { - if (symbol == SYM_MINUS) +int isConstant() { + if (symbol == SYM_INTEGER) return 1; - else if (symbol == SYM_PLUS) + else if (symbol == SYM_CHARACTER) return 1; else return 0; @@ -1622,16 +1868,44 @@ int isStarOrDivOrModulo() { return 0; } -int waitForStatement() { - if (symbol == SYM_ASTERISK) +int isPlusOrMinus() { + if (symbol == SYM_MINUS) + return 1; + else if (symbol == SYM_PLUS) + return 1; + else + return 0; +} + +int isComparison() { + if (symbol == SYM_EQUALITY) + return 1; + else if (symbol == SYM_NOTEQ) + return 1; + else if (symbol == SYM_LT) + return 1; + else if (symbol == SYM_GT) + return 1; + else if (symbol == SYM_LEQ) + return 1; + else if (symbol == SYM_GEQ) + return 1; + else + return 0; +} + +int lookForFactor() { + if (symbol == SYM_LPARENTHESIS) + return 0; + else if (symbol == SYM_ASTERISK) return 0; else if (symbol == SYM_IDENTIFIER) return 0; - else if (symbol == SYM_WHILE) + else if (symbol == SYM_INTEGER) return 0; - else if (symbol == SYM_IF) + else if (symbol == SYM_CHARACTER) return 0; - else if (symbol == SYM_RETURN) + else if (symbol == SYM_STRING) return 0; else if (symbol == SYM_EOF) return 0; @@ -1639,8 +1913,16 @@ int waitForStatement() { return 1; } -int waitForVariable() { - if (symbol == SYM_INT) +int lookForStatement() { + if (symbol == SYM_ASTERISK) + return 0; + else if (symbol == SYM_IDENTIFIER) + return 0; + else if (symbol == SYM_WHILE) + return 0; + else if (symbol == SYM_IF) + return 0; + else if (symbol == SYM_RETURN) return 0; else if (symbol == SYM_EOF) return 0; @@ -1648,16 +1930,10 @@ int waitForVariable() { return 1; } -int waitForFactor() { - if (symbol == SYM_LPARENTHESIS) - return 0; - else if (symbol == SYM_ASTERISK) - return 0; - else if (symbol == SYM_IDENTIFIER) - return 0; - else if (symbol == SYM_INTEGER) +int lookForType() { + if (symbol == SYM_INT) return 0; - else if (symbol == SYM_CHARACTER) + else if (symbol == SYM_VOID) return 0; else if (symbol == SYM_EOF) return 0; @@ -1665,35 +1941,144 @@ int waitForFactor() { return 1; } -void save_registers() { - while (allocatedRegisters > 0) { - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); +void talloc() { + // we use registers REG_T0-REG_T9 and REG_S0-REG_S7 for temporaries + if (allocatedTemporaries < REG_T9 - REG_A3) + allocatedTemporaries = allocatedTemporaries + 1; + else { + syntaxErrorMessage((int*) "out of registers"); - allocatedRegisters = allocatedRegisters - 1; + exit(-1); } } -void restore_registers(int numberOfRegisters) { +int currentTemporary() { + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); - while (allocatedRegisters < numberOfRegisters) { - allocatedRegisters = allocatedRegisters + 1; - - emitIFormat(OP_LW, REG_SP, allocatedRegisters, 0); - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + exit(-1); } } -int* getVariable(int *variable) { - int* entry; +int previousTemporary() { + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); - entry = getSymbolTableEntry(variable, local_symbol_table); + exit(-1); + } +} - if ((int)entry == 0) { - entry = getSymbolTableEntry(variable, global_symbol_table); +int nextTemporary() { + if (allocatedTemporaries < REG_T9 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); - if ((int)entry == 0) - syntaxError(ERR_UNDECLARED_VARIABLE); + exit(-1); + } +} + +void tfree(int numberOfTemporaries) { + allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; + + if (allocatedTemporaries < 0) { + syntaxErrorMessage((int*) "illegal register deallocation"); + + exit(-1); + } +} + +void save_temporaries() { + while (allocatedTemporaries > 0) { + // push temporary onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } +} + +void restore_temporaries(int numberOfTemporaries) { + while (allocatedTemporaries < numberOfTemporaries) { + talloc(); + + // restore temporary from stack + emitIFormat(OP_LW, REG_SP, currentTemporary(), 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + } +} + +void syntaxErrorSymbol(int expected) { + printLineNumber((int*) "error"); + + printSymbol(expected); + print((int*) " expected but "); + + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +void syntaxErrorUnexpected() { + printLineNumber((int*) "error"); + + print((int*) "unexpected symbol "); + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +int* putType(int type) { + if (type == INT_T) + return (int*) "int"; + else if (type == INTSTAR_T) + return (int*) "int*"; + else if (type == VOID_T) + return (int*) "void"; + else + return (int*) "unknown"; +} + +void typeWarning(int expected, int found) { + printLineNumber((int*) "warning"); + + print((int*) "type mismatch, "); + + print(putType(expected)); + + print((int*) " expected but "); + + print(putType(found)); + + print((int*) " found"); + + println(); +} + +int* getVariable(int *variable) { + int *entry; + + entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); + + if (entry == (int*) 0) { + entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); + + if (entry == (int*) 0) { + printLineNumber((int*) "error"); + + print(variable); + + print((int*) " undeclared"); + println(); + + exit(-1); + } } return entry; @@ -1704,68 +2089,81 @@ int load_variable(int *variable) { entry = getVariable(variable); - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_LW, getRegister(entry), allocatedRegisters, getData(entry)); + emitIFormat(OP_LW, getRegister(entry), currentTemporary(), getData(entry)); return getType(entry); } void load_integer() { - // assert: ivalue >= 0 or ivalue == INT_MIN - - allocatedRegisters = allocatedRegisters + 1; + // assert: constant >= 0 or constant == INT_MIN - if (ivalue >= 0) { - mayBeINTMINConstant = 0; + talloc(); - if (ivalue < twoToThePowerOf(15)) + if (constant >= 0) { + if (constant < twoToThePowerOf(15)) // ADDIU can only load numbers < 2^15 without sign extension - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, ivalue); - else if (ivalue < twoToThePowerOf(28)) { + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); + else if (constant < twoToThePowerOf(28)) { // load 14 msbs of a 28-bit number first - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, rightShift(ivalue, 14)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 14)); // shift left by 14 bits emitLeftShiftBy(14); // and finally add 14 lsbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 18), 18)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 18), 18)); } else { // load 14 msbs of a 31-bit number first - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, rightShift(ivalue, 17)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 17)); emitLeftShiftBy(14); // then add the next 14 msbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 15), 18)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 15), 18)); emitLeftShiftBy(3); // and finally add the remaining 3 lsbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 29), 29)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 29), 29)); } } else { // load largest positive 16-bit number with a single bit set: 2^14 - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, twoToThePowerOf(14)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), twoToThePowerOf(14)); // and then multiply 2^14 by 2^14*2^3 to get to 2^31 == INT_MIN emitLeftShiftBy(14); emitLeftShiftBy(3); } +} - getSymbol(); +void load_string() { + int l; + + l = stringLength(string) + 1; + + allocatedMemory = allocatedMemory + l; + + if (l % 4 != 0) + allocatedMemory = allocatedMemory + 4 - l % 4; + + createSymbolTableEntry(GLOBAL_TABLE, string, -allocatedMemory, STRING, INTSTAR_T, 0); + + talloc(); + + emitIFormat(OP_ADDIU, REG_GP, currentTemporary(), -allocatedMemory); } int help_call_codegen(int *entry, int *procedure) { int type; - type = UNKNOWN; - - if ((int)entry == 0) { + if (entry == (int*) 0) { // CASE 1: function call, no definition, no declaration. - createSymbolTableEntry(GLOBAL_TABLE, procedure, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, procedure, binaryLength, FUNCTION, INT_T, 0); + emitJFormat(OP_JAL, 0); + type = INT_T; //assume default return type 'int' } else { @@ -1773,156 +2171,174 @@ int help_call_codegen(int *entry, int *procedure) { if (getData(entry) == 0) { // CASE 2: function call, no definition, but declared. - setData(entry, codeLength); + setData(entry, binaryLength); + emitJFormat(OP_JAL, 0); - } else if (getOpcode(*(memory + getData(entry))) == OP_JAL) { + } else if (getOpcode(loadBinary(getData(entry))) == OP_JAL) { // CASE 3: function call, no declaration - emitJFormat(OP_JAL, getData(entry)); - setData(entry, codeLength - 2); + emitJFormat(OP_JAL, getData(entry) / 4); + + setData(entry, binaryLength - 8); } else // CASE 4: function defined, use the address - emitJFormat(OP_JAL, getData(entry)); + emitJFormat(OP_JAL, getData(entry) / 4); } return type; } void help_procedure_prologue(int localVariables) { - // save return address + // allocate space for return address emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, REG_LINK, 0); - // save caller's frame + // save return address + emitIFormat(OP_SW, REG_SP, REG_RA, 0); + + // allocate space for caller's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + + // save caller's frame pointer emitIFormat(OP_SW, REG_SP, REG_FP, 0); - // allocate callee's frame + // set callee's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_FP, 0); - // allocate callee's local variables - if (localVariables != 0) { - emitIFormat(OP_ADDIU, REG_SP, REG_SP, localVariables * (-4)); - } + // allocate space for callee's local variables + if (localVariables != 0) + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4 * localVariables); } -void help_procedure_epilogue(int parameters, int functionStart, int functionType) { - // deallocate callee's frame and local variables +void help_procedure_epilogue(int parameters) { + // deallocate space for callee's frame pointer and local variables emitIFormat(OP_ADDIU, REG_FP, REG_SP, 0); - // restore caller's frame + // restore caller's frame pointer emitIFormat(OP_LW, REG_SP, REG_FP, 0); + + // deallocate space for caller's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // restore return address and deallocate parameters - emitIFormat(OP_LW, REG_SP, REG_LINK, 0); - emitIFormat(OP_ADDIU, REG_SP, REG_SP, ((parameters+1)*4)); + // restore return address + emitIFormat(OP_LW, REG_SP, REG_RA, 0); + + // deallocate space for return address and parameters + emitIFormat(OP_ADDIU, REG_SP, REG_SP, (parameters + 1) * 4); // return - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } int gr_call(int *procedure) { int *entry; - int numberOfRegisters; + int numberOfTemporaries; int type; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries - entry = getSymbolTableEntry(procedure, global_symbol_table); + entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); - numberOfRegisters = allocatedRegisters; + numberOfTemporaries = allocatedTemporaries; - save_registers(); + save_temporaries(); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 if (isExpression()) { gr_expression(); - // TODO: check if types/number of params is correct. - // PSH first parameter onto stack + // TODO: check if types/number of parameters is correct + // push first parameter onto stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); while (symbol == SYM_COMMA) { getSymbol(); + gr_expression(); - // PSH more parameters onto stack + // push more parameters onto stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); } + if (symbol == SYM_RPARENTHESIS) { getSymbol(); + type = help_call_codegen(entry, procedure); } else { - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); + type = INT_T; } } else if (symbol == SYM_RPARENTHESIS) { getSymbol(); + type = help_call_codegen(entry, procedure); } else { - syntaxWarn(ERR_EXPRESSION); + syntaxErrorSymbol(SYM_RPARENTHESIS); + type = INT_T; } - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 - restore_registers(numberOfRegisters); + restore_temporaries(numberOfTemporaries); - // assert: allocatedRegisters == n + // assert: allocatedTemporaries == n return type; } int gr_factor() { + int hasCast; int cast; int type; + int *variableOrProcedureName; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries + + hasCast = 0; - cast = 0; // turn off cast by default + type = INT_T; - while (waitForFactor()) - syntaxError(ERR_IDENT_OR_CONST_OR_EXP); + while (lookForFactor()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } // optional cast: [ cast ] if (symbol == SYM_LPARENTHESIS) { getSymbol(); - mayBeINTMINConstant = 0; - - // (int) + // cast: "(" "int" [ "*" ] ")" if (symbol == SYM_INT) { - getSymbol(); - - cast = INT_T; - - // (int*) - if (symbol == SYM_ASTERISK) { - getSymbol(); + hasCast = 1; - cast = INTSTAR_T; - } + cast = gr_type(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); - // Not a cast: "(" expression ")" + // not a cast: "(" expression ")" } else { type = gr_expression(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return type; } @@ -1932,15 +2348,13 @@ int gr_factor() { if (symbol == SYM_ASTERISK) { getSymbol(); - mayBeINTMINConstant = 0; - // ["*"] identifier if (symbol == SYM_IDENTIFIER) { type = load_variable(identifier); getSymbol(); - // * "(" simpleExpression ")" + // * "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { getSymbol(); @@ -1949,19 +2363,17 @@ int gr_factor() { if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(ERR_IDENTIFIER_OR_LPARENTHESIS); + syntaxErrorUnexpected(); - // dereference - emitIFormat(OP_LW, allocatedRegisters, allocatedRegisters, 0); + if (type != INTSTAR_T) + typeWarning(INTSTAR_T, type); - if (cast == 0) { - if (type != INTSTAR_T) - syntaxWarn(ERR_ILLEGAL_DEREF); + // dereference + emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); - type = INT_T; - } + type = INT_T; // identifier? } else if (symbol == SYM_IDENTIFIER) { @@ -1969,111 +2381,107 @@ int gr_factor() { getSymbol(); - mayBeINTMINConstant = 0; - if (symbol == SYM_LPARENTHESIS) { getSymbol(); - // function call: identifier "(" ... ")" ... + // function call: identifier "(" ... ")" type = gr_call(variableOrProcedureName); - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_ADDIU, REG_RR, allocatedRegisters, 0); + emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); } else - // else.. it is just an 'identifier' + // variable access: identifier type = load_variable(variableOrProcedureName); // integer? } else if (symbol == SYM_INTEGER) { load_integer(); + + getSymbol(); + type = INT_T; // character? } else if (symbol == SYM_CHARACTER) { - mayBeINTMINConstant = 0; - - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, ivalue); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); getSymbol(); + type = INT_T; + // string? + } else if (symbol == SYM_STRING) { + load_string(); + + getSymbol(); + + type = INTSTAR_T; + // "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { - mayBeINTMINConstant = 0; getSymbol(); + type = gr_expression(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); - } + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 - if (cast == 0) - return type; - else + if (hasCast) return cast; + else + return type; } int gr_term() { int ltype; + int operatorSymbol; int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries ltype = gr_factor(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 // * / or % ? while (isStarOrDivOrModulo()) { - if (symbol == SYM_ASTERISK) { - // assert: allocatedRegisters == n + 2 - getSymbol(); - rtype = gr_factor(); - - - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_MULTU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFLO); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + operatorSymbol = symbol; - } else if (symbol == SYM_DIV) { - getSymbol(); - rtype = gr_factor(); + getSymbol(); + rtype = gr_factor(); - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFLO); + // assert: allocatedTemporaries == n + 2 - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + if (ltype != rtype) + typeWarning(ltype, rtype); - } else if (symbol == SYM_MOD) { - getSymbol(); - rtype = gr_factor(); + if (operatorSymbol == SYM_ASTERISK) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFHI); + } else if (operatorSymbol == SYM_DIV) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + } else if (operatorSymbol == SYM_MOD) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFHI); } + + tfree(1); } - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return ltype; } @@ -2081,192 +2489,164 @@ int gr_term() { int gr_simpleExpression() { int sign; int ltype; - int rtype; int operatorSymbol; + int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries // optional: - if (symbol == SYM_MINUS) { sign = 1; + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } } else sign = 0; ltype = gr_term(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 if (sign == 1) { - if (mayBeINTMINConstant) - // avoids 0-INT_MIN overflow when bootstrapping - // even though 0-INT_MIN == INT_MIN - mayBeINTMINConstant = 0; - else - emitRFormat(OP_SPECIAL, REG_ZR, allocatedRegisters, allocatedRegisters, FCT_SUBU); + if (ltype != INT_T) { + typeWarning(INT_T, ltype); + + ltype = INT_T; + } + + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), currentTemporary(), FCT_SUBU); } // + or -? while (isPlusOrMinus()) { operatorSymbol = symbol; + getSymbol(); rtype = gr_term(); - // assert: allocatedRegisters == n + 2 + // assert: allocatedTemporaries == n + 2 if (operatorSymbol == SYM_PLUS) { - if (ltype == rtype) { // base case, normal arithmetic - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else if (ltype == INTSTAR_T) { - if (rtype == INT_T) { - // pointer arithmetic requires factor of 2^2 - emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else { - syntaxError(ERR_TYPE_MISMATCH); - } - } else if (rtype == INTSTAR_T) { - if (ltype == INT_T) { - // pointer arithmetic requires factor of 2^2 + if (ltype == INTSTAR_T) { + if (rtype == INT_T) + // pointer arithmetic: factor of 2^2 of integer operand emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else - syntaxError(ERR_TYPE_MISMATCH); - } - } else { - if (ltype == rtype) - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); - else - syntaxError(ERR_TYPE_MISMATCH); + } else if (rtype == INTSTAR_T) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_ADDU); + + } else if (operatorSymbol == SYM_MINUS) { + if (ltype != rtype) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); } - allocatedRegisters = allocatedRegisters - 1; + tfree(1); } - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return ltype; } int gr_expression() { int ltype; + int operatorSymbol; int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries - ltype = gr_simpleExpression(); // type of left element + ltype = gr_simpleExpression(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 //optional: ==, !=, <, >, <=, >= simpleExpression - if (symbol == SYM_EQUAL) { + if (isComparison()) { + operatorSymbol = symbol; + getSymbol(); - rtype = gr_simpleExpression(); - // assert: allocatedRegisters == n + 2 + rtype = gr_simpleExpression(); - if (ltype == rtype) { - // subtract, if result = 0 then 1, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); + // assert: allocatedTemporaries == n + 2 - allocatedRegisters = allocatedRegisters - 1; + if (ltype != rtype) + typeWarning(ltype, rtype); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); - } else - syntaxError(ERR_TYPE_MISMATCH); + if (operatorSymbol == SYM_EQUALITY) { + // subtract, if result = 0 then 1, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); - } else if (symbol == SYM_NOTEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_NOTEQ) { // subtract, if result = 0 then 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); - - allocatedRegisters = allocatedRegisters - 1; - - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); - } else - syntaxError(ERR_TYPE_MISMATCH); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); - } else if (symbol == SYM_LT) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_LT) { // set to 1 if a < b, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SLT); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); - } else if (symbol == SYM_GT) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 - - if (ltype == rtype) { + } else if (operatorSymbol == SYM_GT) { // set to 1 if b < a, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters-1, allocatedRegisters-1, FCT_SLT); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); - - } else if (symbol == SYM_LEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); - // assert: allocatedRegisters == n + 2 + tfree(1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_LEQ) { // if b < a set 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters-1, allocatedRegisters-1, FCT_SLT); + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); - allocatedRegisters = allocatedRegisters - 1; + tfree(1); - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - } else - syntaxError(ERR_TYPE_MISMATCH); - - } else if (symbol == SYM_GEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); - // assert: allocatedRegisters == n + 2 - - if (ltype == rtype) { + } else if (operatorSymbol == SYM_GEQ) { // if a < b set 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SLT); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); - allocatedRegisters = allocatedRegisters - 1; + tfree(1); - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - } else - syntaxError(ERR_TYPE_MISMATCH); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + } } - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return ltype; } @@ -2275,75 +2655,92 @@ void gr_while() { int brBackToWhile; int brForwardToEnd; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 + + brBackToWhile = binaryLength; - brBackToWhile = codeLength; + brForwardToEnd = 0; // while ( expression ) if (symbol == SYM_WHILE) { getSymbol(); + if (symbol == SYM_LPARENTHESIS) { getSymbol(); + gr_expression(); - //don't know where to branch, fixup later - brForwardToEnd = codeLength; - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + // do not know where to branch, fixup later + brForwardToEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); if (symbol == SYM_RPARENTHESIS) { getSymbol(); + // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); + while (isNotRbraceOrEOF()) gr_statement(); if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } } // only one statement without {} else gr_statement(); } else - syntaxError(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } else - syntaxError(SYM_WHILE); + syntaxErrorSymbol(SYM_WHILE); // unconditional branch to beginning of while - emitIFormat(OP_BEQ, 0, 0, brBackToWhile - codeLength - 1); + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, (brBackToWhile - binaryLength - 4) / 4); - // first instr after loop comes here, now we have - // our address for the conditional jump from above - fixup_relative(brForwardToEnd); + if (brForwardToEnd != 0) + // first instruction after loop comes here + // now we have our address for the conditional jump from above + fixup_relative(brForwardToEnd); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_if() { int brForwardToElseOrEnd; int brForwardToEnd; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 // if ( expression ) if (symbol == SYM_IF) { getSymbol(); + if (symbol == SYM_LPARENTHESIS) { getSymbol(); + gr_expression(); // if the "if" case is not true, we jump to "else" (if provided) - brForwardToElseOrEnd = codeLength; - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + brForwardToElseOrEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); if (symbol == SYM_RPARENTHESIS) { getSymbol(); + // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); @@ -2353,8 +2750,11 @@ void gr_if() { if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } } // only one statement without {} else @@ -2365,8 +2765,8 @@ void gr_if() { getSymbol(); // if the "if" case was true, we jump to the end - brForwardToEnd = codeLength; - emitIFormat(OP_BEQ, 0, 0, 0); + brForwardToEnd = binaryLength; + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 0); // if the "if" case was not true, we jump here fixup_relative(brForwardToElseOrEnd); @@ -2374,13 +2774,18 @@ void gr_if() { // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); + while (isNotRbraceOrEOF()) gr_statement(); if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + // only one statement without {} } else gr_statement(); @@ -2391,142 +2796,144 @@ void gr_if() { // if the "if" case was not true, we jump here fixup_relative(brForwardToElseOrEnd); } else - syntaxError(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } else - syntaxError(SYM_IF); + syntaxErrorSymbol(SYM_IF); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_return(int returnType) { - // assert: allocatedRegisters == 0 + int type; + + // assert: allocatedTemporaries == 0 - // keyword return if (symbol == SYM_RETURN) getSymbol(); else - syntaxError(SYM_RETURN); + syntaxErrorSymbol(SYM_RETURN); // optional: expression if (symbol != SYM_SEMICOLON) { - if (returnType != VOID_T) { - // TODO check for other wrong types, too - gr_expression(); + type = gr_expression(); - // save value of expression in return register - emitRFormat(OP_SPECIAL, REG_ZR, allocatedRegisters, REG_RR, FCT_ADDU); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_WRONG_RETURNTYPE); + if (returnType == VOID_T) + typeWarning(type, returnType); + else if (type != returnType) + typeWarning(returnType, type); + + // save value of expression in return register + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), REG_V0, FCT_ADDU); + + tfree(1); } // unconditional branch to procedure epilogue // maintain fixup chain for later fixup - emitJFormat(OP_J, returnBranches); + emitJFormat(OP_J, returnBranches / 4); // new head of fixup chain - returnBranches = codeLength-2; + // offest is 8 rather than 4 bytes because of delay slot NOP + returnBranches = binaryLength - 8; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_statement() { + int ltype; + int rtype; int *variableOrProcedureName; int *entry; - // assert: allocatedRegisters == 0; + // assert: allocatedTemporaries == 0; + + while (lookForStatement()) { + syntaxErrorUnexpected(); - while (waitForStatement()) - syntaxError(ERR_STATEMENT); + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } // ["*"] if (symbol == SYM_ASTERISK) { getSymbol(); - // ["*"] identifier + + // "*" identifier if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); + ltype = load_variable(identifier); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + getSymbol(); - // ["*"] identifier "=" + // "*" identifier "=" if (symbol == SYM_ASSIGN) { getSymbol(); - gr_expression(); + rtype = gr_expression(); + + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); - emitIFormat(OP_SW, allocatedRegisters-1, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 2; + tfree(2); } else - syntaxError(ERR_ASSIGN); + syntaxErrorSymbol(SYM_ASSIGN); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); - // "*" "(" identifier [ "+" integer ] + // "*" "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { getSymbol(); - if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); - - getSymbol(); - - if (symbol == SYM_PLUS) { - getSymbol(); - if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); - getSymbol(); - } else if (symbol == SYM_INTEGER) - load_integer(); - else - syntaxError(ERR_IDENTIFIER_OR_INTEGER); + ltype = gr_expression(); - // pointer arithmetic requires factor of 2^2 - emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); - allocatedRegisters = allocatedRegisters - 1; - } + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - if (symbol == SYM_RPARENTHESIS) { + // "*" "(" expression ")" "=" + if (symbol == SYM_ASSIGN) { getSymbol(); - // "*" "(" identifier ["+" integer] ")" =" - if (symbol == SYM_ASSIGN) { - getSymbol(); - - gr_expression(); + rtype = gr_expression(); - emitIFormat(OP_SW, allocatedRegisters-1, allocatedRegisters, 0); + if (rtype != INT_T) + typeWarning(INT_T, rtype); - allocatedRegisters = allocatedRegisters - 2; - } else - syntaxError(ERR_ASSIGN); + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxWarn(SYM_SEMICOLON); + tfree(2); } else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); } else - syntaxError(ERR_IDENTIFIER); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } - - // identifier = [ "*" ] identifier "=" expression ";" | - // identifier = call ";" - // call; + // identifier "=" expression | call else if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - // call ";" + // call if (symbol == SYM_LPARENTHESIS) { getSymbol(); @@ -2535,24 +2942,31 @@ void gr_statement() { if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); - // identifier = expression ";" + // identifier = expression } else if (symbol == SYM_ASSIGN) { entry = getVariable(variableOrProcedureName); + + ltype = getType(entry); + getSymbol(); - gr_expression(); - emitIFormat(OP_SW, getRegister(entry), allocatedRegisters, getData(entry)); + rtype = gr_expression(); + + if (ltype != rtype) + typeWarning(ltype, rtype); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, getRegister(entry), currentTemporary(), getData(entry)); + + tfree(1); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxError(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } else - syntaxError(ERR_IDENTIFIER_OR_ASSIGN); + syntaxErrorUnexpected(); } // while statement? else if (symbol == SYM_WHILE) { @@ -2564,28 +2978,23 @@ void gr_statement() { } // return statement? else if (symbol == SYM_RETURN) { - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); gr_return(getType(entry)); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } } -int gr_variable() { +int gr_type() { int type; - while (waitForVariable()) - syntaxError(ERR_TYPE); - - type = UNKNOWN; + type = INT_T; if (symbol == SYM_INT) { - type = INT_T; - getSymbol(); if (symbol == SYM_ASTERISK) { @@ -2593,117 +3002,204 @@ int gr_variable() { getSymbol(); } - - if (symbol != SYM_IDENTIFIER) - syntaxError(ERR_IDENTIFIER); } else - syntaxError(ERR_EOF); + syntaxErrorSymbol(SYM_INT); return type; } +void gr_variable(int offset) { + int type; + + type = gr_type(); + + if (symbol == SYM_IDENTIFIER) { + createSymbolTableEntry(LOCAL_TABLE, identifier, offset, VARIABLE, type, 0); + + getSymbol(); + } else { + syntaxErrorSymbol(SYM_IDENTIFIER); + + createSymbolTableEntry(LOCAL_TABLE, (int*) "missing variable name", offset, VARIABLE, type, 0); + } +} + +void gr_initialization(int *name, int offset, int type) { + int hasCast; + int cast; + int sign; + + initialValue = 0; + + hasCast = 0; + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else if (symbol == SYM_ASSIGN) { + getSymbol(); + + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + hasCast = 1; + + getSymbol(); + + cast = gr_type(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } + + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; + + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; + + if (isConstant()) { + initialValue = constant; + + getSymbol(); + + if (sign == 1) + initialValue = -initialValue; + } else + syntaxErrorUnexpected(); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorUnexpected(); + + if (hasCast) { + if (type != cast) + typeWarning(type, cast); + } else if (type != INT_T) + typeWarning(type, INT_T); + + createSymbolTableEntry(GLOBAL_TABLE, name, offset, VARIABLE, type, initialValue); +} + void gr_procedure(int *procedure, int returnType) { + int numberOfParameters; int parameters; - int oparam; - int offset; int localVariables; - int type; int functionStart; int *entry; - currentFuncName = procedure; + currentProcedureName = procedure; - oparam = 0; + numberOfParameters = 0; // ( variable , variable ) ; if (symbol == SYM_LPARENTHESIS) { getSymbol(); - parameters = 0; - if (symbol != SYM_RPARENTHESIS) { - type = gr_variable(); + gr_variable(0); - createSymbolTableEntry(LOCAL_TABLE, identifier, 0, VARIABLE, type); - - getSymbol(); - - parameters = 1; + numberOfParameters = 1; while (symbol == SYM_COMMA) { getSymbol(); - type = gr_variable(); - - createSymbolTableEntry(LOCAL_TABLE, identifier, 0, VARIABLE, type); + gr_variable(0); - getSymbol(); - - parameters = parameters + 1; + numberOfParameters = numberOfParameters + 1; } - oparam = parameters; entry = local_symbol_table; - offset = 8; // skip fp and link - while (parameters > 0) { - setData(entry, offset); - parameters = parameters - 1; - offset = offset + 4; + + parameters = 0; + + while (parameters < numberOfParameters) { + // 8 bytes offset to skip frame pointer and link + setData(entry, parameters * 4 + 8); + + parameters = parameters + 1; entry = getNext(entry); } if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else getSymbol(); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); if (symbol == SYM_SEMICOLON) { - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); - if ((int)entry == 0) - createSymbolTableEntry(GLOBAL_TABLE, currentFuncName, 0, FUNCTION, returnType); + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, 0, FUNCTION, returnType, 0); getSymbol(); // ( variable, variable ) { variable; variable; statement } } else if (symbol == SYM_LBRACE) { - functionStart = codeLength; + functionStart = binaryLength; + getSymbol(); - localVariables = 0; - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); - if ((int)entry == 0) { - createSymbolTableEntry(GLOBAL_TABLE, currentFuncName, codeLength, FUNCTION, returnType); - } else { - if (getData(entry) != 0) - if (getOpcode(*(memory + getData(entry))) == OP_JAL) + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, binaryLength, FUNCTION, returnType, 0); + else { + if (getData(entry) != 0) { + if (getOpcode(loadBinary(getData(entry))) == OP_JAL) fixlink_absolute(getData(entry), functionStart); + else { + printLineNumber((int*) "error"); + + print((int*) "multiple definitions of "); + + print(currentProcedureName); + + println(); + } + } - // TODO: overwrites previous definitions setData(entry, functionStart); - // TODO: check type of declaration and definition + if (getType(entry) != returnType) + typeWarning(getType(entry), returnType); + setType(entry, returnType); } - while (symbol == SYM_INT) { - type = gr_variable(); + localVariables = 0; + while (symbol == SYM_INT) { localVariables = localVariables + 1; - createSymbolTableEntry(LOCAL_TABLE, identifier, -4 * localVariables, VARIABLE, type); - - getSymbol(); + gr_variable(-4 * localVariables); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } help_procedure_prologue(localVariables); @@ -2716,84 +3212,81 @@ void gr_procedure(int *procedure, int returnType) { if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } - fixlink_absolute(returnBranches, codeLength); + fixlink_absolute(returnBranches, binaryLength); returnBranches = 0; - help_procedure_epilogue(oparam, functionStart, returnType); + help_procedure_epilogue(numberOfParameters); } else - syntaxError(ERR_LBRACE_OR_SEMICOLON); + syntaxErrorUnexpected(); - local_symbol_table = 0; + local_symbol_table = (int*) 0; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_cstar() { - int offset; int type; int *variableOrProcedureName; - type = UNKNOWN; + while (symbol != SYM_EOF) { + while (lookForType()) { + syntaxErrorUnexpected(); - while (isVariableOrProcedure()) { - // type identifier - if (symbol == SYM_INT) { - type = INT_T; + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } - getSymbol(); + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; - if (symbol == SYM_ASTERISK) { - type = INTSTAR_T; - getSymbol(); - } + getSymbol(); if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - // type identifier, this means it is a global variable - if (symbol == SYM_SEMICOLON) { - getSymbol(); - - offset = allocatedGlobalVariables * (-4); - - createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, offset, VARIABLE, type); - - allocatedGlobalVariables = allocatedGlobalVariables + 1; - } - // type identifier procedure - else - gr_procedure(variableOrProcedureName, type); + gr_procedure(variableOrProcedureName, type); } else - syntaxError(ERR_IDENTIFIER); - - // void identifier procedure - } else if (symbol == SYM_VOID) { - type = VOID_T; - getSymbol(); + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - gr_procedure(variableOrProcedureName, type); - } - } else - syntaxError(ERR_PROCEDURE_OR_VARIABLE); - } + // type identifier "(" procedure declaration or definition + if (symbol == SYM_LPARENTHESIS) + gr_procedure(variableOrProcedureName, type); + else { + allocatedMemory = allocatedMemory + 4; - // when we leave while, we don't expect any more - // code to come, but if it does, it's a syntax error - if (symbol != SYM_EOF) { - syntaxError(ERR_EOF); - exit(-1); + // type identifier ";" global variable declaration + if (symbol == SYM_SEMICOLON) { + getSymbol(); + + createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, -allocatedMemory, VARIABLE, type, 0); + + // type identifier "=" global variable definition + } else + gr_initialization(variableOrProcedureName, -allocatedMemory, type); + } + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } } } @@ -2805,54 +3298,99 @@ void emitLeftShiftBy(int b) { // assert: 0 <= b < 15 // load multiplication factor less than 2^15 to avoid sign extension - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters+1, twoToThePowerOf(b)); - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters+1, 0, FCT_MULTU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters, FCT_MFLO); + emitIFormat(OP_ADDIU, REG_ZR, nextTemporary(), twoToThePowerOf(b)); + emitRFormat(OP_SPECIAL, currentTemporary(), nextTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, currentTemporary(), FCT_MFLO); } void emitMainEntry() { - int *label; - - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // null page + // instruction at address zero cannot be fixed up, so just put a NOP there + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); - // "main": entry point - label = (int*)createString('m','a','i','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", binaryLength, FUNCTION, INT_T, 0); - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + mainJumpAddress = binaryLength; + // jump and link to main, will return here only if there is no exit call emitJFormat(OP_JAL, 0); + + // we exit cleanly with error code 0 pushed onto the stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, REG_ZR, 0); } // ----------------------------------------------------------------- -// ----------------------------- MAIN ------------------------------ +// --------------------------- COMPILER ---------------------------- // ----------------------------------------------------------------- -int main_compiler() { - initScanner(); - initSymbolTable(); - initParser(); +void compile() { + print(selfieName); + print((int*) ": this is selfie's cstarc compiling "); + print(sourceName); + println(); - allocateMachineMemory(maxCodeLength*4); + sourceFD = open(sourceName, O_RDONLY, 0); - getSymbol(); + if (sourceFD < 0) { + print(selfieName); + print((int*) ": could not open input file "); + print(sourceName); + println(); + + exit(-1); + } + + // reset scanner + resetScanner(); + + // reset global symbol table + resetGlobalSymbolTable(); + + // allocate space for storing binary + binary = malloc(maxBinaryLength); + binaryLength = 0; + + // reset code length + codeLength = 0; + + // allocate space for storing source code line numbers + sourceLineNumber = malloc(maxBinaryLength); + // jump to main emitMainEntry(); - // Library functions: - emitExit(); // first library function because this marks - // also 'default'-exit when programmer hasn't - // inserted exit() call in main + // library: + // exit must be first to exit main + // if exit call in main is missing + emitExit(); emitRead(); emitWrite(); emitOpen(); emitMalloc(); - emitGetchar(); emitPutchar(); + emitSchedYield(); + emitSwitch(); + emitMlock(); + emitMunlock(); + emitGetpid(); + + // parser + gr_cstar(); + + // set code length + codeLength = binaryLength; - gr_cstar(); // invoke compiler - emitBinary(); + // emit global variables and strings + emitGlobalsStrings(); - exit(0); + if (getInstrIndex(loadBinary(mainJumpAddress)) == 0) { + print(selfieName); + print((int*) ": main function missing in "); + print(sourceName); + println(); + + exit(-1); + } } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -2861,6 +3399,14 @@ int main_compiler() { // ----------------------------------------------------------------- // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void printRegister(int reg) { + print((int*) *(REGISTERS + reg)); +} + // ----------------------------------------------------------------- // ---------------------------- ENCODER ---------------------------- // ----------------------------------------------------------------- @@ -2953,6 +3499,14 @@ int signExtend(int immediate) { // ---------------------------- DECODER ---------------------------- // ----------------------------------------------------------------- +void printOpcode(int opcode) { + print((int*) *(OPCODES + opcode)); +} + +void printFunction(int function) { + print((int*) *(FUNCTIONS + function)); +} + void decode() { opcode = getOpcode(ir); @@ -3015,24 +3569,31 @@ void decodeJFormat() { } // ----------------------------------------------------------------- -// ---------------------------- MEMORY ----------------------------- +// ----------------------------- CODE ------------------------------ // ----------------------------------------------------------------- -void allocateMachineMemory(int size) { - memory = (int*)malloc(size); +int loadBinary(int addr) { + return *(binary + addr / 4); } -// ----------------------------------------------------------------- -// ---------------------------- BINARY ----------------------------- -// ----------------------------------------------------------------- +void storeBinary(int addr, int instruction) { + *(binary + addr / 4) = instruction; +} + +void storeInstruction(int addr, int instruction) { + *(sourceLineNumber + addr / 4) = lineNumber; + + storeBinary(addr, instruction); +} void emitInstruction(int instruction) { - if (codeLength >= maxCodeLength) { - syntaxError(ERR_MAXCODELENGTH); + if (binaryLength >= maxBinaryLength) { + syntaxErrorMessage((int*) "exceeded maximum binary length"); exit(-1); } else { - *(memory + codeLength) = instruction; - codeLength = codeLength + 1; + storeInstruction(binaryLength, instruction); + + binaryLength = binaryLength + 4; } } @@ -3070,95 +3631,155 @@ void emitJFormat(int opcode, int instr_index) { } void fixup_relative(int fromAddress) { - *(memory + fromAddress) = encodeIFormat( - getOpcode(*(memory + fromAddress)), - getRS(*(memory + fromAddress)), - getRT(*(memory + fromAddress)), - codeLength - fromAddress - 1); + int instruction; + + instruction = loadBinary(fromAddress); + + storeBinary(fromAddress, + encodeIFormat(getOpcode(instruction), + getRS(instruction), + getRT(instruction), + (binaryLength - fromAddress - 4) / 4)); } void fixup_absolute(int fromAddress, int toAddress) { - *(memory + fromAddress) = - encodeJFormat(getOpcode(*(memory + fromAddress)), toAddress); + storeBinary(fromAddress, + encodeJFormat(getOpcode(loadBinary(fromAddress)), toAddress / 4)); } void fixlink_absolute(int fromAddress, int toAddress) { int previousAddress; while (fromAddress != 0) { - previousAddress = getInstrIndex(*(memory + fromAddress)); + previousAddress = getInstrIndex(loadBinary(fromAddress)) * 4; fixup_absolute(fromAddress, toAddress); fromAddress = previousAddress; } } -void emitBinary() { - int i; - int *filename; - int fd; +int copyStringToBinary(int *s, int a) { + int l; + int w; - i = 0; + l = stringLength(s) + 1; - // put global variables as 0 at end of codearray - while (i < allocatedGlobalVariables) { - *(memory + codeLength) = 0; + w = a + l; - codeLength = codeLength + 1; + if (l % 4 != 0) + // making sure w is a multiple of 4 bytes + w = w + 4 - l % 4; - i = i + 1; + while (a < w) { + storeBinary(a, *s); + + s = s + 1; + a = a + 4; + } + + return w; +} + +void emitGlobalsStrings() { + int *entry; + + entry = global_symbol_table; + + // assert: n = binaryLength + + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeBinary(binaryLength, getValue(entry)); + + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToBinary(getString(entry), binaryLength); + + entry = getNext(entry); } - filename = (int*)malloc(4*4); - *filename = 7632239; //filename: out + // assert: binaryLength == n + allocatedMemory + + allocatedMemory = 0; +} + +void emit() { + int fd; - // assumption: file with name "out" exists prior to execution of compiler - fd = open(filename, 1); // 1 = O_WRONLY + fd = open(binaryName, O_CREAT_WRONLY_TRUNC, S_IRUSR_IWUSR_IRGRP_IROTH); if (fd < 0) { - syntaxError(ERR_FILE_NOT_FOUND); + print(selfieName); + print((int*) ": could not create output file "); + print(binaryName); + println(); + exit(-1); } - // The mipster_sycall 4004 writes the code array into a binary called 'out'. - // The syscall uses the 'write' system call of the underlying operating - // system and the compiler (gcc/x86). The write system call of our Linux uses - // Little Endian byte ordering. - write(fd, memory, codeLength*4); + print(selfieName); + print((int*) ": writing code into output file "); + print(binaryName); + println(); + + *io_buffer = codeLength; + + // first write code length + write(fd, io_buffer, 4); + + // then write binary + write(fd, binary, binaryLength); } -int loadBinary(int *filename) { +void load() { int fd; - int i; - int ret; + int numberOfReadBytes; - fd = open(filename, 0); + fd = open(binaryName, O_RDONLY, 0); + + if (fd < 0) { + print(selfieName); + print((int*) ": could not open input file "); + print(binaryName); + println(); - if (fd < 0) exit(-1); + } - i = 0; + binary = malloc(maxBinaryLength); + binaryLength = 0; - ret = 4; + codeLength = 0; - while (ret == 4) { - ret = read(fd, memory + i, 4); + sourceLineNumber = (int*) 0; - if (debug_load) { - memset(string_buffer, 33, 0); - print(itoa(i * 4, string_buffer, 16, 4)); - putchar(' '); - putchar('#'); - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa(*(memory+i), string_buffer, 16, 8)); - putchar(CHAR_LF); - } + print(selfieName); + print((int*) ": loading code from input file "); + print(binaryName); + println(); - i = i + 1; + // read code length first + numberOfReadBytes = read(fd, io_buffer, 4); + + if (numberOfReadBytes == 4) { + codeLength = *io_buffer; + + // now read binary + numberOfReadBytes = read(fd, binary, maxBinaryLength); + + if (numberOfReadBytes > 0) { + binaryLength = numberOfReadBytes; + + return; + } } - // Return global pointer and bump pointer for malloc - return i * 4; + print(selfieName); + print((int*) ": failed to load code from input file "); + print(binaryName); + println(); + + exit(-1); } // ----------------------------------------------------------------- @@ -3166,22 +3787,23 @@ int loadBinary(int *filename) { // ----------------------------------------------------------------- void emitExit() { - int *label; - - // "exit" - label = createString('e','x','i','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "exit", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + // load argument for exit emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + + // remove the argument from the stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + // load the correct syscall number and invoke syscall emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_EXIT); emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + // never returns here } void syscall_exit() { @@ -3189,24 +3811,18 @@ void syscall_exit() { exitCode = *(registers+REG_A0); - printString('[','O','S',']',' ','T', 'e', 'r','m','i','n','a','t','e','d',' ','w','i','t','h'); - putchar(' '); - *(registers+REG_V0) = exitCode; - print(itoa(exitCode, string_buffer, 10, 0)); - putchar(CHAR_LF); + print(binaryName); + print((int*) ": exiting with error code "); + print(itoa(exitCode, string_buffer, 10, 0, 0)); + println(); - exit(0); + halt = 1; } void emitRead() { - int *label; - - // "read" - label = createString('r','e','a','d',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3222,48 +3838,41 @@ void emitRead() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_read() { int count; - int address; + int vaddr; int fd; int *buffer; int size; - count = *(registers+REG_A2); - address = *(registers+REG_A1) / 4; - fd = *(registers+REG_A0); + count = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); - buffer = memory + address; + buffer = memory + tlb(vaddr); size = read(fd, buffer, count); *(registers+REG_V0) = size; - if (debug_syscalls) { - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','r','e','a','d',' ',CHAR_TAB,0,0,0,0); - - print(itoa(fd, string_buffer, 10, 0)); - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa((int)buffer, string_buffer, 16, 8)); - putchar(' '); - print(itoa(size, string_buffer, 10, 0)); - putchar(CHAR_LF); + if (debug_read) { + print(binaryName); + print((int*) ": read "); + print(itoa(size, string_buffer, 10, 0, 0)); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8, 0)); + println(); } } void emitWrite() { - int *label; - - // "write" - label = createString('w','r','i','t','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3279,41 +3888,44 @@ void emitWrite() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_write() { int size; - int address; + int vaddr; int fd; int *buffer; - size = *(registers+REG_A2); - address = *(registers+REG_A1) / 4; - fd = *(registers+REG_A0); + size = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); - buffer = memory + address; + buffer = memory + tlb(vaddr); size = write(fd, buffer, size); *(registers+REG_V0) = size; - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','w','r','i','t','e',CHAR_LF,0,0,0,0); + if (debug_write) { + print(binaryName); + print((int*) ": wrote "); + print(itoa(size, string_buffer, 10, 0, 0)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8, 0)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + println(); + } } void emitOpen() { - int *label; - - // "open" - label = createString('o','p','e','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "open", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // mode + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); emitIFormat(OP_LW, REG_SP, REG_A1, 0); // flags emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); @@ -3324,61 +3936,54 @@ void emitOpen() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_open() { + int mode; int flags; - int address; + int vaddr; int *filename; int fd; - flags = *(registers+REG_A1); - address = *(registers+REG_A0) / 4; + mode = *(registers+REG_A2); + flags = *(registers+REG_A1); + vaddr = *(registers+REG_A0); - filename = memory + address; + filename = memory + tlb(vaddr); - fd = open(filename, flags); + fd = open(filename, flags, mode); *(registers+REG_V0) = fd; - if (debug_syscalls) { - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','o','p','e','n',' ',CHAR_TAB,0,0,0,0); - - print(itoa(fd, string_buffer, 10, 0)); - putchar(CHAR_LF); + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 16, 0, 0)); + print((int*) " and mode "); + print(itoa(mode, string_buffer, 8, 0, 0)); + print((int*) " returning file descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + println(); } } void emitMalloc() { - int *label; - - // "malloc" - label = createString('m','a','l','l','o','c',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INTSTAR_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "malloc", binaryLength, FUNCTION, INTSTAR_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); - // load argument for malloc (size) emitIFormat(OP_LW, REG_SP, REG_A0, 0); - - // remove the argument from the stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // load the correct syscall number and invoke syscall emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MALLOC); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - // put return value into return register - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - // jump back to caller - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_malloc() { @@ -3388,7 +3993,7 @@ void syscall_malloc() { size = *(registers+REG_A0); if (size % 4 != 0) - size = size + (4 - size % 4); + size = size + 4 - size % 4; bump = *(registers+REG_K1); @@ -3398,45 +4003,18 @@ void syscall_malloc() { *(registers+REG_K1) = bump + size; *(registers+REG_V0) = bump; - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','m','a','l','l','o','c',CHAR_LF,0,0,0); -} - -void emitGetchar() { - int *label; - - // "getchar" - label = createString('g','e','t','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); - - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 0); - - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_GETCHAR); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); -} - -void syscall_getchar() { - *(registers+REG_V0) = getchar(); - - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','g','e','t','c','h','a','r',CHAR_LF,0,0); + if (debug_malloc) { + print(binaryName); + print((int*) ": malloc "); + print(itoa(size, string_buffer, 10, 0, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8, 0)); + println(); + } } void emitPutchar() { - int *label; - - // "putchar" - label = createString('p','u','t','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3450,441 +4028,1458 @@ void emitPutchar() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ -// ----------------------------------------------------------------- -// --------------------- E M U L A T O R --------------------- +void emitSchedYield() { + + // create Symbol Table Entroy for yield + createSymbolTableEntry(GLOBAL_TABLE, (int*) "sched_yield", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SCHED_YIELD); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + +} + +void syscall_sched_yield(){ + + schedule_and_switch(); + + if (debug_sched_yield) { + print(binaryName); + println(); + print((int*) "sched_yield"); + println(); + } + +} + +void emitSwitch() { + + // create Symbol Table Entry for swapoff + createSymbolTableEntry(GLOBAL_TABLE, (int*) "switch", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SWITCH); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + +} + +void syscall_switch() { + + if(*(running_process) == 0){ + + prev_node = getNodeByIdFromProcessList(running_process_id); + prev_process = (int*) (prev_node); + + syscall_getpid(); + + next_node = getNodeByIdFromProcessList(running_process_id); + next_process = (int*) (next_node); + + *(running_process + 1) = *(running_process + 1) + 1; + + running_process = next_process ; + + ready_queue = deleteFirstNodeFromList(ready_queue); + println(); + println(); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "Running Kernel Process and Switch to User Process"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + println(); + } + else{ + prev_node = getNodeByIdFromProcessList(running_process_id); + prev_process = (int*) (prev_node); + + next_node = getNodeByIdFromProcessList(0); + next_process = (int*) (next_node); + + running_process = next_process; + + ready_queue = addToList(ready_queue, (int) prev_process); + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Running User Process and Switch to Kernel Process"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + + } + +} + +void emitMlock() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "mlock", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MLOCK); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + // We don't have a return value so we just jump back + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_mlock() { + *lock = *(running_process); + + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Running User Process get's the lock"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); +} + +void emitMunlock() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "munlock", binaryLength, FUNCTION, INT_T, 0); + + // doesn't have any arguments + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MUNLOCK); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + // We don't have a return value so we just jump back + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_munlock() { + int size; + int new_size; + int i; + int* node; + int* process; + + i = 0; + size = sizeOfList(blocked_queue); + *lock = 0; + + while(i < size){ + new_size = sizeOfList(blocked_queue) - 1; + node = (int*) getNodeFromList(blocked_queue, new_size); + process = (int*) *(node + 1); + blocked_queue = deleteFirstNodeFromList(blocked_queue); + ready_queue = addToList(ready_queue,(int) process); + i = i + 1; + } +} + +void emitGetpid() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "getpid", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_GETPID); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + // We don't have a return value so we just jump back + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_getpid(int* list) { + + int* node; + int* process; + int size; + + size = sizeOfList(ready_queue)-1; + + node = (int*) getNodeFromList(ready_queue, size); + process = (int*) *(node + 1); + running_process_id = *(process); + +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------------- kOS --------------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +int* getNodeByIdFromProcessList(int id){ + + int* node_i; + int* process_i; + int i; + int j; + int* Buffer; + + i = 0; + + Buffer = (int*)malloc(4*10); + + while(i < all_processes) { + node_i = (int*) getNodeFromList(process_list, i); + process_i = (int*) *(node_i + 1); + + j = (int) *(process_i); + + if(j == id){ + + return process_i; + } + i = i + 1; + } + + +} + +void create_process_List(int number){ + int *node; + int *process; + int pid_process_list; + int pid_ready_queue; + + + pid_process_list = 0; + pid_ready_queue = number_of_processes - 1; + process_list = initializeList(process_list); + + while(pid_process_list < number){ + if(pid_process_list == 0){ + process_list = addToList(process_list, (int) kernel_process); + pid_process_list = pid_process_list + 1; + } + else{ + node = (int*) getNodeFromList(ready_queue, pid_ready_queue); + process = (int*) *(node+1); + process_list = addToList(process_list, (int) process); + pid_process_list = pid_process_list + 1; + pid_ready_queue = pid_ready_queue - 1; + } + } +} + +// ------------------------ DATA STRUCTURE FOR THE LOCK ----------------------- +// Creating a the Lock with Process ID which holds the Lock +// and a Pointer to the Blocked Queue +void create_lock(){ + + lock = malloc(2 * 4); + *lock = 0; + *(lock+1) = *blocked_queue; +} + + +// Sort the list with Bubble Sort +int* sortListByPC(int *list) { + + int size; + int i; + int *listNodeX; + int *listNodeY; + int *tempNode; + int *listProcessX; + int *listProcessY; + int listProcessPCX; + int listProcessPCY; + int* Buffer; + + Buffer = (int*)malloc(4*10); + size = sizeOfList(list); + + + if(size == 0){ + print((int*) "List is empty"); + println(); + } + else{ + while(size > 1){ + + print((int*) "List is not empty"); + println(); + i = 0; + while(i < size-1) { + listNodeX = (int*) getNodeFromList(list, i); + listNodeY = (int*) getNodeFromList(list, i+1); + listProcessX = (int*) *(listNodeX + 1); + listProcessY = (int*) *(listNodeY + 1); + listProcessPCX = *(listProcessX+1); + listProcessPCY = *(listProcessY+1); + + println(); + print(itoa(listProcessPCX, Buffer, 10, 0, 0)); + println(); + + println(); + print(itoa(listProcessPCY, Buffer, 10, 0, 0)); + println(); + + if(listProcessPCX < listProcessPCY) { + print((int*) "change"); + println(); + *(listNodeX + 1) = (int) listProcessY; + *(listNodeY + 1) = (int) listProcessX; + } + else{ + print((int*) "no change"); + println(); + } + i = i + 1; + } + size = size - 1; + } + } + + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Ready-Queue after sorting"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(ready_queue); + print((int*) "PCs"); + println(); + printListPC(ready_queue); + + return list; +} + +void runOS(int argc, int* argv){ + + int* Buffer; + Buffer = (int*)malloc(4*10); + + + while(1){ + println(); + println(); + println(); + println(); + println(); + print((int*) "BEFORE RUNNING KERNEL"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Process-List before running kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(process_list); + print((int*) "PCs"); + println(); + printListPC(process_list); + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Ready-Queue before running Kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(ready_queue); + print((int*) "PCs"); + println(); + printListPC(ready_queue); + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Blocked-Queue before running Kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(blocked_queue); + print((int*) "PCs"); + println(); + printListPC(blocked_queue); + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Running Process before running Kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PID"); + println(); + print(itoa(*(running_process), Buffer, 10, 0, 0)); + println(); + print((int*) "PC"); + println(); + print(itoa(*(running_process+1), Buffer, 10, 0, 0)); + println(); + + syscall_switch(); + + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Process-List after running kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "PIDs"); + println(); + printListPID(process_list); + print((int*) "PCs"); + println(); + printListPC(process_list); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Ready-Queue after running kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "PIDs"); + println(); + printListPID(ready_queue); + print((int*) "PCs"); + println(); + printListPC(ready_queue); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Blocked-Queue after running kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "PIDs"); + println(); + printListPID(blocked_queue); + print((int*) "PCs"); + println(); + printListPC(blocked_queue); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Running-Process after running kernel"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "PID"); + println(); + print(itoa(*(running_process), Buffer, 10, 0, 0)); + println(); + print((int*) "PC"); + println(); + print(itoa(*(running_process+1), Buffer, 10, 0, 0)); + println(); + + if(debug_locking == 1){ + if(*lock == 0){ + syscall_mlock(); + debug_locking = 0; + run(argc, (int*) argv); + } + else if(*lock == *running_process){ + + syscall_munlock(); + + ready_queue = sortListByPC(ready_queue); + + debug_locking = 0; + + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Unlocking and adding all User Process from the Blocked-Queue to the Ready-Queue"); + println(); + print((int*) "and then running the actual User Process"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + run(argc, (int*) argv); + } + else{ + blocked_queue = addToList(blocked_queue, (int) running_process); + running_process = kernel_process; + + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Running User Process added to Blocked-Queue"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + debug_locking = 0; + } + } + else{ + + if(*lock == *running_process){ + + syscall_munlock(); + + ready_queue = sortListByPC(ready_queue); + + debug_locking = 0; + + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Unlocking and adding all User Process from the Blocked-Queue to the Ready-Queue"); + println(); + print((int*) "and then running the actual User Process"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + run(argc, (int*) argv); + } + else{ + println(); + println(); + println(); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "Running User Process does not need the lock"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + print((int*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + println(); + debug_locking = 1; + run(argc, (int*) argv); + } + } + } + +} + +void kOS(int argc, int* argv) { + int *new_reg; + int* Buffer; + + if(booting == 1){ + + booting = 0; + + new_reg = malloc(4*32); + Buffer = (int*)malloc(4*10); + + all_processes = number_of_processes + 1; + + kernel_process = create_process(0, new_reg, reg_hi, reg_lo); + running_process = kernel_process; + + current_frame_number = 0; + + create_frame_table(); + + println(); + print((int*) "Memory Size"); + println(); + + println(); + print(itoa(memorySize, Buffer, 10, 0, 0)); + println(); + + create_ready_queue(all_processes, ticks); + create_process_List(all_processes); + blocked_queue = initializeList(blocked_queue); + create_lock(); + + println(); + println(); + println(); + println(); + println(); + print((int*) "BOOTING"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "____________________________________________________"); + println(); + println(); + print((int*) "This is the Process-List after Booting"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(process_list); + print((int*) "PCs"); + println(); + printListPC(process_list); + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Ready-Queue after Booting"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(ready_queue); + print((int*) "PCs"); + println(); + printListPC(ready_queue); + + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Blocked-Queue after Booting"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PIDs"); + println(); + printListPID(blocked_queue); + print((int*) "PCs"); + println(); + printListPC(blocked_queue); + + print((int*) "____________________________________________________"); + println(); + print((int*) "This is the Running-Process after Booting"); + println(); + print((int*) "____________________________________________________"); + println(); + print((int*) "PID"); + println(); + print(itoa(*(running_process), Buffer, 10, 0, 0)); + println(); + print((int*) "PC"); + println(); + print(itoa(*(running_process+1), Buffer, 10, 0, 0)); + println(); + + runOS(argc, (int*) argv); + } + + else{ + runOS(argc, (int*) argv); + } + +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- // ----------------------------------------------------------------- // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +int tlb(int vaddr) { + if (vaddr % 4 != 0) + exception_handler(EXCEPTION_ADDRESSERROR); + + // physical memory is word-addressed for lack of byte-sized data type + return vaddr / 4; +} + +int loadMemory(int vaddr) { + int paddr; + + paddr = tlb(vaddr); + + return *(memory + paddr); +} + +void storeMemory(int vaddr, int data) { + int paddr; + + paddr = tlb(vaddr); + + *(memory + paddr) = data; +} + // ----------------------------------------------------------------- // ------------------------- INSTRUCTIONS -------------------------- // ----------------------------------------------------------------- void fct_syscall() { - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + if (debug) { + printFunction(function); + println(); } - if (*(registers+REG_V0) == SYSCALL_EXIT) { - syscall_exit(); - } else if (*(registers+REG_V0) == SYSCALL_READ) { - syscall_read(); - } else if (*(registers+REG_V0) == SYSCALL_WRITE) { - syscall_write(); - } else if (*(registers+REG_V0) == SYSCALL_OPEN) { - syscall_open(); - } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { - syscall_malloc(); - } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { - syscall_getchar(); - } else { - exception_handler(EXCEPTION_UNKNOWNSYSCALL); - } + if (interpret) { + if (*(registers+REG_V0) == SYSCALL_EXIT) { + syscall_exit(); + } else if (*(registers+REG_V0) == SYSCALL_READ) { + syscall_read(); + } else if (*(registers+REG_V0) == SYSCALL_WRITE) { + syscall_write(); + } else if (*(registers+REG_V0) == SYSCALL_OPEN) { + syscall_open(); + } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { + syscall_malloc(); + } else if (*(registers+REG_V0) == SYSCALL_SCHED_YIELD) { + syscall_sched_yield(); + } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { + syscall_switch(); + } else { + exception_handler(EXCEPTION_UNKNOWNSYSCALL); + } - pc = pc + 1; + pc = pc + 4; + } } void fct_nop() { - pc = pc + 1; - - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + if (debug) { + printFunction(function); + println(); } + + if (interpret) + pc = pc + 4; } void op_jal() { - *(registers+REG_LINK) = pc * 4 + 8; + if (debug) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 0, 0)); + print((int*) "["); + print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(REG_RA); + print((int*) "="); + print(itoa(*(registers+REG_RA), string_buffer, 16, 0, 0)); + } + } - pc = instr_index; + if (interpret) { + *(registers+REG_RA) = pc + 8; - // TODO: execute delay slot + pc = instr_index * 4; - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + // keep track of number of procedure calls + calls = calls + 1; - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + *(callsPerAddress + pc / 4) = *(callsPerAddress + pc / 4) + 1; + + // TODO: execute delay slot + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(REG_RA); + print((int*) "="); + print(itoa(*(registers+REG_RA), string_buffer, 16, 0, 0)); + print((int*) ",$pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); } } void op_j() { - pc = instr_index; + if (debug) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 0, 0)); + print((int*) "["); + print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + } - // TODO: execute delay slot + if (interpret) { + pc = instr_index * 4; - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + // TODO: execute delay slot + } - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) ": -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); } } void op_beq() { - pc = pc + 1; - - if (*(registers+rs) == *(registers+rt)) { - pc = pc + signExtend(immediate); - // TODO: execute delay slot + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "["); + print(itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } } - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + if (interpret) { + pc = pc + 4; - putchar(' '); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); + if (*(registers+rs) == *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; + + if (signExtend(immediate) < 0) { + // keep track of number of loop iterations + loops = loops + 1; + + *(loopsPerAddress + pc / 4) = *(loopsPerAddress + pc / 4) + 1; + } + + // TODO: execute delay slot + } + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); } } void op_bne() { - pc = pc + 1; - - if (*(registers+rs) != *(registers+rt)) { - pc = pc + signExtend(immediate); - // TODO: execute delay slot + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "["); + print(itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } } - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + if (interpret) { + pc = pc + 4; + + if (*(registers+rs) != *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; - putchar(' '); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); + // TODO: execute delay slot + } + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); } } void op_addiu() { - *(registers+rt) = *(registers+rs) + signExtend(immediate); - - // TODO: check for overflow + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + printRegister(rs); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + } + } - pc = pc + 1; + if (interpret) { + *(registers+rt) = *(registers+rs) + signExtend(immediate); - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + // TODO: check for overflow - putchar(' '); - print((int*)(*(register_strings+rt))); - putchar(','); - print((int*)(*(register_strings+rs))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } + println(); } } void fct_jr() { - pc = *(registers+rs) / 4; - - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); - - putchar(CHAR_LF); + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); + } } -} - -void op_lui() { - *(registers+rt) = leftShift(immediate, 16); - - pc = pc + 1; - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + if (interpret) + pc = *(registers+rs); - putchar(' '); - - print((int*)(*(register_strings+rt))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); } } void fct_mfhi() { - *(registers+rd) = reg_hi; - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + *(registers+rd) = reg_hi; - putchar(' '); - print((int*)(*(register_strings+rd))); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + } + println(); } } void fct_mflo() { - *(registers+rd) = reg_lo; - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + *(registers+rd) = reg_lo; - putchar(' '); - print((int*)(*(register_strings+rd))); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + } + println(); } } void fct_multu() { - // TODO: 64-bit resolution currently not supported - reg_lo = *(registers+rs) * *(registers+rt); - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + // TODO: 64-bit resolution currently not supported + reg_lo = *(registers+rs) * *(registers+rt); - putchar(' '); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> $lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + println(); } } void fct_divu() { - reg_lo = *(registers+rs) / *(registers+rt); - reg_hi = *(registers+rs) % *(registers+rt); - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + reg_lo = *(registers+rs) / *(registers+rt); + reg_hi = *(registers+rs) % *(registers+rt); - putchar(' '); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> $lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + println(); } } void fct_addu() { - *(registers+rd) = *(registers+rs) + *(registers+rt); + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } + } - pc = pc + 1; + if (interpret) { + *(registers+rd) = *(registers+rs) + *(registers+rt); - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + pc = pc + 4; + } - putchar(' '); - print((int*)(*(register_strings+rd))); - putchar(','); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + } + println(); } } void fct_subu() { - *(registers+rd) = *(registers+rs) - *(registers+rt); - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + *(registers+rd) = *(registers+rs) - *(registers+rt); - putchar(' '); - print((int*)(*(register_strings+rd))); - putchar(','); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); + pc = pc + 4; + } + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + } + println(); } } void op_lw() { int vaddr; - int paddr; - - vaddr = *(registers+rs) + signExtend(immediate); - paddr = addressTranslation(vaddr) / 4; + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "("); + printRegister(rs); + print((int*) ")"); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); + } + } - *(registers+rt) = *(memory+paddr); + if (interpret) { + vaddr = *(registers+rs) + signExtend(immediate); - pc = pc + 1; + *(registers+rt) = loadMemory(vaddr); - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + // keep track of number of loads + loads = loads + 1; - putchar(' '); - print((int*)(*(register_strings+rt))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); + *(loadsPerAddress + pc / 4) = *(loadsPerAddress + pc / 4) + 1; - putchar('('); - print((int*)(*(register_strings+rs))); - putchar(')'); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) "=memory[vaddr="); + print(itoa(vaddr, string_buffer, 16, 0, 0)); + print((int*) "]"); + } + println(); } } void fct_slt() { - if (*(registers+rs) < *(registers+rt)) - *(registers+rd) = 1; - else - *(registers+rd) = 0; - - pc = pc + 1; + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } + } - if (debug_disassemble) { - print((int*)(*(fct_strings+function))); + if (interpret) { + if (*(registers+rs) < *(registers+rt)) + *(registers+rd) = 1; + else + *(registers+rd) = 0; - putchar(' '); - print((int*)(*(register_strings+rd))); - putchar(','); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); + } + println(); } } void op_sw() { int vaddr; - int paddr; - int tmp; - vaddr = *(registers+rs) + signExtend(immediate); - - paddr = addressTranslation(vaddr) / 4; + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "("); + printRegister(rs); + print((int*) ")"); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); + } + } - *(memory+paddr) = *(registers+rt); + if (interpret) { + vaddr = *(registers+rs) + signExtend(immediate); - pc = pc + 1; + storeMemory(vaddr, *(registers+rt)); - if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); + // keep track of number of stores + stores = stores + 1; - putchar(' '); - print((int*)(*(register_strings+rt))); - putchar(','); - print(itoa(signExtend(immediate), string_buffer, 10, 0)); + *(storesPerAddress + pc / 4) = *(storesPerAddress + pc / 4) + 1; - putchar('('); - print((int*)(*(register_strings+rs))); - putchar(')'); + pc = pc + 4; + } - putchar(CHAR_LF); + if (debug) { + if (interpret) { + print((int*) " -> memory[vaddr="); + print(itoa(vaddr, string_buffer, 16, 0, 0)); + print((int*) "]="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + print((int*) "="); + printRegister(rt); + } + println(); } } void fct_teq() { - if (*(registers+rs) == *(registers+rt)) - exception_handler(EXCEPTION_SIGNAL); - - pc = pc + 1; - - if (debug_disassemble) { - print((int*)*(fct_strings+function)); + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); + } + } - putchar(' '); - print((int*)(*(register_strings+rs))); - putchar(','); - print((int*)(*(register_strings+rt))); + if (interpret) { + if (*(registers+rs) == *(registers+rt)) + exception_handler(EXCEPTION_SIGNAL); - putchar(CHAR_LF); + pc = pc + 4; } + + if (debug) + println(); } // ----------------------------------------------------------------- // -------------------------- INTERPRETER -------------------------- // ----------------------------------------------------------------- -void exception_handler(int enumber) { - if (enumber == EXCEPTION_SIGNAL) { - exit(EXCEPTION_SIGNAL); - } else if (enumber == EXCEPTION_ADDRESSERROR) { - exit(EXCEPTION_ADDRESSERROR); - } else if (enumber == EXCEPTION_UNKNOWNINSTRUCTION) { - exit(EXCEPTION_UNKNOWNINSTRUCTION); - } else if (enumber == EXCEPTION_HEAPOVERFLOW) { - exit(EXCEPTION_HEAPOVERFLOW); - } else if (enumber == EXCEPTION_UNKNOWNSYSCALL) { - exit(EXCEPTION_UNKNOWNSYSCALL); - } else if (enumber == EXCEPTION_UNKNOWNFUNCTION) { - exit(EXCEPTION_UNKNOWNFUNCTION); - } +void printException(int enumber) { + print((int*) *(EXCEPTIONS + enumber)); } -int addressTranslation(int vaddr) { - if (vaddr % 4 != 0) - exception_handler(EXCEPTION_ADDRESSERROR); +void exception_handler(int enumber) { + print(binaryName); + print((int*) ": exception: "); + printException(enumber); + println(); - return vaddr; + exit(enumber); } -void pre_debug() { - if (debug_disassemble) { - memset(string_buffer, 33, 0); // print current PC - print(itoa(4 * pc, string_buffer, 16, 4)); - putchar(CHAR_TAB); - } +void fetch() { + ir = loadMemory(pc); } -void post_debug() { - int i; - if (debug_registers) { - i = 0; +void execute() { + if (debug) + if (sourceLineNumber != (int*) 0) { + print(binaryName); + print((int*) ": "); + } - while (i < 32) { - if (*(registers+i) != 0) { - print((int*)*(register_strings+i)); - putchar(CHAR_TAB); - memset(string_buffer, 33, 0); - print(itoa(*(registers+i), string_buffer, 16, 8)); + if (interpret) + if (debug) + print((int*) "$pc="); - putchar(CHAR_LF); - } - i = i + 1; + if (debug) { + print(itoa(pc, string_buffer, 16, 8, 0)); + if (sourceLineNumber != (int*) 0) { + print((int*) "(~"); + print(itoa(*(sourceLineNumber + pc / 4), string_buffer, 10, 0, 0)); + print((int*) ")"); } - putchar(CHAR_LF); + print((int*) ": "); } -} - -void fetch() { - ir = *(memory+pc); -} -void execute() { if (opcode == OP_SPECIAL) { if (function == FCT_NOP) { fct_nop(); @@ -3928,55 +5523,95 @@ void execute() { } else { exception_handler(EXCEPTION_UNKNOWNINSTRUCTION); } + + if (interpret == 0) { + if (pc == codeLength - 4) + halt = 1; + else + pc = pc + 4; + } } -void run() { +// Print the value of the Process IDs +void printListPID(int *list) { + int counter; + int number; + int *Buffer; + int *node; + int *process; + + Buffer = (int*)malloc(4*10); + + counter = sizeOfList(list)-1; + + while(counter >= 0) { + node = (int*) getNodeFromList(list, counter); + process = (int*) *(node+1); + number = *(process); + print(itoa(number, Buffer, 10, 0, 0)); + putchar(CHAR_LF); + counter = counter - 1; + } - while (1) { - fetch(); - decode(); - pre_debug(); - execute(); - post_debug(); - } } -void debug_boot(int memorySize) { - printString('m','e','m',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +// Print the value of the Program counters +void printListPC(int *list) { + + int counter; + int number; + int *Buffer; + int *node; + int *process; - print(itoa(memorySize/1024/1024*4, string_buffer, 10, 0)); + counter = sizeOfList(list)-1; - printString('M','B',CHAR_LF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + while(counter >= 0) { + node = (int*) getNodeFromList(list, counter); + process = (int*) *(node+1); + number = *(process+1); + Buffer = (int*)malloc(4*10); + print(itoa(number, Buffer, 10, 0, 0)); + putchar(CHAR_LF); + counter = counter - 1; + } } -int* parse_args(int argc, int *argv, int *cstar_argv) { - // assert: ./selfie -m size executable {-m size executable} - int memorySize; +void run(int argc, int* argv) { + + int instr; - memorySize = atoi((int*)*(cstar_argv+2)) * 1024 * 1024 / 4; + instr = 0; + halt = 0; - allocateMachineMemory(memorySize*4); + while (halt == 0) { - // initialize stack pointer - *(registers+REG_SP) = (memorySize - 1) * 4; + instr = instr + 1; + *(running_process + 1) = *(running_process + 1) + 1; - debug_boot(memorySize); + if(instr == numb_of_instr){ + halt = 1; + } + } + + interpret = 0; + debug = 0; - // return executable file name - return (int*)*(argv+3); + syscall_switch(); + kOS(argc, (int*) argv); } void up_push(int value) { - int address; + int vaddr; // allocate space for one value on the stack *(registers+REG_SP) = *(registers+REG_SP) - 4; // compute address - address = *(registers+REG_SP) / 4; + vaddr = *(registers+REG_SP); // store value - *(memory + address) = value; + storeMemory(vaddr, value); } int up_malloc(int size) { @@ -3987,154 +5622,727 @@ int up_malloc(int size) { return *(registers+REG_V0); } -int CStringLength(int* s) { +int up_copyString(int *s) { int l; + int a; + int w; + int t; + + l = stringLength(s) + 1; + + a = up_malloc(l); - l = 0; + w = a + l; - while (rightShift(leftShift(*s, 24 - (l % 4) * 8), 24) != 0) { - l = l + 1; + if (l % 4 != 0) + // making sure w is a multiple of 4 bytes + w = w + 4 - l % 4; - if (l % 4 == 0) - s = s + 1; + t = a; + + while (a < w) { + storeMemory(a, *s); + + s = s + 1; + a = a + 4; } - return l; + return t; } -int up_copyCString(int *s) { - int l; - int r; +void up_copyArguments(int argc, int *argv) { + int vaddr; + + up_push(argc); + + vaddr = up_malloc(argc * 4); + + up_push(vaddr); + + while (argc > 0) { + storeMemory(vaddr, up_copyString((int*) *argv)); + + vaddr = vaddr + 4; + + argv = argv + 1; + argc = argc - 1; + } +} + +void copyBinaryToMemory() { int a; - l = CStringLength(s); + a = 0; - r = up_malloc(l+1); + while (a < binaryLength) { + storeMemory(a, loadBinary(a)); - a = r / 4; + a = a + 4; + } +} - while (a * 4 < r + l + 1) { - *(memory + a) = *s; +int addressWithMaxCounter(int *counters, int max) { + int a; + int n; + int i; + int c; - s = s + 1; - a = a + 1; + a = -1; + + n = 0; + + i = 0; + + while (i < maxBinaryLength / 4) { + c = *(counters + i); + + if (n < c) + if (c < max) { + n = c; + a = i * 4; + } + + i = i + 1; } - return r; + return a; } -void up_copyArguments(int argc, int *argv) { - int c_argv; - - up_push(argc); +int fixedPointRatio(int a, int b) { + // assert: a >= b + int r; - c_argv = up_malloc(argc*4); + // compute fixed point ratio r with 2 fractional digits - up_push(c_argv); + r = 0; - c_argv = c_argv / 4; + // multiply a/b with 100 but avoid overflow - while (argc > 0) { - *(memory + c_argv) = up_copyCString((int*)*argv); + if (a <= INT_MAX / 100) { + if (b != 0) + r = a * 100 / b; + } else if (a <= INT_MAX / 10) { + if (b / 10 != 0) + r = a * 10 / (b / 10); + } else { + if (b / 100 != 0) + r = a / (b / 100); + } - c_argv = c_argv + 1; - argv = argv + 1; + // compute a/b in percent + // 1000000 = 10000 (for 100.00%) * 100 (for 2 fractional digits of r) - argc = argc - 1; + if (r != 0) + return 1000000 / r; + else + return 0; +} + +int printCounters(int total, int *counters, int max) { + int a; + + a = addressWithMaxCounter(counters, max); + + print(itoa(*(counters + a / 4), string_buffer, 10, 0, 0)); + + print((int*) "("); + print(itoa(fixedPointRatio(total, *(counters + a / 4)), string_buffer, 10, 0, 2)); + print((int*) "%)"); + + if (*(counters + a / 4) != 0) { + print((int*) "@"); + print(itoa(a, string_buffer, 16, 8, 0)); + if (sourceLineNumber != (int*) 0) { + print((int*) "(~"); + print(itoa(*(sourceLineNumber + a / 4), string_buffer, 10, 0, 0)); + print((int*) ")"); + } } + + return a; } -int main_emulator(int argc, int *argv, int *cstar_argv) { - initInterpreter(); +void printProfile(int *message, int total, int *counters) { + int a; + + if (total > 0) { + print(selfieName); + print(message); + print(itoa(total, string_buffer, 10, 0, 0)); + print((int*) ","); + a = printCounters(total, counters, INT_MAX); // max counter + print((int*) ","); + a = printCounters(total, counters, *(counters + a / 4)); // 2nd max + print((int*) ","); + a = printCounters(total, counters, *(counters + a / 4)); // 3rd max + println(); + } +} + +void disassemble(int argc, int* argv) { + assemblyFD = open(assemblyName, O_CREAT_WRONLY_TRUNC, S_IRUSR_IWUSR_IRGRP_IROTH); + + if (assemblyFD < 0) { + print(selfieName); + print((int*) ": could not create assembly output file "); + print(assemblyName); + println(); + + exit(-1); + } + + print(selfieName); + print((int*) ": writing assembly into output file "); + print(assemblyName); + println(); - *(registers+REG_GP) = loadBinary(parse_args(argc, argv, cstar_argv)); + outputName = assemblyName; + outputFD = assemblyFD; - *(registers+REG_K1) = *(registers+REG_GP); + interpret = 0; + debug = 1; - up_copyArguments(argc-3, argv+3); + copyBinaryToMemory(); - run(); + resetInterpreter(); - exit(0); + run(argc, (int*) argv); + + outputName = (int*) 0; + outputFD = 1; +} + +//// Assignment 0: Basic data structures //// +//Review linked lists and implement a simple program using a singly linked list in C*. The minimal requirements are as follows: +// +//must be implemented in C* +//must compile with selfie +//must run on selfie +//the list must be dynamically allocated +//every node must be dynamically allocated +//inserting nodes to the list and removing nodes from the list +//list iteration +//Bonus: sort the list. Any way you like +//Deadline: Oct 15, end of day + +// Initialization of the linked list (Creating the header with data -1) +// The header cannot be deleted!! +int* initializeList(int *list) { + int *header; + int data; + + header = malloc(4*2); + *header = 0; + return header; +} + +// Add a node to the linked list at the bottom +int* addToList(int *list, int data) { + + int *newNode; + newNode = malloc(4*2); + *newNode = (int) list; + *(newNode+1) = data; + return newNode; +} + +// Iterate through the linked list and get the nth node of the list +int getNodeFromList(int *list, int nthNode) { + + while(nthNode > 0) { + list = (int*) *list; + nthNode = nthNode - 1; + } + + return (int) list; +} + +// Get the size of the linked list +int sizeOfList(int *list) { + + int count; + count = 0; + + while(*list != 0) { + list = (int*) *list; + count = count + 1; + } + return count; +} + +// Delete a node from the linked list from the top +int* deleteFirstNodeFromList(int *list) { + + int *prev; + int *next; + int size; + prev = malloc(2*4); + next = malloc(2*4); + *prev = 0; + *next = 0; + size = sizeOfList(list); + + if(size == 1){ + list = initializeList(list); + } + else{ + + prev = (int*) getNodeFromList(list, size-2); + next = (int*) getNodeFromList(list, size); + *prev = (int) next; + } + + return list; +} + +// Sort the list with Bubble Sort +int* sortList(int *list) { + + int size; + int i; + int *listitemX; + int *listitemY; + int x; + int y; + + size = sizeOfList(list); + + + if(size == 0){ + print((int*) "List is empty"); + println(); + } + else{ + while(size > 1){ + i = 0; + while(i < size-1) { + listitemX = (int*) getNodeFromList(list, i); + listitemY = (int*) getNodeFromList(list, i+1); + x = *(listitemX+1); + y = *(listitemY+1); + + if(x < y) { + *(listitemX + 1) = y; + *(listitemY + 1) = x; + } + i = i + 1; + } + size = size - 1; + } + } + return list; +} + +// Print the linked list +void printList(int *list) { + + int counter; + int *nodeNumber; + int number; + int *Buffer; + + counter = sizeOfList(list)-1; + + while(counter >= 0) { + nodeNumber = (int*) getNodeFromList(list, counter); + number = *(nodeNumber+1); + Buffer = (int*)malloc(4*10); + print(itoa(number, Buffer, 10, 0, 0)); + putchar(CHAR_LF); + counter = counter - 1; + } +} + +//Testing for Assignment 00 +int testList() { + + int *list; + // Create new linked list (FIFO Linked List): + // top -> [9,7,8,2,4,1,5,3] -> bottom + print((int*) "Insert into list"); + println(); + list = initializeList(list); + list = addToList(list, 9); + list = addToList(list, 7); + list = addToList(list, 8); + list = addToList(list, 2); + list = addToList(list, 4); + list = addToList(list, 1); + list = addToList(list, 5); + list = addToList(list, 3); + printList(list); + + // Delete the first node (FIFO Linked List): + // top -> [2,4,1,5,3] -> bottom + print((int*) "Delete first Node"); + println(); + list = deleteFirstNodeFromList(list); //9 + list = deleteFirstNodeFromList(list); //7 + list = deleteFirstNodeFromList(list); //8 + list = deleteFirstNodeFromList(list); //2 + list = deleteFirstNodeFromList(list); //4 + list = deleteFirstNodeFromList(list); //1 + list = deleteFirstNodeFromList(list); //5 + list = deleteFirstNodeFromList(list); //3 + printList(list); + + // Sorting the list + // top -> [5,4,3,2,1] -> bottom + print((int*) "Sorting the List"); + println(); + list = sortList(list); + printList(list); + + exit(0); +} + +// ------------------------ DATA STRUCTURE FOR A PAGE TABLE ENTRY ----------------------- +// Creating a new Page table entry with physical Address and virtual Address. +int* create_page_table_entry(int* physical_address, int* virtual_address){ + //initialization of the process + int* page_table_entry; + //memory allocation + page_table_entry = malloc (2 * 4); + + //initalization of the argments of the process + *page_table_entry = (int) physical_address; + *(page_table_entry+1) = (int) virtual_address; + + return page_table_entry; +} + +// partition the emulated memory (like physical memory on a real machine) into 4KB +// frames +// ------------------------ Frame Table ---------------------------------------- +void create_frame_table(){ + + int i; + int* address; + int* Buffer; + int number_of_frames; + + i = 0; + + Buffer = (int*)malloc(4*10); + + number_of_frames = memorySize / FRAME_SIZE; + + frame_table = initializeList(frame_table); + + while(i < number_of_frames){ + address = (int*) (i * FRAME_SIZE); + frame_table = addToList(frame_table, (int) address); + print((int*) "Frame number"); + println(); + print(itoa(i, Buffer, 10, 0, 0)); + println(); + print((int*) "Frame address"); + println(); + print(itoa((int)address, Buffer, 10, 0, 0)); + println(); + i = i + 1; + } +} + +// Virtual address space is organised in 4KB pages +// ------------------------ Page Table ---------------------------------------- +int* create_page_table(int* page_table){ + + int number_of_pages; + + number_of_pages = virtual_memory_size / PAGE_SIZE; + + page_table = initializeList(page_table); + + return page_table; +} + + +// ------------------------ DATA STRUCTURE FOR A PROCESS ----------------------- +// Creating a new Process with Process ID (new_pid), Programm Counter (new_pc), +// Address to the Register (new_reg), Address to the Memory (new_mem), +// hi register for multiplication/division (new_reg_hi) and +// lo register for multiplication/division (new_reg_lo) and +int* create_process(int new_pid, int* new_reg, int new_reg_hi, int new_reg_lo){ + //initialization of the process + int* process; + int* start; + int* page_table; + int* virtual_memory; + int* Buffer; + Buffer = (int*)malloc(4*10); + + if(new_pid == 0){ + + process = malloc (6 * 4); + + //initalization of the arugments of the process + *process = new_pid; + *(process+1) = 0; + *(process+2) = (int) new_reg; + *(process+3) = * memory; + *(process+4) = new_reg_hi; + *(process+5) = new_reg_lo; + + return process; + } + else{ + + process = malloc (7 * 4); + virtual_memory = malloc(virtual_memory_size); + + print((int*) "Virtual Memory"); + println(); + print(itoa((int)virtual_memory, Buffer, 10, 0, 0)); + println(); + print((int*) "Virtual Memory Size"); + println(); + print(itoa(virtual_memory_size, Buffer, 10, 0, 0)); + println(); + + page_table = create_page_table(page_table); + + //initalization of the argments of the process + *process = new_pid; + *(process+1) = 0; + *(process+2) = (int) new_reg; + //each process gets a 4MB virtual address space. + *(process+3) = * virtual_memory; + *(process+4) = new_reg_hi; + *(process+5) = new_reg_lo; + *(process+6) = (int) page_table; + + return process; + } +} + +void schedule_and_switch(){ + int size; + int *node; + size = sizeOfList(ready_queue); + //if the ready queue is empty, the running process can continue + if(size == 0){ + print((int*) "empty---------"); + println(); + return; + } + //else the processes have to be switched so that the next process from the ready queue is allowed to run + else{ + // 1. Saving the states of the running process in the ready queue + ready_queue = addToList(ready_queue, (int) running_process); + // 2. Switching the running process and get the first of the ready queue + node = (int*) getNodeFromList(ready_queue, size); + running_process = (int*) *(node+1); + + // 3. Delete the first Process from ready queue because it is the running process + ready_queue = deleteFirstNodeFromList(ready_queue); + } +} + +// ------------------------ READY QUEUE ---------------------------------------- +// Creating a Ready queue with n processes and with m as number of instructions +void create_ready_queue(int n, int m){ + int *new_process; + int pid; + int *new_reg; + + numb_of_instr = m; + pid = 1; + ready_queue = initializeList(ready_queue); + running_process_id = 0; + + while(pid < n){ + new_reg = malloc(4*32); + new_process = create_process(pid, new_reg, reg_hi, reg_lo); + ready_queue = addToList(ready_queue, (int) new_process); + pid = pid + 1; + } +} + +void emulate(int argc, int *argv) { + print(selfieName); + print((int*) ": this is selfie's mipster executing "); + print(binaryName); + print((int*) " with "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0, 0)); + print((int*) "MB of memory"); + println(); + + interpret = 1; + + copyBinaryToMemory(); + + resetInterpreter(); + + *(registers+REG_SP) = memorySize - 4; // initialize stack pointer + + *(registers+REG_GP) = binaryLength; // initialize global pointer + + *(registers+REG_K1) = *(registers+REG_GP); // initialize bump pointer + + up_copyArguments(argc, argv); + + //run(argc, (int*) argv); + kOS(argc, (int*) argv); + + print(selfieName); + print((int*) ": this is selfie's mipster terminating "); + print(binaryName); + println(); + + print(selfieName); + print((int*) ": profile: total,max(ratio%)@addr(line#),2max(ratio%)@addr(line#),3max(ratio%)@addr(line#)"); + println(); + printProfile((int*) ": calls: ", calls, callsPerAddress); + printProfile((int*) ": loops: ", loops, loopsPerAddress); + printProfile((int*) ": loads: ", loads, loadsPerAddress); + printProfile((int*) ": stores: ", stores, storesPerAddress); } // ----------------------------------------------------------------- // ----------------------------- MAIN ------------------------------ // ----------------------------------------------------------------- -int* copyC2CStarString(int* s) { - int l; - int *r; - int i; +int selfie(int argc, int* argv) { + if (argc < 2) + return -1; + else { + while (argc >= 2) { + if (stringCompare((int*) *argv, (int*) "-c")) { + sourceName = (int*) *(argv+1); + binaryName = sourceName; + + argc = argc - 2; + argv = argv + 2; + + compile(); + } else if (stringCompare((int*) *argv, (int*) "-o")) { + binaryName = (int*) *(argv+1); + + argc = argc - 2; + argv = argv + 2; + + if (binaryLength > 0) + emit(); + else { + print(selfieName); + print((int*) ": nothing to emit to output file "); + print(binaryName); + println(); + } + } else if (stringCompare((int*) *argv, (int*) "-s")) { + assemblyName = (int*) *(argv+1); - l = CStringLength(s); + argc = argc - 2; + argv = argv + 2; - r = malloc((l + 1) * 4); + if (binaryLength > 0) { + initMemory(binaryLength); - i = 0; + disassemble(argc, (int*) argv); + } else { + print(selfieName); + print((int*) ": nothing to disassemble to output file "); + print(assemblyName); + println(); + } + } else if (stringCompare((int*) *argv, (int*) "-l")) { + binaryName = (int*) *(argv+1); - while (i <= l) { - *(r+i) = rightShift(leftShift(*s, 24 - (i % 4) * 8), 24); + argc = argc - 2; + argv = argv + 2; - i = i + 1; + load(); + } else if (stringCompare((int*) *argv, (int*) "-m")) { + initMemory(atoi((int*) *(argv+1)) * MEGABYTE); - if (i % 4 == 0) - s = s + 1; - } + argc = argc - 1; + argv = argv + 1; - return r; -} + // pass binaryName as first argument replacing size + *argv = (int) binaryName; + + if (binaryLength > 0) { + debug = 0; + booting = 1; -int* copyC2CStarArguments(int argc, int *argv) { - int *cstar_argv; - int *cursor; + emulate(argc, argv); + } else { + print(selfieName); + print((int*) ": nothing to emulate"); + println(); - cstar_argv = malloc(argc * 4); + exit(-1); + } - cursor = cstar_argv; + return 0; + } else if (stringCompare((int*) *argv, (int*) "-d")) { + initMemory(atoi((int*) *(argv+1)) * MEGABYTE); - while (argc > 0) { - *cursor = (int)copyC2CStarString((int*)*argv); + argc = argc - 1; + argv = argv + 1; - argv = argv + 1; - cursor = cursor + 1; - argc = argc - 1; + // pass binaryName as first argument replacing size + *argv = (int) binaryName; + + if (binaryLength > 0) { + debug = 1; + + emulate(argc, argv); + } else { + print(selfieName); + print((int*) ": nothing to debug"); + println(); + + exit(-1); + } + + return 0; + } else if (stringCompare((int*) *argv, (int*) "-k")) { + initMemory(atoi((int*) *(argv+1)) * MEGABYTE); + + argc = argc - 1; + argv = argv + 1; + booting = 1; + kOS(argc, (int*) argv); + + return 0; + } else if (stringCompare((int*) *argv, (int*) "-t")) { + argc = argc - 1; + argv = argv + 1; + + testList(); + + return 0; + } else + return -1; + } } - return cstar_argv; + return 0; } int main(int argc, int *argv) { - int *cstar_argv; - int *firstParameter; - initLibrary(); + initLibrary(); + initScanner(); initRegister(); initDecoder(); - initSyscalls(); - cstar_argv = copyC2CStarArguments(argc, argv); + initInterpreter(); - if (argc > 1) { - firstParameter = (int*) (*(cstar_argv+1)); + ticks = 1000000000; + number_of_processes = 16; - if (*firstParameter == '-') { - if (*(firstParameter+1) == 'c') - main_compiler(); - else if (*(firstParameter+1) == 'm') { - if (argc > 3) - main_emulator(argc, argv, cstar_argv); - else - exit(-1); - } - else { - exit(-1); - } - } else { - exit(-1); - } - } else - // default: compiler - main_compiler(); + selfieName = (int*) *argv; + + argc = argc - 1; + argv = argv + 1; + + if (selfie(argc, (int*) argv) != 0) { + print(selfieName); + print((int*) ": usage: selfie { -c source | -o binary | -s assembly | -l binary } [ -m size ... | -d size ... | -k size ... ] "); + println(); + } }