diff --git a/AUTHORS b/AUTHORS index f8c27e6..8629a2f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,4 +2,5 @@ Martin Aigner Christian Barthel Christoph Kirsch Michael Lippautz -Simone Oblasser \ No newline at end of file +Simone Oblasser +Dalmir Hasic \ No newline at end of file diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index bc43d2f..d2b26f4 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ You can enable verbose debugging with variables set in `selfie.c`: ### On Mac OS X / 64-bit Linux -On Mac OS X as well as on 64-bit Linux (requires gcc-multiarch. On Ubuntu, install gcc-multilib), you may use the following command to compile `selfie.c`: +On Mac OS X as well as on 64-bit Linux (requires gcc-multiarch or, on Ubuntu, gcc-multilib), you may use the following command to compile `selfie.c`: ```bash clang -w -m32 -D'main(a, b)=main(int argc, char **argv)' -o selfie selfie.c @@ -105,4 +105,4 @@ clang -w -m32 -D'main(a, b)=main(int argc, char **argv)' -o selfie selfie.c After that, you can proceed with the same commands as for 32-bit Linux. -The `-w` option suppresses warnings that can be ignored for now. The `-m32` option makes the compiler generate a 32-bit executable. Selfie only supports 32-bit architectures right now. The `-D` option is needed to bootstrap the main function declaration. The `char` data type is not available in C\* but required by `clang`. +The `-w` option suppresses warnings that can be ignored for now. The `-m32` option makes the compiler generate a 32-bit executable. Selfie only supports 32-bit architectures right now. The `-D` option is needed to bootstrap the main function declaration. The `char` data type is not available in C\* but required by `clang`. \ No newline at end of file diff --git a/WithPaging.txt b/WithPaging.txt new file mode 100644 index 0000000..4aadf5f Binary files /dev/null and b/WithPaging.txt differ diff --git a/WithoutPaging.txt b/WithoutPaging.txt new file mode 100644 index 0000000..15aec13 Binary files /dev/null and b/WithoutPaging.txt differ diff --git a/list.c b/list.c new file mode 100644 index 0000000..74f8efd --- /dev/null +++ b/list.c @@ -0,0 +1,345 @@ +int main(); +int *string_buffer; +int CHAR_LF; +int CHAR_TAB; +int CHAR_CR; +int INT_MIN; +int INT_MAX; +int result; +int *power_of_two_table; + + + +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 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); + + +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) { + + *(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; +} + +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) { + + assignString(string_buffer, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + + print(string_buffer); +} + +void print(int *s) { + while (*s != 0) { + putchar(*s); + s = s + 1; + } +} + +int stringLength(int *s) { + int i; + + i = 0; + + while (*(s+i) != 0) + i = i + 1; + + return i; +} + +void reverseString(int *s) { + int tmp; + int i; + int j; + + i = 0; + j = stringLength(s) - 1; + + while (i < j) { + tmp = *(s+i); + *(s+i) = *(s+j); + *(s+j) = tmp; + i = i + 1; + j = j - 1; + } +} + +int* itoa(int n, int *s, int b, int a) { + // assert: b in {2,4,8,10,16} + + int i; + int sign; + + i = 0; + + sign = 0; + + if (n == 0) { + *s = '0'; + + i = 1; + } else if (n < 0) { + sign = 1; + + if (b == 10) { + if (n == INT_MIN) { + *s = '8'; // rightmost decimal digit of 32-bit INT_MIN + + n = -(n / 10); + i = i + 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + *s = '0'; // rightmost non-decimal digit of INT_MIN + + n = (rightShift(INT_MIN, 1) / b) * 2; + i = i + 1; + } else + n = rightShift(leftShift(n, 1), 1); + } + } + + while (n != 0) { + *(s+i) = n % b; + + if (*(s+i) > 9) + *(s+i) = *(s+i) - 10 + 'A'; + else + *(s+i) = *(s+i) + '0'; + + n = n / b; + i = i + 1; + + if (i == 1) { + if (sign) { + if (b != 10) + n = n + (rightShift(INT_MIN, 1) / b) * 2; + } + } + } + + if (b != 10) { + while (i < a) { + *(s+i) = '0'; // align with zeros + + i = i + 1; + } + } else if (sign) { + *(s+i) = '-'; + + i = i + 1; + } + + *(s+i) = 0; // null terminated string + + reverseString(s); + + return s; +} + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + + +void init (){ + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + 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 + + string_buffer = malloc(33*4); + + +} + + +int * insert(int data, int * head){ + int * adr; + + adr = (int*)malloc (2*4); + *adr = data; + *(adr+1) = head; + + return adr; + +} + +void printList(int*head){ + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + while ((int)(head) != 0){ + print(itoa(*(head),number_buffer,10,0)); + putchar(CHAR_LF); + head = *(head+1); + } +} + +void sortList(int *head){ + int i; + int j; + int help; + int* temp; + + i = 0; + j = 0; + + while(*(head+1) != 0){ + + temp = *(head+1); + + while((int)(temp) != 0){ + + if(*(head) < *(temp)){ + help = *(temp); + *temp = *head; + *head = help; + } + + temp = *(temp+1); + } + + head = *(head+1); + } +} + +void remove(int data, int * head){ + int* current; + int* previous; + int* help; + + current = head; + previous = 0; + + if(*(current) == data){ + help = *(current+1); + *current = *help; + *(current+1) = *(help+1); + } + else{ + while((int)current != 0){ + if(*(current) == data){ + *(previous+1) =(int*)(*(current+1)); + current = 0; + } + else{ + previous = current; + current = *(current+1); + } + } + } +} + + + +int main(){ + int* head; + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + init(); + + //inserting + head = insert(7,head); + head = insert(8,head); + head = insert(3,head); + head = insert(6,head); + head = insert(9,head); + head = insert(16,head); + head = insert(18,head); + head = insert(50,head); + head = insert(42,head); + head = insert(31,head); + head = insert(39,head); + head = insert(29,head); + head = insert(13,head); + head = insert(0,head); + head = insert(72,head); + head = insert(51,head); + + //printing + putchar(CHAR_LF); + printString('O','r','i','g','i','n','a','l',' ','L','i','s','t',' ',0,0,0,0,0,0); + putchar(CHAR_LF); + printList(head); + putchar(CHAR_LF); + + //removing 9, inserting 4 + remove(9,head); + head = insert(4,head); + + //printing + printString('R','e','m','o','v','e','d',' ','9',' ','I','n','s','e','r','t','e','d',' ','4'); + putchar(CHAR_LF); + printList(head); + + //sorting + sortList(head); + + + //printing + putchar(CHAR_LF); + printString('S','o','r','t','e','d',' ','L','i','s','t',' ',0,0,0,0,0,0,0,0); + putchar(CHAR_LF); + printList(head); + + exit(0); +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..3aa6522 --- /dev/null +++ b/makefile @@ -0,0 +1,21 @@ +CFLAGS=-O3 -Wall + +PROGRAMS=selfie + + +default: compile run + +compile: + -rm -r $ test.mips + -touch out + ./selfie -c < test.c + -mv out test.mips + -touch out + ./selfie -c < selfie.c + -mv out selfie.mips + -touch out + ./selfie -c < selfieProducerConsumer.c + -mv out producerConsumer.mips + +run: + ./selfie -m 32 test.mips diff --git a/selfie.c b/selfie.c index c2b5d87..1cb922a 100755 --- a/selfie.c +++ b/selfie.c @@ -80,39 +80,53 @@ 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); + 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 *string_buffer; // ------------------------- INITIALIZATION ------------------------ @@ -136,11 +150,8 @@ 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 - - string_buffer = malloc(33*4); + // accommodate 32-bit numbers for itoa + string_buffer = malloc(33); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -155,342 +166,160 @@ void initLibrary() { void initScanner(); -int findNextCharacter(); +void printSymbol(int symbol); +void printLineNumber(int* message); + +void syntaxErrorMessage(int *message); +void syntaxErrorCharacter(int character); + 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); - // ------------------------ 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 = 64; // 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 - -// ------------------------- 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); +int lineNumber = 1; // current Line Number for error reporting - // ------------ "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); +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 - // ------------ "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); +int constant = 0; // stores numerical value of scanned integer or character - // ------------ "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); +int initialValue = 0; // stores initial value of variable definitions - // ------------ "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); +int mayBeINTMINConstant = 0; // support INT_MIN constant +int isINTMINConstant = 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); +int character; // most recently read character +int symbol; // most recently recognized symbol - // ------------ "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); +// ------------------------- INITIALIZATION ------------------------ - // ------------ "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); +void initScanner () { + 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"; - lineNumber = 1; character = getchar(); - symbol = -1; - - identifier = 0; - integer = 0; - - ivalue = 0; - - mayBeINTMINConstant = 0; + symbol = SYM_EOF; } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void initSymbolTable(); - -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; - -// ------------------------- 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; -} +// table pointers +int *global_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; // ----------------------------------------------------------------- // ---------------------------- PARSER ----------------------------- @@ -499,25 +328,31 @@ void initSymbolTable() { void initParser(); int isNotRbraceOrEOF(); -int isVariableOrProcedure(); int isExpression(); -int isPlusOrMinus(); int isStarOrDivOrModulo(); +int isPlusOrMinus(); +int isComparison(); + +int lookForFactor(); +int lookForStatement(); +int lookForType(); -int waitForStatement(); -int waitForVariable(); -int waitForFactor(); +void save_temporaries(); +void restore_temporaries(int numberOfTemporaries); -void save_registers(); -void restore_registers(int numberOfRegisters); +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,36 +363,33 @@ 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; +int maxBinaryLength; // ------------------------ GLOBAL VARIABLES ----------------------- -int allocatedRegisters; // number of allocated registers -int allocatedGlobalVariables; // number of global variables +int allocatedTemporaries = 0; // number of allocated temporaries -int codeLength; -int returnBranches; -int *currentFuncName; // holds the name of currently parsed function +int allocatedMemory = 0; // number of bytes for global variables and strings + +int mainJumpAddress = 0; // address of main function +int returnBranches = 0; // fixup chain for return statements + +int *currentProcedureName = (int*) 0; // name of currently parsed procedure // ------------------------- INITIALIZATION ------------------------ void initParser() { - // set maximum code length for emitting code - maxCodeLength = 32000; - - allocatedRegisters = 0; - allocatedGlobalVariables = 0; - - codeLength = 0; - returnBranches = 0; - currentFuncName = 0; + // set maximum code length in bytes for emitting code + maxBinaryLength = twoToThePowerOf(17); } // ----------------------------------------------------------------- @@ -577,36 +409,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 +512,9 @@ int signExtend(int immediate); void initDecoder(); +void printOpcode(int opcode); +void printFunction(int function); + void decode(); void decodeRFormat(); void decodeIFormat(); @@ -639,77 +522,98 @@ 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 ----------------------------- // ----------------------------------------------------------------- -void allocateMachineMemory(int size); +void initMemory(int size, int* name); + +int tlb(int vaddr); + +int loadMemory(int vaddr); +void storeMemory(int vaddr, int data); // ------------------------ GLOBAL VARIABLES ----------------------- -int *memory; // machine memory +int *memory; +int memorySize; + +int *binaryName; +int binaryLength; + +// ------------------------- INITIALIZATION ------------------------ + +void initMemory(int size, int *name) { + memory = malloc(size); + memorySize = size; + + binaryName = name; + binaryLength = 0; +} // ----------------------------------------------------------------- // ---------------------------- BINARY ----------------------------- @@ -724,15 +628,15 @@ void fixup_relative(int fromAddress); void fixup_absolute(int fromAddress, int toAddress); void fixlink_absolute(int fromAddress, int toAddress); +int copyStringToMemory(int *s, int a); + void emitBinary(); -int loadBinary(int *filename); +void loadBinary(); // ----------------------------------------------------------------- // --------------------------- SYSCALLS ---------------------------- // ----------------------------------------------------------------- -void initSyscalls(); - void emitExit(); void syscall_exit(); @@ -753,25 +657,34 @@ void syscall_getchar(); void emitPutchar(); -// ------------------------ GLOBAL CONSTANTS ----------------------- +void emitYield(); //ADDED A2 +void syscall_yield(); //ADDED A2 -int SYSCALL_EXIT; -int SYSCALL_READ; -int SYSCALL_WRITE; -int SYSCALL_OPEN; -int SYSCALL_MALLOC; -int SYSCALL_GETCHAR; +void emitSwitch(); //ADDED A3 +void syscall_switch(); //ADDED A3 -// ------------------------- INITIALIZATION ------------------------ +void emitLock(); +void syscall_lock(); -void initSyscalls() { - SYSCALL_EXIT = 4001; - SYSCALL_READ = 4003; - SYSCALL_WRITE = 4004; - SYSCALL_OPEN = 4005; - SYSCALL_MALLOC = 5001; - SYSCALL_GETCHAR = 5002; -} +void emitUnlock(); +void syscall_unlock(); + +void emitTrap(); +void syscall_trap(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; +int SYSCALL_MALLOC = 5001; +int SYSCALL_GETCHAR = 5002; +int SYSCALL_YIELD = 5003; //ADDED A2 +int SYSCALL_SWITCH = 5004; //ADDED A3 +int SYSCALL_LOCK = 5005; //ADDED A4 +int SYSCALL_UNLOCK = 5006; //ADDED A4 +int SYSCALL_TRAP = 6007; //ADDED A4 // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -809,9 +722,9 @@ void op_teq(); void initInterpreter(); -void exception_handler(int enumber); +void printException(int enumber); -int addressTranslation(int vaddr); +void exception_handler(int enumber); void pre_debug(); void post_debug(); @@ -820,124 +733,198 @@ void fetch(); void execute(); void run(); -void debug_boot(int memorySize); -int* parse_args(int argc, int *argv, int *cstar_argv); +void parse_args(int argc, int *argv); + void up_push(int value); int up_malloc(int size); -int up_copyCString(int *s); void up_copyArguments(int argc, int *argv); -int main_emulator(int argc, int *argv, int *cstar_argv); +int main_emulator(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_load = 0; + +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; +int debug_getchar = 0; + +int debug_registers = 0; +int debug_disassemble = 0; -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 reg_hi; // hi register for multiplication/division -int reg_lo; // lo register for multiplication/division + +// -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- + +void push(int *mem, int *reg, int reg_hi, int reg_lo, int pc,int pId,int *segment,int gp, int sp, int k1,int *pageTable, int *head); + +void setPrcosessNext(int *process, int *next); +void setProcessPc(int * process, int pc); +void setProcessMemory(int *process, int *memory); +void setProcessRegisters(int *process, int *registers); +void setProcessRegHi(int *process, int reg_hi); +void setProcessRegLo(int *process, int reg_lo); +void setProcessId (int *process, int pId); +void setProcessSegPointer(int *process, int *segment); +void setProcessGlobalP(int *process, int gp); +void setProcessStackP(int *process, int sp); +void setProcessK1(int *process,int kp); +void setProcessPageTable(int *process, int *pageTable); + + +int* getProcessNext(int *process); +int getProcessPc(int *process); +int* getProcessMemory(int *process); +int* getProcessRegisters(int *process); +int getProcessRegHi(int *process); +int getProcessRegLo(int *process); +int getProcessId(int *process); +int* getProcessSegPointer(int *process); +int getProcessGlobalP(int *process); +int getProcessStackP(int *process); +int getProcessK1(int *process); +int getProcessPageTable(int *process); + + +void createProcessList(int numberoOfProcesses); +void createProcess(int *head, int pId); +void memCopy(int *oldMemory, int *newMemory, int length); + +int * insertSegment(int pId, int start, int size, int *head); + +void setSegmentId(int *segment, int pId); +void setSegmentNext(int *segment, int *next); +void setSegmentStart(int *segment, int start); +void setSegmentSize(int *segment, int size); + +int* getSegmentNext(int *segment); +int getSegmentId(int *segment); +int getSegmentStart(int *segment); +int getSegmentSize(int *segment); + +int* pop(int *head); +void scheduler(); + +// ------------------ADDITIONAL GLOBAL VARIABLES A1 -------------- + +int *readyqueue = 0; +int memSize; +int numberofInstructions = 0; + +// ------------------ADDITIONAL GLOBAL VARIABLES A2--------------- +int *process = 0; +int *segmentTable = 0; +int segPointer = 0; +//int segSize = 2097152; +int segSize = 4194304; +int communicationSegment = 1048576; //adress for the second segment 1048576*4 +int segmentStart = 0; //this variable is initalized when scheduler is called + // so that it doesn't have to be computed every time + // tlb is called + +// ----------------- ASSIGNMENT 3 -------------------------------- +int main_os(); +int interruptOccured = 0; +int processTable = 0; +void insertInProcessTable(int *process, int gp, int sp,int*head); + + +void setProcessTableNext(int *processEntry, int *next); +void setProcessTableProcess(int *processEntry, int *process); +void setProcessTableGp(int *processEntry, int gp); +void setProcessTableSp(int *processEntry, int sp); +int *getProcessTableNext(int *processEntry); +int *getProcessTableProcess(int *processEntry); +int getProcessTableGp(int *processEntry); +int getProcessTableSp(int *processEntry); + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segstart,int gp,int sp,int k1); +void restoreKernelState(); +int tlb_debug = 0; +void loadProcess(int * name, int id); + +// ------------------ ASSIGNMENT 4 ------------------------------- + +void interpretEnvent(); +int processLock = 0; + +// ------------------ ASSIGNMENT 5 ------------------------------- + +void printMemory(int *memory, int length, int from); +int palloc(int adr); +int searchPageTable(int adr); +void turnOnPaging(); +int getNextFrame(); + +int *pageTable = 0; +int *freeList = 0; +int *realMemory; +int *virtualMemory; +int freeListPointer = 1; +int pagingFlag = 0; //paging turned off + +// --------------------ASSIGNEMNT 6+7 ------------------------------- + +int *getPageTableStart(int pID); +int pageFault = 0; +void checkPageFault(int vaddr); +int freeListKernel = 0; +int flag = 0; +int pageTableAdress = 0; +int counterRun = 0; +int loadFlag = 0; + +// -------------------ASSIGNMENT 8 -------------------------------- + +int *queue_t; +int *q_tail; +int *q_head; +int mc_bump = 0; +int firstInsertFlag = 1; + +void init_mcqueue(); +void mc_enqueue(int *queue_t, int value); +void mc_decueue(int *queue_t, int * value); +int * init_node(int *queue_t, int value); +void print_mc_queue(int *queue_t); +int CAS(int * node, int old, int new); +void create_thread(int pId); // ------------------------- 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); - - pc = 0; - ir = 0; - - reg_hi = 0; - reg_lo = 0; + 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); + } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -977,56 +964,85 @@ int rightShift(int n, int b) { (INT_MAX / twoToThePowerOf(b) + 1); } +int getCharacter(int *s, int i) { + // assert: i >= 0 + int a; + + a = i / 4; + + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); +} + +int* putCharacter(int *s, int i, int c) { + // assert: i >= 0, all characters are 7-bit + int a; + + a = i / 4; + + *(s + a) = (*(s + a) - leftShift(getCharacter(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 (getCharacter(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 = getCharacter(s, i); + + putCharacter(s, i, getCharacter(s, j)); + putCharacter(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 (getCharacter(s, i) == 0) + if (getCharacter(t, i) == 0) return 1; else return 0; - else if (*s == *t) { - s = s + 1; - t = t + 1; - } else + else if (getCharacter(s, i) == getCharacter(t, i)) + i = i + 1; + else return 0; } -int atoi(int* s) { +int atoi(int *s) { + int i; int n; + i = 0; + n = 0; - while (*s != 0) { - n = n * 10 + *s - '0'; - s = s + 1; + while (getCharacter(s, i) != 0) { + n = n * 10 + getCharacter(s, i) - '0'; + + i = i + 1; } return n; @@ -1043,7 +1059,7 @@ int* itoa(int n, int *s, int b, int a) { sign = 0; if (n == 0) { - *s = '0'; + putCharacter(s, 0, '0'); i = 1; } else if (n < 0) { @@ -1051,7 +1067,8 @@ 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 + putCharacter(s, 0, '8'); n = -(n / 10); i = i + 1; @@ -1059,7 +1076,8 @@ int* itoa(int n, int *s, int b, int a) { n = -n; } else { if (n == INT_MIN) { - *s = '0'; // rightmost non-decimal digit of INT_MIN + // rightmost non-decimal digit of INT_MIN + putCharacter(s, 0, '0'); n = (rightShift(INT_MIN, 1) / b) * 2; i = i + 1; @@ -1069,12 +1087,10 @@ int* itoa(int n, int *s, int b, int a) { } while (n != 0) { - *(s+i) = n % b; - - if (*(s+i) > 9) - *(s+i) = *(s+i) - 10 + 'A'; + if (n % b > 9) + putCharacter(s, i, n % b - 10 + 'A'); else - *(s+i) = *(s+i) + '0'; + putCharacter(s, i, n % b + '0'); n = n / b; i = i + 1; @@ -1089,70 +1105,69 @@ int* itoa(int n, int *s, int b, int a) { if (b != 10) { while (i < a) { - *(s+i) = '0'; // align with zeros + putCharacter(s, i, '0'); // align with zeros i = i + 1; } + + if (b == 16) { + putCharacter(s, i, 'x'); + putCharacter(s, i + 1, '0'); + + i = i + 2; + } } else if (sign) { - *(s+i) = '-'; + putCharacter(s, i, '-'); i = i + 1; } - *(s+i) = 0; // null terminated string + putCharacter(s, i, 0); // null terminated string - reverseString(s); + stringReverse(s); return s; } void print(int *s) { - while (*s != 0) { - putchar(*s); - s = s + 1; - } -} + int i; -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) { + i = 0; - *(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; -} + while (getCharacter(s, i) != 0) { + putchar(getCharacter(s, i)); -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; + i = i + 1; + } +} - 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; +void println() { + putchar(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) { + putchar(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 + putchar(character); - print(string_buffer); + putchar(CHAR_SINGLEQUOTE); } -void memset(int *a, int size, int v) { - while (size > 0) { - size = size - 1; - *(a+size) = v; - } +void printString(int *s) { + putchar(CHAR_DOUBLEQUOTE); + + print(s); + + putchar(CHAR_DOUBLEQUOTE); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -1165,6 +1180,58 @@ void memset(int *a, int size, int v) { // ---------------------------- SCANNER ---------------------------- // ----------------------------------------------------------------- +void printSymbol(int symbol) { + putchar(CHAR_DOUBLEQUOTE); + + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); + + putchar(CHAR_DOUBLEQUOTE); +} + +void printLineNumber(int* message) { + print((int*) "cstarc: "); + print(message); + print((int*) " in line "); + print(itoa(lineNumber, string_buffer, 10, 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(); +} + +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; @@ -1178,7 +1245,7 @@ int findNextCharacter() { inComment = 0; else if (character == CHAR_CR) inComment = 0; - else if (character == SYM_EOF) + else if (character == CHAR_EOF) return character; } else if (isCharacterWhitespace()) { @@ -1189,13 +1256,13 @@ int findNextCharacter() { character = getchar(); - } else if (character == '#') { + } else if (character == CHAR_HASH) { character = getchar(); inComment = 1; - } else if (character == '/') { + } else if (character == CHAR_SLASH) { character = getchar(); - if (character == '/') + if (character == CHAR_SLASH) inComment = 1; else { symbol = SYM_DIV; @@ -1207,26 +1274,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 +1299,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 +1345,243 @@ 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; + + putCharacter(identifier, i, character); + i = i + 1; + character = getchar(); } - *(identifier+i) = 0; // null terminated string + putCharacter(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; + + putCharacter(integer, i, character); + i = i + 1; + character = getchar(); } - *(integer+i) = 0; // null terminated string - ivalue = atoi(integer); + putCharacter(integer, i, 0); // null terminated string + + constant = atoi(integer); - if (ivalue < 0) { - if (ivalue == INT_MIN) { - if (mayBeINTMINConstant == 0) { - syntaxError(ERR_WRAPAROUND); + 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 == ';') { + } else if (character == CHAR_SINGLEQUOTE) { character = getchar(); - symbol = SYM_SEMICOLON; - } else if (character == '+') { - character = getchar(); - symbol = SYM_PLUS; + constant = 0; - } else if (character == '-') { - character = getchar(); - symbol = SYM_MINUS; + if (character == CHAR_EOF) { + syntaxErrorMessage((int*) "reached end of file looking for a character constant"); - } else if (character == '*') { - character = getchar(); - symbol = SYM_ASTERISK; + exit(-1); + } else + constant = character; - } else if (character == '=') { character = getchar(); - if (character == '=') { + + if (character == CHAR_SINGLEQUOTE) character = getchar(); - symbol = SYM_EQUAL; + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + exit(-1); } else - symbol = SYM_ASSIGN; + syntaxErrorCharacter(CHAR_SINGLEQUOTE); - } else if (character == '(') { - character = getchar(); - symbol = SYM_LPARENTHESIS; + symbol = SYM_CHARACTER; - } else if (character == ')') { + } else if (character == CHAR_DOUBLEQUOTE) { character = getchar(); - symbol = SYM_RPARENTHESIS; - } else if (character == '{') { - character = getchar(); - symbol = SYM_LBRACE; + string = malloc(maxStringLength + 1); - } else if (character == '}') { - character = getchar(); - symbol = SYM_RBRACE; + i = 0; - } else if (character == ',') { - character = getchar(); - symbol = SYM_COMMA; + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } - } else if (character == '<') { - character = getchar(); - if (character == '=') { + putCharacter(string, i, character); + + i = i + 1; + character = getchar(); - symbol = SYM_LEQ; - } else - symbol = SYM_LT; + } - } else if (character == '>') { - character = getchar(); - if (character == '=') { + if (character == CHAR_DOUBLEQUOTE) character = getchar(); - symbol = SYM_GEQ; - } else - symbol = SYM_GT; + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); - } else if (character == '!') { + exit(-1); + } + + putCharacter(string, i, 0); // null terminated string + + symbol = SYM_STRING; + + } else if (character == CHAR_SEMICOLON) { character = getchar(); - if (character == '=') { - character = getchar(); - symbol = SYM_NOTEQ; - } else - syntaxError(ERR_UNKNOWN); + symbol = SYM_SEMICOLON; - } else if (character == '%') { + } else if (character == CHAR_PLUS) { character = getchar(); - symbol = SYM_MOD; + symbol = SYM_PLUS; + + } else if (character == CHAR_DASH) { + character = getchar(); + symbol = SYM_MINUS; - } else if (character == 39) { // ' + } else if (character == CHAR_ASTERISK) { character = getchar(); - ivalue = character; // any ascii character + symbol = SYM_ASTERISK; + + } else if (character == CHAR_EQUAL) { character = getchar(); - if (character == 39) { // ' + if (character == CHAR_EQUAL) { character = getchar(); - symbol = SYM_CHARACTER; + symbol = SYM_EQUALITY; } 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); + symbol = SYM_ASSIGN; - print(warning); + } else if (character == CHAR_LPARENTHESIS) { + character = getchar(); + symbol = SYM_LPARENTHESIS; - print((int*)(*(stringArray+errCode))); + } else if (character == CHAR_RPARENTHESIS) { + character = getchar(); + symbol = SYM_RPARENTHESIS; - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); + } else if (character == CHAR_LBRACE) { + character = getchar(); + symbol = SYM_LBRACE; - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + } else if (character == CHAR_RBRACE) { + character = getchar(); + symbol = SYM_RBRACE; - print(errNewline); -} + } else if (character == CHAR_COMMA) { + character = getchar(); + symbol = SYM_COMMA; -void syntaxError(int errCode) { - int *numberBuffer; + } else if (character == CHAR_LT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_LEQ; + } else + symbol = SYM_LT; - numberBuffer = (int*)malloc(4*10); + } else if (character == CHAR_GT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_GEQ; + } else + symbol = SYM_GT; - print(error); + } else if (character == CHAR_EXCLAMATION) { + character = getchar(); + if (character == CHAR_EQUAL) + character = getchar(); + else + syntaxErrorCharacter(CHAR_EQUAL); - print((int*)(*(stringArray+errCode))); + symbol = SYM_NOTEQ; - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); + } else if (character == CHAR_PERCENTAGE) { + character = getchar(); + symbol = SYM_MOD; - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + } else { + printLineNumber((int*) "error"); + print((int*) "found unknown character "); + printCharacter(character); + + 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 +1592,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 +1627,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 +1657,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 +1670,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 +1689,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 +1717,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 +1762,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 +1779,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 +1790,142 @@ 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"); + + exit(-1); + } +} + +int currentTemporary() { + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int previousTemporary() { + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int nextTemporary() { + if (allocatedTemporaries < REG_T9 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); + + exit(-1); + } +} - allocatedRegisters = allocatedRegisters - 1; +void tfree(int numberOfTemporaries) { + allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; + + if (allocatedTemporaries < 0) { + syntaxErrorMessage((int*) "illegal register deallocation"); + + exit(-1); } } -void restore_registers(int numberOfRegisters) { +void save_temporaries() { + while (allocatedTemporaries > 0) { + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } +} - while (allocatedRegisters < numberOfRegisters) { - allocatedRegisters = allocatedRegisters + 1; +void restore_temporaries(int numberOfTemporaries) { + while (allocatedTemporaries < numberOfTemporaries) { + talloc(); - emitIFormat(OP_LW, REG_SP, allocatedRegisters, 0); + 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; + int *entry; - entry = getSymbolTableEntry(variable, local_symbol_table); + entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); - if ((int)entry == 0) { - entry = getSymbolTableEntry(variable, global_symbol_table); + if (entry == (int*) 0) { + entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); - if ((int)entry == 0) - syntaxError(ERR_UNDECLARED_VARIABLE); + if (entry == (int*) 0) { + printLineNumber((int*) "error"); + + print(variable); + + print((int*) " undeclared"); + println(); + + exit(-1); + } } return entry; @@ -1704,68 +1936,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 +2018,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(loadMemory(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 - cast = 0; // turn off cast by default + hasCast = 0; - while (waitForFactor()) - syntaxError(ERR_IDENT_OR_CONST_OR_EXP); + type = INT_T; + + 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 +2195,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 +2210,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 +2228,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; + talloc(); - allocatedRegisters = allocatedRegisters + 1; - - 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); - - } else if (symbol == SYM_DIV) { - getSymbol(); - rtype = gr_factor(); + operatorSymbol = symbol; + getSymbol(); - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFLO); + rtype = gr_factor(); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + // assert: allocatedTemporaries == n + 2 + + 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 +2336,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); - - } else if (symbol == SYM_GT) { - getSymbol(); - rtype = gr_simpleExpression(); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); - // assert: allocatedRegisters == n + 2 + tfree(1); - 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(); - - // assert: allocatedRegisters == n + 2 + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); - 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 +2502,92 @@ void gr_while() { int brBackToWhile; int brForwardToEnd; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 - brBackToWhile = codeLength; + brBackToWhile = binaryLength; + + 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, 0, 0, (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 +2597,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,7 +2612,7 @@ void gr_if() { getSymbol(); // if the "if" case was true, we jump to the end - brForwardToEnd = codeLength; + brForwardToEnd = binaryLength; emitIFormat(OP_BEQ, 0, 0, 0); // if the "if" case was not true, we jump here @@ -2374,13 +2621,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 +2643,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(); - emitIFormat(OP_SW, allocatedRegisters-1, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 2; + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + 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 +2789,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 +2825,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 +2849,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(loadMemory(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,86 +3059,83 @@ 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(); + } + + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; getSymbol(); - if (symbol == SYM_ASTERISK) { - type = INTSTAR_T; + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + getSymbol(); - } + + gr_procedure(variableOrProcedureName, type); + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - // type identifier, this means it is a global variable - if (symbol == SYM_SEMICOLON) { - getSymbol(); + // type identifier "(" procedure declaration or definition + if (symbol == SYM_LPARENTHESIS) + gr_procedure(variableOrProcedureName, type); + else { + allocatedMemory = allocatedMemory + 4; - offset = allocatedGlobalVariables * (-4); + // type identifier ";" global variable declaration + if (symbol == SYM_SEMICOLON) { + getSymbol(); - createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, offset, VARIABLE, type); + createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, -allocatedMemory, VARIABLE, type, 0); - allocatedGlobalVariables = allocatedGlobalVariables + 1; + // type identifier "=" global variable definition + } else + gr_initialization(variableOrProcedureName, -allocatedMemory, type); } - // type identifier procedure - else - gr_procedure(variableOrProcedureName, type); } else - syntaxError(ERR_IDENTIFIER); - - // void identifier procedure - } else if (symbol == SYM_VOID) { - type = VOID_T; - getSymbol(); - - if (symbol == SYM_IDENTIFIER) { - variableOrProcedureName = identifier; - - getSymbol(); - - gr_procedure(variableOrProcedureName, type); - } - } else - syntaxError(ERR_PROCEDURE_OR_VARIABLE); - } - - // 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); - } -} + syntaxErrorSymbol(SYM_IDENTIFIER); + } + } +} // ----------------------------------------------------------------- // ------------------------ MACHINE CODE LIBRARY ------------------- @@ -2805,20 +3145,18 @@ 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; + // instruction at address zero cannot be fixed up + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // null page + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", binaryLength, FUNCTION, INT_T, 0); - // "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, label, codeLength, FUNCTION, INT_T); + mainJumpAddress = binaryLength; emitJFormat(OP_JAL, 0); } @@ -2829,28 +3167,40 @@ void emitMainEntry() { int main_compiler() { initScanner(); - initSymbolTable(); initParser(); - allocateMachineMemory(maxCodeLength*4); + // memory in bytes and executable file name "out" + initMemory(maxBinaryLength, (int*) "out"); getSymbol(); + // 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(); - - gr_cstar(); // invoke compiler - emitBinary(); + emitYield(); + emitSwitch(); + emitLock(); + emitUnlock(); + + // parser + gr_cstar(); + + if (getInstrIndex(loadMemory(mainJumpAddress)) != 0) + emitBinary(); + else { + print((int*) "cstarc: main function missing"); + println(); + } exit(0); } @@ -2861,6 +3211,14 @@ int main_compiler() { // ----------------------------------------------------------------- // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void printRegister(int reg) { + print((int*) *(REGISTERS + reg)); +} + // ----------------------------------------------------------------- // ---------------------------- ENCODER ---------------------------- // ----------------------------------------------------------------- @@ -2953,6 +3311,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); @@ -3018,8 +3384,114 @@ void decodeJFormat() { // ---------------------------- MEMORY ----------------------------- // ----------------------------------------------------------------- -void allocateMachineMemory(int size) { - memory = (int*)malloc(size); +int tlb(int vaddr) { + int adr; + + if (vaddr % 4 != 0) + exception_handler(EXCEPTION_ADDRESSERROR); + + //if paging is enabled and it is not kernel process + if(pagingFlag == 1){ + if(segmentStart !=0){ + adr = searchPageTable(vaddr); + return adr/4; + } + } + if(loadFlag == 1){ + adr = searchPageTable(vaddr); + return adr/4; + } + else{ + if(tlb_debug == 1){ + if(process !=0){ + print(itoa(vaddr/4, string_buffer, 10, 0)); + + print((int*)" --> "); + + vaddr = vaddr + segmentStart; + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + + else{ + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + } + else{ + if(segmentStart !=0){ + vaddr = vaddr + segmentStart; + } + } + } + // physical memory is word-addressed for lack of byte-sized data type + return vaddr / 4; +} + +int searchPageTable(int vaddr){ + int i; + int frame; + int offset; + int debugFlag = 0; + + frame = vaddr/4096; + offset = vaddr%4096; + + if(*(pageTable+frame)==0){ + pageFault == 1; + *(pageTable+frame) = freeListKernel;//freeList; + freeListKernel = freeListKernel + 4096; + + return *(pageTable+frame)+offset; + } + else{ + return *(pageTable+frame)+offset; + + } + + +} + +void checkPageFault (int vaddr){ + int frame; + int offset; + + frame = vaddr/4096; + offset = vaddr%4096; + + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(memory+communicationSegment+41) = vaddr; + } + +} + + +int loadMemory(int vaddr) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return 0; + } + } + + return *(memory + tlb(vaddr)); +} + +void storeMemory(int vaddr, int data) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return; + } + } + + *(memory + tlb(vaddr)) = data; } // ----------------------------------------------------------------- @@ -3027,12 +3499,13 @@ void allocateMachineMemory(int size) { // ----------------------------------------------------------------- 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; + storeMemory(binaryLength, instruction); + + binaryLength = binaryLength + 4; } } @@ -3070,95 +3543,111 @@ 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 = loadMemory(fromAddress); + + storeMemory(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); + storeMemory(fromAddress, + encodeJFormat(getOpcode(loadMemory(fromAddress)), toAddress / 4)); } void fixlink_absolute(int fromAddress, int toAddress) { int previousAddress; while (fromAddress != 0) { - previousAddress = getInstrIndex(*(memory + fromAddress)); + previousAddress = getInstrIndex(loadMemory(fromAddress)) * 4; fixup_absolute(fromAddress, toAddress); fromAddress = previousAddress; } } +int copyStringToMemory(int *s, int a) { + int l; + int w; + + l = stringLength(s) + 1; + + w = a + l; + + if (l % 4 != 0) + w = w + 4 - l % 4; + + while (a < w) { + storeMemory(a, *s); + + s = s + 1; + a = a + 4; + } + + return w; +} + void emitBinary() { - int i; - int *filename; + int *entry; int fd; - i = 0; + entry = global_symbol_table; - // put global variables as 0 at end of codearray - while (i < allocatedGlobalVariables) { - *(memory + codeLength) = 0; + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeMemory(binaryLength, getValue(entry)); - codeLength = codeLength + 1; + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToMemory(getString(entry), binaryLength); - i = i + 1; + entry = getNext(entry); } - filename = (int*)malloc(4*4); - *filename = 7632239; //filename: out - - // assumption: file with name "out" exists prior to execution of compiler - fd = open(filename, 1); // 1 = O_WRONLY + // assert: file with name binaryName exists prior to execution of compiler + fd = open(binaryName, 1); // 1 = O_WRONLY if (fd < 0) { - syntaxError(ERR_FILE_NOT_FOUND); + syntaxErrorMessage((int*) "output file not found"); 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); + // The mipster_syscall 4004 writes the code array into a file. + // The syscall uses the "write" system call of the OS and compiler. + // The write system call of our Linux uses little endian byte ordering. + write(fd, memory, binaryLength); } -int loadBinary(int *filename) { +void loadBinary() { int fd; - int i; - int ret; + int numberOfReadBytes; - fd = open(filename, 0); + fd = open(binaryName, 0); // 0 = O_RDONLY if (fd < 0) exit(-1); - i = 0; - - ret = 4; + numberOfReadBytes = 4; - while (ret == 4) { - ret = read(fd, memory + i, 4); + while (numberOfReadBytes == 4) { + numberOfReadBytes = read(fd, memory + tlb(binaryLength), 4); 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(binaryName); + print((int*) ": "); + print(itoa(binaryLength, string_buffer, 16, 8)); + print((int*) ": "); + print(itoa(loadMemory(binaryLength), string_buffer, 16, 8)); + println(); } - i = i + 1; + if (numberOfReadBytes == 4) + binaryLength = binaryLength + 4; } - - // Return global pointer and bump pointer for malloc - return i * 4; } // ----------------------------------------------------------------- @@ -3166,12 +3655,7 @@ 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); @@ -3189,24 +3673,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(binaryName); + print((int*) ": exiting with error code "); print(itoa(exitCode, string_buffer, 10, 0)); - putchar(CHAR_LF); + println(); exit(0); } 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 +3700,40 @@ 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); + 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(' '); + if (debug_read) { + print(binaryName); + print((int*) ": read "); print(itoa(size, string_buffer, 10, 0)); - putchar(CHAR_LF); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + 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,38 +3749,39 @@ 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)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 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); @@ -3324,41 +3795,38 @@ 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 flags; - int address; + int vaddr; int *filename; int fd; - flags = *(registers+REG_A1); - address = *(registers+REG_A0) / 4; + flags = *(registers+REG_A1); + vaddr = *(registers+REG_A0); - filename = memory + address; + filename = memory + tlb(vaddr); fd = open(filename, flags); *(registers+REG_V0) = fd; - if (debug_syscalls) { - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','o','p','e','n',' ',CHAR_TAB,0,0,0,0); - + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 10, 0)); + print((int*) " returning file descriptor "); print(itoa(fd, string_buffer, 10, 0)); - putchar(CHAR_LF); + 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); @@ -3374,11 +3842,8 @@ void emitMalloc() { 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); + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_malloc() { @@ -3388,7 +3853,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,17 +3863,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); + if (debug_malloc) { + print(binaryName); + print((int*) ": malloc "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8)); + println(); + } } 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); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "getchar", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3418,40 +3884,602 @@ void emitGetchar() { 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); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_getchar() { - *(registers+REG_V0) = getchar(); + int c; + + c = getchar(); - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','g','e','t','c','h','a','r',CHAR_LF,0,0); + *(registers+REG_V0) = c; + + if (debug_getchar) { + print(binaryName); + print((int*) ": getchar "); + printCharacter(c); + println(); + } } void emitPutchar() { - int *label; + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes + + emitIFormat(OP_ADDIU, REG_SP, REG_A1, 0); // pointer to character + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 1); // stdout file descriptor - // "putchar" - label = createString('p','u','t','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0); + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} +//----------------------------------------------------------------------------------------- +//---------------------------ASSIGNEMENT 3, CONTAINS BUGS --------------------------------- +//----------------------------------------------------------------------------------------- + + +void emitSwitch(){ + 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + //emitIFormat(OP_LW, REG_SP, REG_T1, 0); + //emitIFormat(OP_LW, REG_SP, REG_T2, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SWITCH); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_switch(){ + + saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); + + if(*(memory+communicationSegment+12) == 0){ + registers = malloc(32*4); + } + else{ + registers = *(memory+communicationSegment+12); + } + + if(*(memory+communicationSegment+20) == 0){ + pageTable = malloc(4*1024); //ADDED A5 + + print("allocating in emulator pageTable "); + print(itoa(process,string_buffer,10,0)); + println(); + + exit(0); + } + else{ + pageTable = memory + (*(memory+communicationSegment+20))/4; + } + + + pc = *(memory+communicationSegment+11); + reg_hi = *(memory+communicationSegment+13); + reg_lo = *(memory+communicationSegment+14); + segmentStart = *(memory+communicationSegment+15); + process = *(memory+communicationSegment+16); + *(registers+REG_GP) = *(memory+communicationSegment+17); + *(registers+REG_SP) = *(memory+communicationSegment+18); + *(registers+REG_K1) = *(memory+communicationSegment+19); + + numberofInstructions = 0; //reset number of instructions + + print("Thread: "); + print(itoa(process,string_buffer,10,0)); + println(); + + *(memory+communicationSegment+10) = 0; //exit + + +} + + +void emitYield(){ + 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_YIELD); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_yield(){ + + + *(memory+communicationSegment+11) = pc; + *(memory+communicationSegment+12) = registers; + *(memory+communicationSegment+13) = reg_hi; + *(memory+communicationSegment+14) = reg_lo; + *(memory+communicationSegment+15) = segmentStart; + *(memory+communicationSegment+16) = process; + *(memory+communicationSegment+17) = *(registers+REG_GP); + *(memory+communicationSegment+18) = *(registers+REG_SP); + *(memory+communicationSegment+19) = *(registers+REG_K1); + *(memory+communicationSegment+20) = (int)(pageTable)-(int)(memory);//pageTable; + + restoreKernelState(); + +} +void emitLock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "lock", 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_LOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_lock(){ + *(memory+communicationSegment+30) = 1; //lock flag + + syscall_yield(); + + +} + +void emitUnlock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "unlock", 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_UNLOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_unlock(){ + *(memory+communicationSegment+30) = 2; //unlock flag + + syscall_yield(); +} + + + +//------------------------------------------------------------------------ +// MEMORY LAYOUT +// ---------------------------------------------------------------- +// | || | | || || || || +// | OS ||KP| NP| || P1 || P2 || P3 ... PN || +// ---------------------------------------------------------------- +// 0 2MB 4MB 6MB 8MB 32MB +// +// OS - KERNEL +// KP - KERNEL PROCESS +// NP - NEXT PROCESS +// +// ----------------------------------------------------------------------- + + + +// Kernel Process Data Structure : +// +----+------------+ +// | 0 | pc | +// | 1 | reg | +// | 2 | reg_hi | +// | 3 | reg_lo | +// | 4 | segStart | +// | 5 | global p | +// | 6 | stack p | +// +----+------------+ + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ + + *(memory+communicationSegment) = pc; + *(memory + communicationSegment+1) = reg; + *(memory + communicationSegment+2) = reg_hi; + *(memory + communicationSegment+3) = reg_lo; + *(memory + communicationSegment+4) = segStart; + *(memory + communicationSegment+5) = gp; + *(memory + communicationSegment+6) = sp; + *(memory + communicationSegment+7) = k1; + +} + +void restoreKernelState(){ + process =0; + pc = *(memory + communicationSegment); + registers = *(memory + communicationSegment + 1); + reg_hi = *(memory + communicationSegment + 2); + reg_lo = *(memory + communicationSegment + 3); + segmentStart = 0; + *(registers+REG_GP) = *(memory + communicationSegment + 5); + *(registers+REG_SP) = *(memory + communicationSegment + 6); + *(registers+REG_K1) = *(memory + communicationSegment + 7); + +} + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- KOS --------------------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +int main_os(){ + int *program; + int *segment; + int *secondSegmentStart; + + secondSegmentStart = 4*1024*1024; + segSize = 4*1024*1024; + segmentStart = 4*1024*1024*2; + + segPointer =segmentStart; + memory = 0; + initInterpreter(); + readyqueue = 0; + + loadFlag = 1; + freeListKernel = 2097152; + + loadProcess("producerConsumer.mips",2); + create_thread(3); + segmentStart = segmentStart + segSize; + + //loadProcess("test.mips",2); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",3); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",4); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",5); + + loadFlag = 0; + + *(secondSegmentStart+40) = 1;//turn on paging + + *(secondSegmentStart+30) = -1; //set flag to -1 + + + while(1){ + + interpretEnvent(); + + } + + exit(0); +} + +void interpretEnvent(){ + int *program; + int *segment; + int *secondSegmentStart; + int flag; + + int frame; + + secondSegmentStart = 4*1024*1024; + flag = *(secondSegmentStart+30); + + //FLAGS + // -1 START, FIRST PROCESS TO BE LOADED + // 1 PROCESS CALLED LOCK + // 2 PROCESS CALLED UNLOCK + // 4 PAGE FAULT + // 0 ELSE , LOAD NEW PROCESS + + if(flag == -1){ + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+30) = 0; + + *(secondSegmentStart+10) = 1; //switch + } + + else if(flag == 1){ + + processLock = getProcessId(process); + *(secondSegmentStart+10) = 1; //switch + } + else if(flag == 2){ + + if(processLock == getProcessId(process)){ + processLock = 0; + *(secondSegmentStart+30) = 0; + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } + + } + else if(flag == 4){ //page fault + + pageTable = *(secondSegmentStart+20); + frame = *(secondSegmentStart+41) / 4096; //adr saved before in *(secondSegmentStart+41) + + *(pageTable+frame) = freeListKernel; + + freeListKernel = freeListKernel + 4096; + + *(secondSegmentStart+30) = 0; //set flag back to 0 + *(secondSegmentStart+10) = 1; //switch + + + } + + else{ + + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } +} + +void loadProcess(int * name, int id){ + int *segment; + + binaryName = name; + binaryLength = 0; + pageTable = getPageTableStart(id); + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the second segment! + *(registers+REG_SP) = segSize-4; + + segment = insertSegment(id,segPointer,segSize,segmentTable); + segPointer = segPointer + segSize; //increment segmentPointer + push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + +} + +int *getPageTableStart(int pId){ + int *pageTableStart; + int *pageTableProcess; + + pageTableStart= 6*1024*1024; // second part of the communication segment + pageTableProcess= pageTableStart + (pId * 1024); + + return pageTableProcess; +} + +void create_thread(int pId){ + int * segment; + + *(registers+REG_SP) = segSize-1024; + segment = insertSegment(pId,segPointer,segSize,segmentTable); + push(memory,0,reg_hi,reg_lo,pc,pId,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + +} + + +//----------------------MICHAEL-SCOTT QUEUE ------------------------ + +void init_mcqueue(){ + int * ab; + int i; + i =0; + queue_t = 3*1024*1024 + 100; + + q_tail = malloc(1*4); + q_head = malloc(1*4); + + *(queue_t) = 0; + *(queue_t+1) = 0; //ref Number + mc_bump = 0; + + *(q_head) = queue_t; + *(q_tail) = queue_t; + +} + + +void mc_enqueue(int * queue_t, int value ){ + int * node; + int * tail; + int tail_count; + int * tail_next; + int tail_next_count; + int l_break; + int next; + + l_break = 0; + node = init_node(queue_t, value); + + while(l_break == 0){ + tail = *(q_tail); + tail_count = *(tail+1); + tail_next = *(tail); + tail_count = *(tail_next+1); + + if(firstInsertFlag == 1){ //fix with shared mememory!!! + firstInsertFlag = 0; + return; + } + + if(tail == *(q_tail)){ + if(tail_next == 0){ + println(); + if(CAS(tail,(int)(tail_next),(int)(node)) == 1){ + l_break = 1; + } + + } + else{ + CAS(q_tail,(int)(tail),(int)(tail_next)); + } + } + + } + CAS(q_tail,(int)(tail),(int)(node)); +} + +void mc_decueue(int * queue_t, int * pvalue){ + int * head; + int * tail; + int * head_next; + int l_break; + + l_break= 0; + + while(l_break == 0){ + head = *(q_head); + tail = *(q_tail); + head_next = *(head); + + if(head == *(q_head)){ + if(head == tail){ + if(*head_next == 0){ + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + l_break =1; //queue empty! + } + CAS(q_tail, tail+12, (int)(*(tail))); + } + else{ + pvalue = head_next + 2; + if(CAS(q_head,(int)(head),(int)(head_next)) == 1){ + l_break = 1; + } + } + } + } + + + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; +} + + + +int * init_node(int * queue_t, int value){ + *(queue_t + mc_bump+1) = *(queue_t + mc_bump+1) + 1; //ref counter + *(queue_t + mc_bump+2) = value; // value + mc_bump = mc_bump + 3; + + return queue_t+(mc_bump-3); +} + +void print_mc_queue(int * queue_t){ + int *queue; + queue= *(q_head); + + print("printing mc queue "); + println(); + + while((int)(queue) !=0){ + print(itoa(*(queue+2),string_buffer,10,0)); + print(" , "); + queue = *(queue); + } + + println(); + +} + +int CAS(int * node, int old, int new){ + + if(*(node) != old){ + return 0; + } + + *(node) = new; + + return 1; +} + - emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes - emitIFormat(OP_ADDIU, REG_SP, REG_A1, 0); // pointer to character - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 1); // stdout file descriptor - 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); -} // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -3465,111 +4493,122 @@ void emitPutchar() { void fct_syscall() { if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + printFunction(function); + println(); } if (*(registers+REG_V0) == SYSCALL_EXIT) { syscall_exit(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_READ) { syscall_read(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_WRITE) { syscall_write(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_OPEN) { syscall_open(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { syscall_malloc(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { syscall_getchar(); - } else { + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_YIELD) { + pc = pc + 4; + syscall_yield(); + } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { + pc = pc + 4; + syscall_switch(); + }else if (*(registers+REG_V0) == SYSCALL_LOCK) { + pc = pc + 4; + syscall_lock(); + }else if (*(registers+REG_V0) == SYSCALL_UNLOCK) { + pc = pc + 4; + syscall_unlock(); + }else { exception_handler(EXCEPTION_UNKNOWNSYSCALL); } - pc = pc + 1; } void fct_nop() { - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + printFunction(function); + println(); } } void op_jal() { - *(registers+REG_LINK) = pc * 4 + 8; + *(registers+REG_RA) = pc + 8; - pc = instr_index; + pc = instr_index * 4; // TODO: execute delay slot if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - memset(string_buffer, 33, 0); + printOpcode(opcode); + print((int*) " "); print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + println(); } } void op_j() { - pc = instr_index; + pc = instr_index * 4; // TODO: execute delay slot if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - memset(string_buffer, 33, 0); + printOpcode(opcode); + print((int*) " "); print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + println(); } } void op_beq() { - pc = pc + 1; + pc = pc + 4; if (*(registers+rs) == *(registers+rt)) { - pc = pc + signExtend(immediate); + pc = pc + signExtend(immediate) * 4; + // TODO: execute delay slot } if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printOpcode(opcode); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void op_bne() { - pc = pc + 1; + pc = pc + 4; if (*(registers+rs) != *(registers+rt)) { - pc = pc + signExtend(immediate); + pc = pc + signExtend(immediate) * 4; + // TODO: execute delay slot } if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printOpcode(opcode); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } @@ -3578,80 +4617,69 @@ void op_addiu() { // TODO: check for overflow - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void fct_jr() { - pc = *(registers+rs) / 4; + pc = *(registers+rs); if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rs); + println(); } } void op_lui() { *(registers+rt) = leftShift(immediate, 16); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void fct_mfhi() { *(registers+rd) = reg_hi; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); } } void fct_mflo() { *(registers+rd) = reg_lo; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); } } @@ -3659,17 +4687,15 @@ void fct_multu() { // TODO: 64-bit resolution currently not supported reg_lo = *(registers+rs) * *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } @@ -3677,82 +4703,73 @@ void fct_divu() { reg_lo = *(registers+rs) / *(registers+rt); reg_hi = *(registers+rs) % *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } void fct_addu() { *(registers+rd) = *(registers+rs) + *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); + printRegister(rt); + println(); } } void fct_subu() { *(registers+rd) = *(registers+rs) - *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); - + printRegister(rt); + println(); } } void op_lw() { int vaddr; - int paddr; vaddr = *(registers+rs) + signExtend(immediate); - paddr = addressTranslation(vaddr) / 4; + *(registers+rt) = loadMemory(vaddr); - *(registers+rt) = *(memory+paddr); - - pc = pc + 1; + if(pageFault == 0){ + pc = pc + 4; + } if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - putchar('('); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(')'); - - putchar(CHAR_LF); + println(); } } @@ -3762,48 +4779,42 @@ void fct_slt() { else *(registers+rd) = 0; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } void op_sw() { int vaddr; - int paddr; - int tmp; vaddr = *(registers+rs) + signExtend(immediate); - paddr = addressTranslation(vaddr) / 4; + storeMemory(vaddr, *(registers+rt)); - *(memory+paddr) = *(registers+rt); - - pc = pc + 1; + if(pageFault == 0){ + pc = pc + 4; + } + //pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - putchar('('); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(')'); - - putchar(CHAR_LF); + println(); } } @@ -3811,17 +4822,15 @@ void fct_teq() { if (*(registers+rs) == *(registers+rt)) exception_handler(EXCEPTION_SIGNAL); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)*(fct_strings+function)); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } @@ -3829,34 +4838,25 @@ void fct_teq() { // -------------------------- 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); + print(binaryName); + print((int*) ": $pc="); + print(itoa(pc, string_buffer, 16, 8)); + print((int*) ": "); } } @@ -3867,21 +4867,21 @@ void post_debug() { while (i < 32) { if (*(registers+i) != 0) { - print((int*)*(register_strings+i)); - putchar(CHAR_TAB); - memset(string_buffer, 33, 0); + print(binaryName); + print((int*) ": "); + printRegister(i); + putchar(CHAR_EQUAL); print(itoa(*(registers+i), string_buffer, 16, 8)); - - putchar(CHAR_LF); + println(); } i = i + 1; } - putchar(CHAR_LF); + println(); } } void fetch() { - ir = *(memory+pc); + ir = loadMemory(pc); } void execute() { @@ -3930,53 +4930,83 @@ void execute() { } } -void run() { +//A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH +void run(){ 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); + + if(pageFault == 0){ + decode(); + pre_debug(); + execute(); + post_debug(); + + if(*(memory+communicationSegment+10) == 1){ + syscall_switch(); + } + + + if(*(memory+communicationSegment+40) == 1){ + turnOnPaging(); + } + + } + + if(pageFault == 1){ + pageFault = 0; + numberofInstructions = numberofInstructions + 1; + *(memory+communicationSegment+30) = 4; + syscall_yield(); + } + + //if(numberofInstructions > 2){ + // if(process !=0){ + // syscall_yield(); + // } + + //} + + numberofInstructions = numberofInstructions + 1; - print(itoa(memorySize/1024/1024*4, string_buffer, 10, 0)); + } - printString('M','B',CHAR_LF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); } -int* parse_args(int argc, int *argv, int *cstar_argv) { +void parse_args(int argc, int *argv) { // assert: ./selfie -m size executable {-m size executable} - int memorySize; - - memorySize = atoi((int*)*(cstar_argv+2)) * 1024 * 1024 / 4; - allocateMachineMemory(memorySize*4); + // memory size in bytes and executable file name + initMemory(atoi((int*) *(argv+2)) * 1024 * 1024, (int*) *(argv+3)); // initialize stack pointer - *(registers+REG_SP) = (memorySize - 1) * 4; + *(registers+REG_SP) = memorySize - 4; + + memSize = atoi((int*) *(argv+2)) * 1024 * 1024; //ADDED A1 - debug_boot(memorySize); - // return executable file name - return (int*)*(argv+3); + print(binaryName); + print((int*) ": memory size "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0)); + print((int*) "MB"); + println(); } void up_push(int value) { - int address; + int vaddr; + print("stack"); + println(); + // 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,144 +5017,470 @@ int up_malloc(int size) { return *(registers+REG_V0); } -int CStringLength(int* s) { - int l; +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_malloc(stringLength((int*) *argv) + 1)); - l = 0; + copyStringToMemory((int*) *argv, loadMemory(vaddr)); - while (rightShift(leftShift(*s, 24 - (l % 4) * 8), 24) != 0) { - l = l + 1; + vaddr = vaddr + 4; - if (l % 4 == 0) - s = s + 1; + argv = argv + 1; + argc = argc - 1; } +} + +void insertInProcessTable(int *process, int gp, int sp, int *head){ + int *adr; + + adr = malloc(4*4); + + + setProcessTableNext(adr,head); + setProcessTableProcess(adr,process); + setProcessTableGp(adr,gp); + setProcessTableSp(adr,sp); + + processTable = adr; - return l; } -int up_copyCString(int *s) { - int l; - int r; - int a; +void setProcessTableNext(int *processEntry, int *next){ + *processEntry = (int)(next); +} - l = CStringLength(s); +void setProcessTableProcess(int *processEntry, int *process){ + *(processEntry+1) = process; +} + +void setProcessTableGp(int *processEntry, int gp){ + *(processEntry+2) = gp; +} - r = up_malloc(l+1); +void setProcessTableSp(int *processEntry, int sp){ + *(processEntry+3) = sp; +} - a = r / 4; +int* getProcessTableNext(int *processEntry){ + return (int*) *processEntry; +} - while (a * 4 < r + l + 1) { - *(memory + a) = *s; +int *getProcessTableProcess(int *processEntry){ + return (int*) *(processEntry+1); +} - s = s + 1; - a = a + 1; +int getProcessTableGp(int *processEntry){ + return *(processEntry+2); +} + +int getProcessTableSp(int *processEntry){ + return *(processEntry+3); +} + + + +int main_emulator(int argc, int *argv) { + int*segment; + int i; + + initInterpreter(); + + initMemory(64 * 1024 * 1024,"selfie.mips"); + binaryLength = 0; + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the firs segment! + *(registers+REG_SP) = segSize - 4; + + run(); + + exit(0); + +} + +void turnOnPaging(){ + + pagingFlag = 1; + *(memory+communicationSegment+40) = 2; //turn of syscall + +} + +void printMemory(int *adr, int length, int from){ + int i; + int j; + j = 0; + i=from; + print("Memory number, Memory adress, Memory value"); + println(); + while(i 0) { - *(memory + c_argv) = up_copyCString((int*)*argv); +void push(int *memory, int *registers, int reg_hi, int reg_lo, int pc, int pId, int *segment, int gp, int sp, int k1,int *pageTable ,int *head){ + + int *adr; + + // Process Data Structure : + // +----+------------+ + // | 0 | ptr to next| + // | 1 | pc | + // | 2 | mem | + // | 3 | reg | + // | 4 | reg_hi | + // | 5 | reg_lo | + // | 6 | processID | + // | 7 | segPointer | + // | 8 | global p | + // | 9 | stack p | + // | 10 | k1 | + // +----+------------+ + + adr = (int*)malloc (12*4); + + setPrcosessNext(adr,head); + setProcessPc(adr,pc); + setProcessMemory(adr,memory); + setProcessRegisters(adr,registers); + setProcessRegHi(adr,reg_hi); + setProcessRegLo(adr,reg_lo); + setProcessId(adr,pId); + setProcessSegPointer(adr,segment); + setProcessGlobalP(adr,gp); + setProcessStackP(adr,sp); + setProcessK1(adr,k1); + setProcessPageTable(adr,pageTable); - c_argv = c_argv + 1; - argv = argv + 1; + + readyqueue = adr; + +} - argc = argc - 1; +int * pop(int *head){ + int i; + int *temp; + int* number_buffer; + + i = 0; + number_buffer = (int*) malloc (10 * 4); + + + if((int)(head) ==0) + return 0; + + if(*(head) == 0){ + readyqueue = 0; + return head; } + + while(*(head) != 0){ + temp = getProcessNext(head); + if(*(temp) == 0){ + setPrcosessNext(head,0); + return temp; + } + + head = temp; + } + } -int main_emulator(int argc, int *argv, int *cstar_argv) { - initInterpreter(); +void setPrcosessNext(int *process, int *next){ + *process = (int)(next); +} - *(registers+REG_GP) = loadBinary(parse_args(argc, argv, cstar_argv)); +void setProcessPc(int * process, int pc){ + *(process+1) = pc; +} - *(registers+REG_K1) = *(registers+REG_GP); +void setProcessMemory(int *process, int *memory){ + *(process+2) = (int)(memory); +} - up_copyArguments(argc-3, argv+3); +void setProcessRegisters(int *process, int *registers){ + *(process+3) = (int)(registers); +} - run(); +void setProcessRegHi(int *process, int reg_hi){ + *(process+4) = reg_hi; +} - exit(0); +void setProcessRegLo(int *process, int reg_lo){ + *(process+5) = reg_lo; } -// ----------------------------------------------------------------- -// ----------------------------- MAIN ------------------------------ -// ----------------------------------------------------------------- +void setProcessId(int *process, int pId){ + *(process+6) = pId; +} -int* copyC2CStarString(int* s) { - int l; - int *r; - int i; +void setProcessSegPointer(int *process, int *segment){ + *(process+7) = segment; +} - l = CStringLength(s); +void setProcessGlobalP(int *process, int gp){ + *(process+8) = gp; +} - r = malloc((l + 1) * 4); +void setProcessStackP(int *process, int sp){ + *(process+9) = sp; +} +void setProcessK1(int *process, int k1){ + *(process+10) = k1; +} +void setProcessPageTable(int *process, int *pageTable){ + *(process+11) = pageTable; +} - i = 0; +int* getProcessNext(int *process){ + return (int*) *process; +} - while (i <= l) { - *(r+i) = rightShift(leftShift(*s, 24 - (i % 4) * 8), 24); +int getProcessPc(int *process){ + return *(process+1); +} - i = i + 1; +int* getProcessMemory(int *process){ + return (int*) *(process+2); +} - if (i % 4 == 0) - s = s + 1; - } +int* getProcessRegisters(int *process){ + return (int*) *(process+3); +} - return r; +int getProcessRegHi(int *process){ + return *(process+4); } -int* copyC2CStarArguments(int argc, int *argv) { - int *cstar_argv; - int *cursor; +int getProcessRegLo(int *process){ + return *(process+5); +} +int getProcessId(int *process){ + return *(process+6); +} - cstar_argv = malloc(argc * 4); +int* getProcessSegPointer(int *process){ + return (int*) *(process+7); +} - cursor = cstar_argv; +int getProcessGlobalP(int *process){ + return *(process+8); +} +int getProcessStackP(int *process){ + return *(process+9); +} +int getProcessK1(int *process){ + return *(process+10); +} +int getProcessPageTable(int *process){ + return *(process+11); +} - while (argc > 0) { - *cursor = (int)copyC2CStarString((int*)*argv); +int * insertSegment (int pId, int start, int size, int *head){ + int *adr; + + // Segment Data Structure : + // +----+------------+ + // | 0 | ptr to next| + // | 1 | pId | + // | 2 | startAdress| + // | 3 | size | + // +----+------------+ + + adr = (int*)malloc (4*4); + + setSegmentNext(adr,head); + setSegmentId(adr,pId); + setSegmentStart(adr,start); + setSegmentSize(adr,size); + + segmentTable = adr; + + return adr; - argv = argv + 1; - cursor = cursor + 1; - argc = argc - 1; - } +} + +void setSegmentNext(int *segment, int *next){ + *segment = (int)(next); +} + +void setSegmentId(int *segment, int pId){ + *(segment+1) = pId; +} + +void setSegmentStart(int *segment, int start){ + *(segment+2) = start; +} - return cstar_argv; +void setSegmentSize(int *segment, int size){ + *(segment+3) = size; } +int* getSegmentNext(int *segment){ + return (int*) *segment; +} + +int getSegmentId(int *segment){ + return *(segment+1); +} + +int getSegmentStart(int *segment){ + return *(segment+2); +} + +int getSegmentSize(int *segment){ + return *(segment+3); +} + +void scheduler(){ + int pId; + int *segment; + pId= getProcessId(process); + segment = getProcessSegPointer(process); + + //save the process state + push(memory,registers,reg_hi,reg_lo,pc,pId,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + + //get the next process + process = pop(readyqueue); + + + + //memory = getProcessMemory(process); + registers = getProcessRegisters(process); + pc = getProcessPc(process); + reg_hi = getProcessRegHi(process); + reg_lo = getProcessRegLo(process); + +} + + + +// ----------------------------------------------------------------- +// ----------------------------- MAIN ------------------------------ +// ----------------------------------------------------------------- + int main(int argc, int *argv) { - int *cstar_argv; int *firstParameter; initLibrary(); initRegister(); initDecoder(); - initSyscalls(); - - cstar_argv = copyC2CStarArguments(argc, argv); - + if (argc > 1) { - firstParameter = (int*) (*(cstar_argv+1)); + firstParameter = (int*) *(argv+1); - if (*firstParameter == '-') { - if (*(firstParameter+1) == 'c') + if (getCharacter(firstParameter, 0) == '-') { + if (getCharacter(firstParameter, 1) == 'c') main_compiler(); - else if (*(firstParameter+1) == 'm') { + else if (getCharacter(firstParameter, 1) == 'm') { + if (argc > 3) + main_emulator(argc, (int*) argv); + else + exit(-1); + } + else if(getCharacter(firstParameter, 1) == 'k'){ if (argc > 3) - main_emulator(argc, argv, cstar_argv); + main_os(); else exit(-1); } @@ -4134,7 +5490,7 @@ int main(int argc, int *argv) { } else { exit(-1); } - } else - // default: compiler - main_compiler(); -} + } else{ + main_os(); + } +} \ No newline at end of file diff --git a/selfieProducerConsumer.c b/selfieProducerConsumer.c new file mode 100755 index 0000000..fc464b7 --- /dev/null +++ b/selfieProducerConsumer.c @@ -0,0 +1,5518 @@ +// Copyright (c) 2015, the Selfie Project authors. All rights reserved. +// Please see the AUTHORS file for details. Use of this source code is +// governed by a BSD license that can be found in the LICENSE file. +// +// Selfie is a project of the Computational Systems Group at the +// Department of Computer Sciences of the University of Salzburg +// in Austria. For further information and code please refer to: +// +// http://selfie.cs.uni-salzburg.at +// +// The Selfie Project provides an educational platform for teaching +// undergraduate and graduate students the design and implementation +// of programming languages and runtime systems. The focus is on the +// construction of compilers, libraries, operating systems, and even +// virtual machine monitors. The common theme is to identify and +// 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: +// +// 1. a self-compiling compiler called cstarc that compiles +// a tiny but powerful subset of C called C Star (C*) to +// a tiny but powerful subset of MIPS32 called MIPSter, +// 2. a self-executing emulator called mipster that executes +// MIPSter code including itself when compiled with cstarc, and +// 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 +// operating system support in the form of MIPS32 o32 system calls built +// into the emulator. Selfie is meant to be extended in numerous ways. +// +// 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. +// 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 +// arithmetics helping students gain true understanding of two's complement. +// C* is supposed to be close to the minimum necessary for implementing +// a self-compiling, single-pass, recursive-descent compiler. C* can be +// taught in around two weeks of classes depending on student background. +// +// The compiler can readily be extended to compile features missing in C* +// and to improve performance of the generated code. The compiler generates +// MIPSter executables that can directly be executed by the emulator or +// written to a file in a simple, custom-defined format. Support of standard +// MIPS32 ELF binaries should be easy but remains future work. +// +// MIPSter is a tiny Turing-complete subset of the MIPS32 instruction set. +// It only features arithmetic, memory, and control-flow instructions but +// neither bitwise nor byte-level instructions. MIPSter can be properly +// explained in a single week of classes. +// +// The emulator implements minimal operating system support that is meant +// to be extended by students, first as part of the emulator, and then +// ported to run on top of it, similar to an actual operating system or +// virtual machine monitor. The fact that the emulator can execute itself +// helps exposing the self-referential nature of that challenge. +// +// Selfie is the result of many years of teaching systems engineering. +// The design of the compiler is inspired by the Oberon compiler of +// Professor Niklaus Wirth from ETH Zurich. + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- L I B R A R Y --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ----------------------- LIBRARY FUNCTIONS ----------------------- +// ----------------------------------------------------------------- + +void initLibrary(); + +int twoToThePowerOf(int p); +int leftShift(int n, int b); +int rightShift(int n, int b); + +int stringLength(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); + +void print(int *s); +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 *string_buffer; + +// ------------------------- INITIALIZATION ------------------------ + +void initLibrary() { + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; + INT_MIN = -INT_MAX - 1; + + // accommodate 32-bit numbers for itoa + string_buffer = malloc(33); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- C O M P I L E R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- SCANNER ---------------------------- +// ----------------------------------------------------------------- + +void initScanner(); + +void printSymbol(int symbol); +void printLineNumber(int* message); + +void syntaxErrorMessage(int *message); +void syntaxErrorCharacter(int character); + +int isCharacterWhitespace(); +int findNextCharacter(); +int isCharacterLetter(); +int isCharacterDigit(); +int isCharacterLetterOrDigitOrUnderscore(); +int isNotDoubleQuoteOrEOF(); +int identifierStringMatch(int stringIndex); +int identifierOrKeyword(); +int getSymbol(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +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 = 64; // maximum number of characters in a string + +// ------------------------ GLOBAL VARIABLES ----------------------- + +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 + +// ------------------------- INITIALIZATION ------------------------ + +void initScanner () { + 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 = getchar(); + symbol = SYM_EOF; +} + +// ----------------------------------------------------------------- +// ------------------------- 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* 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 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 VARIABLE = 1; +int FUNCTION = 2; +int STRING = 3; + +// types +int INT_T = 1; +int INTSTAR_T = 2; +int VOID_T = 3; + +// symbol tables +int GLOBAL_TABLE = 1; +int LOCAL_TABLE = 2; + +// ------------------------ GLOBAL VARIABLES ----------------------- + +// table pointers +int *global_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; + +// ----------------------------------------------------------------- +// ---------------------------- PARSER ----------------------------- +// ----------------------------------------------------------------- + +void initParser(); + +int isNotRbraceOrEOF(); +int isExpression(); +int isStarOrDivOrModulo(); +int isPlusOrMinus(); +int isComparison(); + +int lookForFactor(); +int lookForStatement(); +int lookForType(); + +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 gr_call(int *procedure); +int gr_factor(); +int gr_term(); +int gr_simpleExpression(); +int gr_expression(); +void gr_while(); +void gr_if(); +void gr_return(int returnType); +void gr_statement(); +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 maxBinaryLength; + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int allocatedTemporaries = 0; // number of allocated temporaries + +int allocatedMemory = 0; // number of bytes for global variables and strings + +int mainJumpAddress = 0; // address of main function +int returnBranches = 0; // fixup chain for return statements + +int *currentProcedureName = (int*) 0; // name of currently parsed procedure + +// ------------------------- INITIALIZATION ------------------------ + +void +initParser() { + // set maximum code length in bytes for emitting code + maxBinaryLength = twoToThePowerOf(17); +} + +// ----------------------------------------------------------------- +// ---------------------- MACHINE CODE LIBRARY --------------------- +// ----------------------------------------------------------------- + +void emitLeftShiftBy(int b); +void emitMainEntry(); + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ------------------- I N T E R F A C E ------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void initRegister(); + +void printRegister(int reg); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +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() { + 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"; +} + +// ----------------------------------------------------------------- +// ---------------------------- ENCODER ---------------------------- +// ----------------------------------------------------------------- + +int encodeRFormat(int opcode, int rs, int rt, int rd, int function); +int encodeIFormat(int opcode, int rs, int rt, int immediate); +int encodeJFormat(int opcode, int instr_index); + +int getOpcode(int instruction); +int getRS(int instruction); +int getRT(int instruction); +int getRD(int instruction); +int getFunction(int instruction); +int getImmediate(int instruction); +int getInstrIndex(int instruction); +int signExtend(int immediate); + +// ----------------------------------------------------------------- +// ---------------------------- DECODER ---------------------------- +// ----------------------------------------------------------------- + +void initDecoder(); + +void printOpcode(int opcode); +void printFunction(int function); + +void decode(); +void decodeRFormat(); +void decodeIFormat(); +void decodeJFormat(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +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 = 0; +int rs = 0; +int rt = 0; +int rd = 0; +int immediate = 0; +int function = 0; +int instr_index = 0; + +// ------------------------- INITIALIZATION ------------------------ + +void initDecoder() { + 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 ----------------------------- +// ----------------------------------------------------------------- + +void initMemory(int size, int* name); + +int tlb(int vaddr); + +int loadMemory(int vaddr); +void storeMemory(int vaddr, int data); + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *memory; +int memorySize; + +int *binaryName; +int binaryLength; + +// ------------------------- INITIALIZATION ------------------------ + +void initMemory(int size, int *name) { + memory = malloc(size); + memorySize = size; + + binaryName = name; + binaryLength = 0; +} + +// ----------------------------------------------------------------- +// ---------------------------- BINARY ----------------------------- +// ----------------------------------------------------------------- + +void emitInstruction(int instruction); +void emitRFormat(int opcode, int rs, int rt, int rd, int function); +void emitIFormat(int opcode, int rs, int rt, int immediate); +void emitJFormat(int opcode, int instr_index); + +void fixup_relative(int fromAddress); +void fixup_absolute(int fromAddress, int toAddress); +void fixlink_absolute(int fromAddress, int toAddress); + +int copyStringToMemory(int *s, int a); + +void emitBinary(); +void loadBinary(); + +// ----------------------------------------------------------------- +// --------------------------- SYSCALLS ---------------------------- +// ----------------------------------------------------------------- + +void emitExit(); +void syscall_exit(); + +void emitRead(); +void syscall_read(); + +void emitWrite(); +void syscall_write(); + +void emitOpen(); +void syscall_open(); + +void emitMalloc(); +void syscall_malloc(); + +void emitGetchar(); +void syscall_getchar(); + +void emitPutchar(); + +void emitYield(); //ADDED A2 +void syscall_yield(); //ADDED A2 + +void emitSwitch(); //ADDED A3 +void syscall_switch(); //ADDED A3 + +void emitLock(); +void syscall_lock(); + +void emitUnlock(); +void syscall_unlock(); + +void emitTrap(); +void syscall_trap(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; +int SYSCALL_MALLOC = 5001; +int SYSCALL_GETCHAR = 5002; +int SYSCALL_YIELD = 5003; //ADDED A2 +int SYSCALL_SWITCH = 5004; //ADDED A3 +int SYSCALL_LOCK = 5005; //ADDED A4 +int SYSCALL_UNLOCK = 5006; //ADDED A4 +int SYSCALL_TRAP = 6007; //ADDED A4 + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ------------------------- INSTRUCTIONS -------------------------- +// ----------------------------------------------------------------- + +void fct_syscall(); +void fct_nop(); +void op_jal(); +void op_j(); +void op_beq(); +void op_bne(); +void op_addiu(); +void fct_jr(); +void op_lui(); +void fct_mfhi(); +void fct_mflo(); +void fct_multu(); +void fct_divu(); +void fct_addu(); +void fct_subu(); +void op_lw(); +void fct_slt(); +void op_sw(); +void op_teq(); + +// ----------------------------------------------------------------- +// -------------------------- INTERPRETER -------------------------- +// ----------------------------------------------------------------- + +void initInterpreter(); + +void printException(int enumber); + +void exception_handler(int enumber); + +void pre_debug(); +void post_debug(); + +void fetch(); +void execute(); +void run(); + +void parse_args(int argc, int *argv); + +void up_push(int value); +int up_malloc(int size); +void up_copyArguments(int argc, int *argv); + +int main_emulator(int argc, int *argv); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int debug_load = 0; + +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; +int debug_getchar = 0; + +int debug_registers = 0; +int debug_disassemble = 0; + +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 *EXCEPTIONS; // array of strings representing exceptions + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *registers; // general purpose registers + +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 + + +// -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- + +void push(int *mem, int *reg, int reg_hi, int reg_lo, int pc,int pId,int *segment,int gp, int sp, int k1,int *pageTable, int *head); + +void setPrcosessNext(int *process, int *next); +void setProcessPc(int * process, int pc); +void setProcessMemory(int *process, int *memory); +void setProcessRegisters(int *process, int *registers); +void setProcessRegHi(int *process, int reg_hi); +void setProcessRegLo(int *process, int reg_lo); +void setProcessId (int *process, int pId); +void setProcessSegPointer(int *process, int *segment); +void setProcessGlobalP(int *process, int gp); +void setProcessStackP(int *process, int sp); +void setProcessK1(int *process,int kp); +void setProcessPageTable(int *process, int *pageTable); + + +int* getProcessNext(int *process); +int getProcessPc(int *process); +int* getProcessMemory(int *process); +int* getProcessRegisters(int *process); +int getProcessRegHi(int *process); +int getProcessRegLo(int *process); +int getProcessId(int *process); +int* getProcessSegPointer(int *process); +int getProcessGlobalP(int *process); +int getProcessStackP(int *process); +int getProcessK1(int *process); +int getProcessPageTable(int *process); + + +void createProcessList(int numberoOfProcesses); +void createProcess(int *head, int pId); +void memCopy(int *oldMemory, int *newMemory, int length); + +int * insertSegment(int pId, int start, int size, int *head); + +void setSegmentId(int *segment, int pId); +void setSegmentNext(int *segment, int *next); +void setSegmentStart(int *segment, int start); +void setSegmentSize(int *segment, int size); + +int* getSegmentNext(int *segment); +int getSegmentId(int *segment); +int getSegmentStart(int *segment); +int getSegmentSize(int *segment); + +int* pop(int *head); +void scheduler(); + +// ------------------ADDITIONAL GLOBAL VARIABLES A1 -------------- + +int *readyqueue = 0; +int memSize; +int numberofInstructions = 0; + +// ------------------ADDITIONAL GLOBAL VARIABLES A2--------------- +int *process = 0; +int *segmentTable = 0; +int segPointer = 0; +//int segSize = 2097152; +int segSize = 4194304; +int communicationSegment = 1048576; //adress for the second segment 1048576*4 +int segmentStart = 0; //this variable is initalized when scheduler is called + // so that it doesn't have to be computed every time + // tlb is called + +// ----------------- ASSIGNMENT 3 -------------------------------- +int main_os(); +int interruptOccured = 0; +int processTable = 0; +void insertInProcessTable(int *process, int gp, int sp,int*head); + + +void setProcessTableNext(int *processEntry, int *next); +void setProcessTableProcess(int *processEntry, int *process); +void setProcessTableGp(int *processEntry, int gp); +void setProcessTableSp(int *processEntry, int sp); +int *getProcessTableNext(int *processEntry); +int *getProcessTableProcess(int *processEntry); +int getProcessTableGp(int *processEntry); +int getProcessTableSp(int *processEntry); + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segstart,int gp,int sp,int k1); +void restoreKernelState(); +int tlb_debug = 0; +void loadProcess(int * name, int id); + +// ------------------ ASSIGNMENT 4 ------------------------------- + +void interpretEnvent(); +int processLock = 0; + +// ------------------ ASSIGNMENT 5 ------------------------------- + +void printMemory(int *memory, int length, int from); +int palloc(int adr); +int searchPageTable(int adr); +void turnOnPaging(); +int getNextFrame(); + +int *pageTable = 0; +int *freeList = 0; +int *realMemory; +int *virtualMemory; +int freeListPointer = 1; +int pagingFlag = 0; //paging turned off + +// --------------------ASSIGNEMNT 6+7 ------------------------------- + +int *getPageTableStart(int pID); +int pageFault = 0; +void checkPageFault(int vaddr); +int freeListKernel = 0; +int flag = 0; +int pageTableAdress = 0; +int counterRun = 0; +int loadFlag = 0; + +// -------------------ASSIGNMENT 8 -------------------------------- + +int *queue_t; +int *q_tail; +int *q_head; +void test(); +void init_mcqueue(); +void mc_enqueue(int *queue_t, int value); +void mc_decueue(int *queue_t, int * value); +int * init_node(int *queue_t, int value); +int mc_bump = 0; +void print_mc_queue(int *queue_t); +int CAS(int * node, int old, int new); +int firstInsertFlag = 1; + +// ------------------------- INITIALIZATION ------------------------ + +void initInterpreter() { + 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); + +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- L I B R A R Y --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ----------------------- LIBRARY FUNCTIONS ----------------------- +// ----------------------------------------------------------------- + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + +int getCharacter(int *s, int i) { + // assert: i >= 0 + int a; + + a = i / 4; + + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); +} + +int* putCharacter(int *s, int i, int c) { + // assert: i >= 0, all characters are 7-bit + int a; + + a = i / 4; + + *(s + a) = (*(s + a) - leftShift(getCharacter(s, i), (i % 4) * 8)) + leftShift(c, (i % 4) * 8); + + return s; +} + +int stringLength(int *s) { + int i; + + i = 0; + + while (getCharacter(s, i) != 0) + i = i + 1; + + return i; +} + +void stringReverse(int *s) { + int i; + int j; + int tmp; + + i = 0; + j = stringLength(s) - 1; + + while (i < j) { + tmp = getCharacter(s, i); + + putCharacter(s, i, getCharacter(s, j)); + putCharacter(s, j, tmp); + + i = i + 1; + j = j - 1; + } +} + +int stringCompare(int *s, int *t) { + int i; + + i = 0; + + while (1) + if (getCharacter(s, i) == 0) + if (getCharacter(t, i) == 0) + return 1; + else + return 0; + else if (getCharacter(s, i) == getCharacter(t, i)) + i = i + 1; + else + return 0; +} + +int atoi(int *s) { + int i; + int n; + + i = 0; + + n = 0; + + while (getCharacter(s, i) != 0) { + n = n * 10 + getCharacter(s, i) - '0'; + + i = i + 1; + } + + return n; +} + +int* itoa(int n, int *s, int b, int a) { + // assert: b in {2,4,8,10,16} + + int i; + int sign; + + i = 0; + + sign = 0; + + if (n == 0) { + putCharacter(s, 0, '0'); + + i = 1; + } else if (n < 0) { + sign = 1; + + if (b == 10) { + if (n == INT_MIN) { + // rightmost decimal digit of 32-bit INT_MIN + putCharacter(s, 0, '8'); + + n = -(n / 10); + i = i + 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + // rightmost non-decimal digit of INT_MIN + putCharacter(s, 0, '0'); + + n = (rightShift(INT_MIN, 1) / b) * 2; + i = i + 1; + } else + n = rightShift(leftShift(n, 1), 1); + } + } + + while (n != 0) { + if (n % b > 9) + putCharacter(s, i, n % b - 10 + 'A'); + else + putCharacter(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 (b != 10) { + while (i < a) { + putCharacter(s, i, '0'); // align with zeros + + i = i + 1; + } + + if (b == 16) { + putCharacter(s, i, 'x'); + putCharacter(s, i + 1, '0'); + + i = i + 2; + } + } else if (sign) { + putCharacter(s, i, '-'); + + i = i + 1; + } + + putCharacter(s, i, 0); // null terminated string + + stringReverse(s); + + return s; +} + +void print(int *s) { + int i; + + i = 0; + + while (getCharacter(s, i) != 0) { + putchar(getCharacter(s, i)); + + i = i + 1; + } +} + +void println() { + putchar(CHAR_LF); +} + +void printCharacter(int character) { + putchar(CHAR_SINGLEQUOTE); + + 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 + putchar(character); + + putchar(CHAR_SINGLEQUOTE); +} + +void printString(int *s) { + putchar(CHAR_DOUBLEQUOTE); + + print(s); + + putchar(CHAR_DOUBLEQUOTE); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- C O M P I L E R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- SCANNER ---------------------------- +// ----------------------------------------------------------------- + +void printSymbol(int symbol) { + putchar(CHAR_DOUBLEQUOTE); + + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); + + putchar(CHAR_DOUBLEQUOTE); +} + +void printLineNumber(int* message) { + print((int*) "cstarc: "); + print(message); + print((int*) " in line "); + print(itoa(lineNumber, string_buffer, 10, 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(); +} + +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(); + + if (character == CHAR_LF) + inComment = 0; + else if (character == CHAR_CR) + inComment = 0; + else if (character == CHAR_EOF) + return character; + + } else if (isCharacterWhitespace()) { + if (character == CHAR_LF) + lineNumber = lineNumber + 1; + else if (character == CHAR_CR) + lineNumber = lineNumber + 1; + + character = getchar(); + + } else if (character == CHAR_HASH) { + character = getchar(); + inComment = 1; + + } else if (character == CHAR_SLASH) { + character = getchar(); + if (character == CHAR_SLASH) + inComment = 1; + else { + symbol = SYM_DIV; + return character; + } + + } else + return character; + } +} + +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; +} + +int isCharacterDigit() { + if (character >= '0') + if (character <= '9') + return 1; + else + return 0; + 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 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() { + if (identifierStringMatch(SYM_WHILE)) + return SYM_WHILE; + if (identifierStringMatch(SYM_IF)) + return SYM_IF; + if (identifierStringMatch(SYM_INT)) + return SYM_INT; + if (identifierStringMatch(SYM_ELSE)) + return SYM_ELSE; + if (identifierStringMatch(SYM_RETURN)) + return SYM_RETURN; + if (identifierStringMatch(SYM_VOID)) + return SYM_VOID; + else + return SYM_IDENTIFIER; +} + +int getSymbol() { + int i; + + symbol = 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 = malloc(maxIdentifierLength + 1); + + i = 0; + + while (isCharacterLetterOrDigitOrUnderscore()) { + if (i >= maxIdentifierLength) { + syntaxErrorMessage((int*) "identifier too long"); + exit(-1); + } + + putCharacter(identifier, i, character); + + i = i + 1; + + character = getchar(); + } + + putCharacter(identifier, i, 0); // null terminated string + + symbol = identifierOrKeyword(); + + } else if (isCharacterDigit()) { + integer = malloc(maxIntegerLength + 1); + + i = 0; + + while (isCharacterDigit()) { + if (i >= maxIntegerLength) { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + + putCharacter(integer, i, character); + + i = i + 1; + + character = getchar(); + } + + putCharacter(integer, i, 0); // null terminated string + + constant = atoi(integer); + + if (constant < 0) { + if (constant == INT_MIN) { + if (mayBeINTMINConstant) + isINTMINConstant = 1; + else { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + } else { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + } + + symbol = SYM_INTEGER; + + } else if (character == CHAR_SINGLEQUOTE) { + character = getchar(); + + constant = 0; + + if (character == CHAR_EOF) { + syntaxErrorMessage((int*) "reached end of file looking for a character constant"); + + exit(-1); + } else + constant = character; + + character = getchar(); + + if (character == CHAR_SINGLEQUOTE) + character = getchar(); + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + exit(-1); + } else + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + symbol = SYM_CHARACTER; + + } else if (character == CHAR_DOUBLEQUOTE) { + character = getchar(); + + string = malloc(maxStringLength + 1); + + i = 0; + + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } + + putCharacter(string, i, character); + + i = i + 1; + + character = getchar(); + } + + if (character == CHAR_DOUBLEQUOTE) + character = getchar(); + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); + + exit(-1); + } + + putCharacter(string, i, 0); // null terminated string + + symbol = SYM_STRING; + + } else if (character == CHAR_SEMICOLON) { + character = getchar(); + symbol = SYM_SEMICOLON; + + } else if (character == CHAR_PLUS) { + character = getchar(); + symbol = SYM_PLUS; + + } else if (character == CHAR_DASH) { + character = getchar(); + symbol = SYM_MINUS; + + } else if (character == CHAR_ASTERISK) { + character = getchar(); + symbol = SYM_ASTERISK; + + } else if (character == CHAR_EQUAL) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_EQUALITY; + } else + symbol = SYM_ASSIGN; + + } else if (character == CHAR_LPARENTHESIS) { + character = getchar(); + symbol = SYM_LPARENTHESIS; + + } else if (character == CHAR_RPARENTHESIS) { + character = getchar(); + symbol = SYM_RPARENTHESIS; + + } else if (character == CHAR_LBRACE) { + character = getchar(); + symbol = SYM_LBRACE; + + } else if (character == CHAR_RBRACE) { + character = getchar(); + symbol = SYM_RBRACE; + + } else if (character == CHAR_COMMA) { + character = getchar(); + symbol = SYM_COMMA; + + } else if (character == CHAR_LT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_LEQ; + } else + symbol = SYM_LT; + + } else if (character == CHAR_GT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_GEQ; + } else + symbol = SYM_GT; + + } else if (character == CHAR_EXCLAMATION) { + character = getchar(); + if (character == CHAR_EQUAL) + character = getchar(); + else + syntaxErrorCharacter(CHAR_EQUAL); + + symbol = SYM_NOTEQ; + + } else if (character == CHAR_PERCENTAGE) { + character = getchar(); + symbol = SYM_MOD; + + } else { + printLineNumber((int*) "error"); + print((int*) "found unknown character "); + printCharacter(character); + + println(); + + exit(-1); + } + + return symbol; +} + +// ----------------------------------------------------------------- +// ------------------------- SYMBOL TABLE -------------------------- +// ----------------------------------------------------------------- + +void createSymbolTableEntry(int whichTable, int *string, int data, int class, int type, int value) { + int *newEntry; + + // 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 = malloc(7 * 4); + + setString(newEntry, string); + setData(newEntry, data); + setClass(newEntry, class); + setType(newEntry, type); + setValue(newEntry, value); + + // create entry at head of symbol table + if (whichTable == GLOBAL_TABLE) { + setRegister(newEntry, REG_GP); + setNext(newEntry, global_symbol_table); + global_symbol_table = newEntry; + } else { + setRegister(newEntry, REG_FP); + setNext(newEntry, local_symbol_table); + local_symbol_table = newEntry; + } +} + +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 (int*) 0; +} + +int* getNext(int *entry) { + // cast only works if size of int and int* is equivalent + return (int*) *entry; +} + +int* getString(int *entry) { + // cast only works if size of int and int* is equivalent + return (int*) *(entry + 1); +} + +int getData(int *entry) { + return *(entry + 2); +} + +int getClass(int *entry) { + return *(entry + 3); +} + +int getType(int *entry) { + return *(entry + 4); +} + +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 setString(int *entry, int *identifier) { + // cast only works if size of int and int* is equivalent + *(entry + 1) = (int) identifier; +} + +void setData(int *entry, int data) { + *(entry + 2) = data; +} + +void setClass(int *entry, int class) { + *(entry + 3) = class; +} + +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 + 6) = reg; +} + +// ----------------------------------------------------------------- +// ---------------------------- PARSER ----------------------------- +// ----------------------------------------------------------------- + +int isNotRbraceOrEOF() { + if (symbol == SYM_RBRACE) + return 0; + else if(symbol == SYM_EOF) + return 0; + else + return 1; +} + +int isExpression() { + if (symbol == SYM_MINUS) + return 1; + else if (symbol == SYM_LPARENTHESIS) + return 1; + else if (symbol == SYM_IDENTIFIER) + return 1; + else if (symbol == SYM_INTEGER) + 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 isConstant() { + if (symbol == SYM_INTEGER) + return 1; + else if (symbol == SYM_CHARACTER) + return 1; + else + return 0; +} + +int isStarOrDivOrModulo() { + if (symbol == SYM_ASTERISK) + return 1; + else if (symbol == SYM_DIV) + return 1; + else if (symbol == SYM_MOD) + return 1; + else + return 0; +} + +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_INTEGER) + return 0; + else if (symbol == SYM_CHARACTER) + return 0; + else if (symbol == SYM_STRING) + return 0; + else if (symbol == SYM_EOF) + return 0; + else + return 1; +} + +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; + else + return 1; +} + +int lookForType() { + if (symbol == SYM_INT) + return 0; + else if (symbol == SYM_VOID) + return 0; + else if (symbol == SYM_EOF) + return 0; + else + return 1; +} + +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"); + + exit(-1); + } +} + +int currentTemporary() { + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int previousTemporary() { + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int nextTemporary() { + if (allocatedTemporaries < REG_T9 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); + + 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) { + 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(); + + 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; +} + +int load_variable(int *variable) { + int *entry; + + entry = getVariable(variable); + + talloc(); + + emitIFormat(OP_LW, getRegister(entry), currentTemporary(), getData(entry)); + + return getType(entry); +} + +void load_integer() { + // assert: constant >= 0 or constant == INT_MIN + + talloc(); + + if (constant >= 0) { + if (constant < twoToThePowerOf(15)) + // ADDIU can only load numbers < 2^15 without sign extension + 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, currentTemporary(), rightShift(constant, 14)); + + // shift left by 14 bits + emitLeftShiftBy(14); + + // and finally add 14 lsbs + 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, currentTemporary(), rightShift(constant, 17)); + + emitLeftShiftBy(14); + + // then add the next 14 msbs + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 15), 18)); + + emitLeftShiftBy(3); + + // and finally add the remaining 3 lsbs + 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, currentTemporary(), twoToThePowerOf(14)); + + // and then multiply 2^14 by 2^14*2^3 to get to 2^31 == INT_MIN + emitLeftShiftBy(14); + emitLeftShiftBy(3); + } +} + +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; + + if (entry == (int*) 0) { + // CASE 1: function call, no definition, no declaration. + createSymbolTableEntry(GLOBAL_TABLE, procedure, binaryLength, FUNCTION, INT_T, 0); + + emitJFormat(OP_JAL, 0); + + type = INT_T; //assume default return type 'int' + + } else { + type = getType(entry); + + if (getData(entry) == 0) { + // CASE 2: function call, no definition, but declared. + setData(entry, binaryLength); + + emitJFormat(OP_JAL, 0); + } else if (getOpcode(loadMemory(getData(entry))) == OP_JAL) { + // CASE 3: function call, no declaration + emitJFormat(OP_JAL, getData(entry) / 4); + + setData(entry, binaryLength - 8); + } else + // CASE 4: function defined, use the address + emitJFormat(OP_JAL, getData(entry) / 4); + } + + return type; +} + +void help_procedure_prologue(int localVariables) { + // allocate space for return address + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + + // 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); + + // set callee's frame pointer + emitIFormat(OP_ADDIU, REG_SP, REG_FP, 0); + + // 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) { + // deallocate space for callee's frame pointer and local variables + emitIFormat(OP_ADDIU, REG_FP, REG_SP, 0); + + // 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 + 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_RA, 0, 0, FCT_JR); +} + +int gr_call(int *procedure) { + int *entry; + int numberOfTemporaries; + int type; + + // assert: n = allocatedTemporaries + + entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); + + numberOfTemporaries = allocatedTemporaries; + + save_temporaries(); + + // assert: allocatedTemporaries == 0 + + if (isExpression()) { + gr_expression(); + + // 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, currentTemporary(), 0); + + tfree(1); + + while (symbol == SYM_COMMA) { + getSymbol(); + + gr_expression(); + + // push more parameters onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); + + type = INT_T; + } + } else if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); + + type = INT_T; + } + + // assert: allocatedTemporaries == 0 + + restore_temporaries(numberOfTemporaries); + + // assert: allocatedTemporaries == n + return type; +} + +int gr_factor() { + int hasCast; + int cast; + int type; + + int *variableOrProcedureName; + + // assert: n = allocatedTemporaries + + hasCast = 0; + + type = INT_T; + + while (lookForFactor()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + // cast: "(" "int" [ "*" ] ")" + if (symbol == SYM_INT) { + hasCast = 1; + + cast = gr_type(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + + // not a cast: "(" expression ")" + } else { + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + + // assert: allocatedTemporaries == n + 1 + + return type; + } + } + + // dereference? + if (symbol == SYM_ASTERISK) { + getSymbol(); + + // ["*"] identifier + if (symbol == SYM_IDENTIFIER) { + type = load_variable(identifier); + + getSymbol(); + + // * "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); + + if (type != INTSTAR_T) + typeWarning(INTSTAR_T, type); + + // dereference + emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); + + type = INT_T; + + // identifier? + } else if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + // function call: identifier "(" ... ")" + type = gr_call(variableOrProcedureName); + + talloc(); + + emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); + } else + // 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) { + talloc(); + + 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) { + getSymbol(); + + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); + + // assert: allocatedTemporaries == n + 1 + + if (hasCast) + return cast; + else + return type; +} + +int gr_term() { + int ltype; + int operatorSymbol; + int rtype; + + // assert: n = allocatedTemporaries + + ltype = gr_factor(); + + // assert: allocatedTemporaries == n + 1 + + // * / or % ? + while (isStarOrDivOrModulo()) { + operatorSymbol = symbol; + + getSymbol(); + + rtype = gr_factor(); + + // assert: allocatedTemporaries == n + 2 + + if (ltype != rtype) + typeWarning(ltype, rtype); + + if (operatorSymbol == SYM_ASTERISK) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + + } else if (operatorSymbol == SYM_DIV) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + + } else if (operatorSymbol == SYM_MOD) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFHI); + } + + tfree(1); + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +int gr_simpleExpression() { + int sign; + int ltype; + int operatorSymbol; + int rtype; + + // 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: allocatedTemporaries == n + 1 + + if (sign == 1) { + 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: allocatedTemporaries == n + 2 + + if (operatorSymbol == SYM_PLUS) { + if (ltype == INTSTAR_T) { + if (rtype == INT_T) + // pointer arithmetic: factor of 2^2 of integer operand + emitLeftShiftBy(2); + } 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); + } + + tfree(1); + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +int gr_expression() { + int ltype; + int operatorSymbol; + int rtype; + + // assert: n = allocatedTemporaries + + ltype = gr_simpleExpression(); + + // assert: allocatedTemporaries == n + 1 + + //optional: ==, !=, <, >, <=, >= simpleExpression + if (isComparison()) { + operatorSymbol = symbol; + + getSymbol(); + + rtype = gr_simpleExpression(); + + // assert: allocatedTemporaries == n + 2 + + if (ltype != rtype) + typeWarning(ltype, rtype); + + if (operatorSymbol == SYM_EQUALITY) { + // subtract, if result = 0 then 1, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); + + tfree(1); + + 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); + + } else if (operatorSymbol == SYM_NOTEQ) { + // subtract, if result = 0 then 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); + + tfree(1); + + 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); + + } else if (operatorSymbol == SYM_LT) { + // set to 1 if a < b, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + } else if (operatorSymbol == SYM_GT) { + // set to 1 if b < a, else 0 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + } else if (operatorSymbol == SYM_LEQ) { + // if b < a set 0, else 1 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + + tfree(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, currentTemporary(), 0); + + } else if (operatorSymbol == SYM_GEQ) { + // if a < b set 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); + + tfree(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, currentTemporary(), 0); + } + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +void gr_while() { + int brBackToWhile; + int brForwardToEnd; + + // assert: allocatedTemporaries == 0 + + brBackToWhile = binaryLength; + + brForwardToEnd = 0; + + // while ( expression ) + if (symbol == SYM_WHILE) { + getSymbol(); + + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + gr_expression(); + + // 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 { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + } + // only one statement without {} + else + gr_statement(); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } else + syntaxErrorSymbol(SYM_WHILE); + + // unconditional branch to beginning of while + emitIFormat(OP_BEQ, 0, 0, (brBackToWhile - binaryLength - 4) / 4); + + if (brForwardToEnd != 0) + // first instruction after loop comes here + // now we have our address for the conditional jump from above + fixup_relative(brForwardToEnd); + + // assert: allocatedTemporaries == 0 +} + +void gr_if() { + int brForwardToElseOrEnd; + int brForwardToEnd; + + // 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 = 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 { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + } + // only one statement without {} + else + gr_statement(); + + //optional: else + if (symbol == SYM_ELSE) { + getSymbol(); + + // if the "if" case was true, we jump to the end + brForwardToEnd = binaryLength; + emitIFormat(OP_BEQ, 0, 0, 0); + + // if the "if" case was not true, we jump here + fixup_relative(brForwardToElseOrEnd); + + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + + // only one statement without {} + } else + gr_statement(); + + // if the "if" case was true, we jump here + fixup_relative(brForwardToEnd); + } else + // if the "if" case was not true, we jump here + fixup_relative(brForwardToElseOrEnd); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } else + syntaxErrorSymbol(SYM_IF); + + // assert: allocatedTemporaries == 0 +} + +void gr_return(int returnType) { + int type; + + // assert: allocatedTemporaries == 0 + + if (symbol == SYM_RETURN) + getSymbol(); + else + syntaxErrorSymbol(SYM_RETURN); + + // optional: expression + if (symbol != SYM_SEMICOLON) { + type = gr_expression(); + + 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 / 4); + + // new head of fixup chain + // offest is 8 rather than 4 bytes because of delay slot NOP + returnBranches = binaryLength - 8; + + // assert: allocatedTemporaries == 0 +} + +void gr_statement() { + int ltype; + int rtype; + int *variableOrProcedureName; + int *entry; + + // assert: allocatedTemporaries == 0; + + while (lookForStatement()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // ["*"] + if (symbol == SYM_ASTERISK) { + getSymbol(); + + // "*" identifier + if (symbol == SYM_IDENTIFIER) { + ltype = load_variable(identifier); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + + getSymbol(); + + // "*" identifier "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); + + rtype = gr_expression(); + + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + tfree(2); + } else + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + + // "*" "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + ltype = gr_expression(); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + // "*" "(" expression ")" "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); + + rtype = gr_expression(); + + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + tfree(2); + } else + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } + // identifier "=" expression | call + else if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + // call + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + gr_call(variableOrProcedureName); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + + // identifier = expression + } else if (symbol == SYM_ASSIGN) { + entry = getVariable(variableOrProcedureName); + + ltype = getType(entry); + + getSymbol(); + + rtype = gr_expression(); + + if (ltype != rtype) + typeWarning(ltype, rtype); + + emitIFormat(OP_SW, getRegister(entry), currentTemporary(), getData(entry)); + + tfree(1); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorUnexpected(); + } + // while statement? + else if (symbol == SYM_WHILE) { + gr_while(); + } + // if statement? + else if (symbol == SYM_IF) { + gr_if(); + } + // return statement? + else if (symbol == SYM_RETURN) { + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + gr_return(getType(entry)); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } +} + +int gr_type() { + int type; + + type = INT_T; + + if (symbol == SYM_INT) { + getSymbol(); + + if (symbol == SYM_ASTERISK) { + type = INTSTAR_T; + + getSymbol(); + } + } else + 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 localVariables; + int functionStart; + int *entry; + + currentProcedureName = procedure; + + numberOfParameters = 0; + + // ( variable , variable ) ; + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + if (symbol != SYM_RPARENTHESIS) { + gr_variable(0); + + numberOfParameters = 1; + + while (symbol == SYM_COMMA) { + getSymbol(); + + gr_variable(0); + + numberOfParameters = numberOfParameters + 1; + } + + entry = local_symbol_table; + + 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 + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + getSymbol(); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + + if (symbol == SYM_SEMICOLON) { + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, 0, FUNCTION, returnType, 0); + + getSymbol(); + + // ( variable, variable ) { variable; variable; statement } + } else if (symbol == SYM_LBRACE) { + functionStart = binaryLength; + + getSymbol(); + + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, binaryLength, FUNCTION, returnType, 0); + else { + if (getData(entry) != 0) { + if (getOpcode(loadMemory(getData(entry))) == OP_JAL) + fixlink_absolute(getData(entry), functionStart); + else { + printLineNumber((int*) "error"); + + print((int*) "multiple definitions of "); + + print(currentProcedureName); + + println(); + } + } + + setData(entry, functionStart); + + if (getType(entry) != returnType) + typeWarning(getType(entry), returnType); + + setType(entry, returnType); + } + + localVariables = 0; + + while (symbol == SYM_INT) { + localVariables = localVariables + 1; + + gr_variable(-4 * localVariables); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } + + help_procedure_prologue(localVariables); + + // create a fixup chain for return statements + returnBranches = 0; + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + + fixlink_absolute(returnBranches, binaryLength); + + returnBranches = 0; + + help_procedure_epilogue(numberOfParameters); + + } else + syntaxErrorUnexpected(); + + local_symbol_table = (int*) 0; + + // assert: allocatedTemporaries == 0 +} + +void gr_cstar() { + int type; + int *variableOrProcedureName; + + while (symbol != SYM_EOF) { + while (lookForType()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; + + getSymbol(); + + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + gr_procedure(variableOrProcedureName, type); + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); + + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + // type identifier "(" procedure declaration or definition + if (symbol == SYM_LPARENTHESIS) + gr_procedure(variableOrProcedureName, type); + else { + allocatedMemory = allocatedMemory + 4; + + // 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); + } + } +} + +// ----------------------------------------------------------------- +// ------------------------ MACHINE CODE LIBRARY ------------------- +// ----------------------------------------------------------------- + +void emitLeftShiftBy(int b) { + // assert: 0 <= b < 15 + + // load multiplication factor less than 2^15 to avoid sign extension + 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() { + // instruction at address zero cannot be fixed up + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); + + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", binaryLength, FUNCTION, INT_T, 0); + + mainJumpAddress = binaryLength; + + emitJFormat(OP_JAL, 0); +} + +// ----------------------------------------------------------------- +// ----------------------------- MAIN ------------------------------ +// ----------------------------------------------------------------- + +int main_compiler() { + initScanner(); + initParser(); + + // memory in bytes and executable file name "out" + initMemory(maxBinaryLength, (int*) "out"); + + getSymbol(); + + // jump to main + emitMainEntry(); + + // library: + // exit must be first to exit main + // if exit call in main is missing + emitExit(); + emitRead(); + emitWrite(); + emitOpen(); + emitMalloc(); + emitGetchar(); + emitPutchar(); + emitYield(); + emitSwitch(); + emitLock(); + emitUnlock(); + + // parser + gr_cstar(); + + if (getInstrIndex(loadMemory(mainJumpAddress)) != 0) + emitBinary(); + else { + print((int*) "cstarc: main function missing"); + println(); + } + + exit(0); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ------------------- I N T E R F A C E ------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void printRegister(int reg) { + print((int*) *(REGISTERS + reg)); +} + +// ----------------------------------------------------------------- +// ---------------------------- ENCODER ---------------------------- +// ----------------------------------------------------------------- + +// ----------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+-----+-----+------+ +// |opcode| rs | rt | rd |00000|fction| +// +------+-----+-----+-----+-----+------+ +// 6 5 5 5 5 6 +int encodeRFormat(int opcode, int rs, int rt, int rd, int function) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= rs < 2^5 + // assert: 0 <= rt < 2^5 + // assert: 0 <= rd < 2^5 + // assert: 0 <= function < 2^6 + return leftShift(leftShift(leftShift(leftShift(opcode, 5) + rs, 5) + rt, 5) + rd, 11) + function; +} + +// ----------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+----------------+ +// |opcode| rs | rt | immediate | +// +------+-----+-----+----------------+ +// 6 5 5 16 +int encodeIFormat(int opcode, int rs, int rt, int immediate) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= rs < 2^5 + // assert: 0 <= rt < 2^5 + // assert: -2^15 <= immediate < 2^15 + if (immediate < 0) + // convert from 32-bit to 16-bit two's complement + immediate = immediate + twoToThePowerOf(16); + + return leftShift(leftShift(leftShift(opcode, 5) + rs, 5) + rt, 16) + immediate; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+--------------------------+ +// |opcode| instr_index | +// +------+--------------------------+ +// 6 26 +int encodeJFormat(int opcode, int instr_index) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= immediate < 2^26 + return leftShift(opcode, 26) + instr_index; +} + +int getOpcode(int instruction) { + return rightShift(instruction, 26); +} + +int getRS(int instruction) { + return rightShift(leftShift(instruction, 6), 27); +} + +int getRT(int instruction) { + return rightShift(leftShift(instruction, 11), 27); +} + +int getRD(int instruction) { + return rightShift(leftShift(instruction, 16), 27); +} + +int getFunction(int instruction) { + return rightShift(leftShift(instruction, 26), 26); +} + +int getImmediate(int instruction) { + return rightShift(leftShift(instruction, 16), 16); +} + +int getInstrIndex(int instruction) { + return rightShift(leftShift(instruction, 6), 6); +} + +int signExtend(int immediate) { + // sign-extend from 16-bit to 32-bit two's complement + if (immediate < twoToThePowerOf(15)) + return immediate; + else + return immediate - twoToThePowerOf(16); +} + +// ----------------------------------------------------------------- +// ---------------------------- DECODER ---------------------------- +// ----------------------------------------------------------------- + +void printOpcode(int opcode) { + print((int*) *(OPCODES + opcode)); +} + +void printFunction(int function) { + print((int*) *(FUNCTIONS + function)); +} + +void decode() { + opcode = getOpcode(ir); + + if (opcode == 0) + decodeRFormat(); + else if (opcode == OP_JAL) + decodeJFormat(); + else if (opcode == OP_J) + decodeJFormat(); + else + decodeIFormat(); +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+-----+-----+------+ +// |opcode| rs | rt | rd |00000|fction| +// +------+-----+-----+-----+-----+------+ +// 6 5 5 5 5 6 +void decodeRFormat() { + rs = getRS(ir); + rt = getRT(ir); + rd = getRD(ir); + immediate = 0; + function = getFunction(ir); + instr_index = 0; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+----------------+ +// |opcode| rs | rt | immediate | +// +------+-----+-----+----------------+ +// 6 5 5 16 +void decodeIFormat() { + rs = getRS(ir); + rt = getRT(ir); + rd = 0; + immediate = getImmediate(ir); + function = 0; + instr_index = 0; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+--------------------------+ +// |opcode| instr_index | +// +------+--------------------------+ +// 6 26 +void decodeJFormat() { + rs = 0; + rt = 0; + rd = 0; + immediate = 0; + function = 0; + instr_index = getInstrIndex(ir); +} + +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +int tlb(int vaddr) { + int adr; + + if (vaddr % 4 != 0) + exception_handler(EXCEPTION_ADDRESSERROR); + + //if paging is enabled and it is not kernel process + if(pagingFlag == 1){ + if(segmentStart !=0){ + adr = searchPageTable(vaddr); + return adr/4; + } + } + if(loadFlag == 1){ + adr = searchPageTable(vaddr); + return adr/4; + } + else{ + if(tlb_debug == 1){ + if(process !=0){ + print(itoa(vaddr/4, string_buffer, 10, 0)); + + print((int*)" --> "); + + vaddr = vaddr + segmentStart; + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + + else{ + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + } + else{ + if(segmentStart !=0){ + vaddr = vaddr + segmentStart; + } + } + } + // physical memory is word-addressed for lack of byte-sized data type + return vaddr / 4; +} + +int searchPageTable(int vaddr){ + int i; + int frame; + int offset; + int debugFlag; + debugFlag= 0; + + frame = vaddr/4096; + offset = vaddr%4096; + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(pageTable+frame) = freeListKernel;//freeList; + freeListKernel = freeListKernel + 4096; + + return *(pageTable+frame)+offset; + } + else{ + return *(pageTable+frame)+offset; + + } + + +} + +void checkPageFault (int vaddr){ + int frame; + int offset; + + frame = vaddr/4096; + offset = vaddr%4096; + + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(memory+communicationSegment+41) = vaddr; + } + +} + + +int loadMemory(int vaddr) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return 0; + } + } + + return *(memory + tlb(vaddr)); +} + +void storeMemory(int vaddr, int data) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return; + } + } + + *(memory + tlb(vaddr)) = data; +} + +// ----------------------------------------------------------------- +// ---------------------------- BINARY ----------------------------- +// ----------------------------------------------------------------- + +void emitInstruction(int instruction) { + if (binaryLength >= maxBinaryLength) { + syntaxErrorMessage((int*) "exceeded maximum binary length"); + exit(-1); + } else { + storeMemory(binaryLength, instruction); + + binaryLength = binaryLength + 4; + } +} + +void emitRFormat(int opcode, int rs, int rt, int rd, int function) { + emitInstruction(encodeRFormat(opcode, rs, rt, rd, function)); + + if (opcode == OP_SPECIAL) { + if (function == FCT_JR) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot + else if (function == FCT_MFLO) { + // In MIPS I-III two instructions after MFLO/MFHI + // must not modify the LO/HI registers + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + } else if (function == FCT_MFHI) { + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + } + } +} + +void emitIFormat(int opcode, int rs, int rt, int immediate) { + emitInstruction(encodeIFormat(opcode, rs, rt, immediate)); + + if (opcode == OP_BEQ) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot + else if (opcode == OP_BNE) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot +} + +void emitJFormat(int opcode, int instr_index) { + emitInstruction(encodeJFormat(opcode, instr_index)); + + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot +} + +void fixup_relative(int fromAddress) { + int instruction; + + instruction = loadMemory(fromAddress); + + storeMemory(fromAddress, + encodeIFormat(getOpcode(instruction), + getRS(instruction), + getRT(instruction), + (binaryLength - fromAddress - 4) / 4)); +} + +void fixup_absolute(int fromAddress, int toAddress) { + storeMemory(fromAddress, + encodeJFormat(getOpcode(loadMemory(fromAddress)), toAddress / 4)); +} + +void fixlink_absolute(int fromAddress, int toAddress) { + int previousAddress; + + while (fromAddress != 0) { + previousAddress = getInstrIndex(loadMemory(fromAddress)) * 4; + fixup_absolute(fromAddress, toAddress); + fromAddress = previousAddress; + } +} + +int copyStringToMemory(int *s, int a) { + int l; + int w; + + l = stringLength(s) + 1; + + w = a + l; + + if (l % 4 != 0) + w = w + 4 - l % 4; + + while (a < w) { + storeMemory(a, *s); + + s = s + 1; + a = a + 4; + } + + return w; +} + +void emitBinary() { + int *entry; + int fd; + + entry = global_symbol_table; + + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeMemory(binaryLength, getValue(entry)); + + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToMemory(getString(entry), binaryLength); + + entry = getNext(entry); + } + + // assert: file with name binaryName exists prior to execution of compiler + fd = open(binaryName, 1); // 1 = O_WRONLY + + if (fd < 0) { + syntaxErrorMessage((int*) "output file not found"); + exit(-1); + } + + // The mipster_syscall 4004 writes the code array into a file. + // The syscall uses the "write" system call of the OS and compiler. + // The write system call of our Linux uses little endian byte ordering. + write(fd, memory, binaryLength); +} + +void loadBinary() { + int fd; + int numberOfReadBytes; + + fd = open(binaryName, 0); // 0 = O_RDONLY + + if (fd < 0) + exit(-1); + + numberOfReadBytes = 4; + + while (numberOfReadBytes == 4) { + numberOfReadBytes = read(fd, memory + tlb(binaryLength), 4); + + if (debug_load) { + print(binaryName); + print((int*) ": "); + print(itoa(binaryLength, string_buffer, 16, 8)); + print((int*) ": "); + print(itoa(loadMemory(binaryLength), string_buffer, 16, 8)); + println(); + } + + if (numberOfReadBytes == 4) + binaryLength = binaryLength + 4; + } +} + +// ----------------------------------------------------------------- +// --------------------------- SYSCALLS ---------------------------- +// ----------------------------------------------------------------- + +void emitExit() { + 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); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_EXIT); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); +} + +void syscall_exit() { + int exitCode; + + exitCode = *(registers+REG_A0); + + *(registers+REG_V0) = exitCode; + + print(binaryName); + print((int*) ": exiting with error code "); + print(itoa(exitCode, string_buffer, 10, 0)); + println(); + + exit(0); +} + +void emitRead() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // count + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_read() { + int count; + int vaddr; + int fd; + int *buffer; + int size; + + count = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); + + buffer = memory + tlb(vaddr); + + size = read(fd, buffer, count); + + *(registers+REG_V0) = size; + + if (debug_read) { + print(binaryName); + print((int*) ": read "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + println(); + } +} + +void emitWrite() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // size + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_write() { + int size; + int vaddr; + int fd; + int *buffer; + + size = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); + + buffer = memory + tlb(vaddr); + + size = write(fd, buffer, size); + + *(registers+REG_V0) = size; + + if (debug_write) { + print(binaryName); + print((int*) ": wrote "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + println(); + } +} + +void emitOpen() { + 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_A1, 0); // flags + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // filename + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_open() { + int flags; + int vaddr; + int *filename; + int fd; + + flags = *(registers+REG_A1); + vaddr = *(registers+REG_A0); + + filename = memory + tlb(vaddr); + + fd = open(filename, flags); + + *(registers+REG_V0) = fd; + + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 10, 0)); + print((int*) " returning file descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + println(); + } +} + +void emitMalloc() { + 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); + + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_malloc() { + int size; + int bump; + + size = *(registers+REG_A0); + + if (size % 4 != 0) + size = size + 4 - size % 4; + + bump = *(registers+REG_K1); + + if (bump + size >= *(registers+REG_SP)) + exception_handler(EXCEPTION_HEAPOVERFLOW); + + *(registers+REG_K1) = bump + size; + *(registers+REG_V0) = bump; + + if (debug_malloc) { + print(binaryName); + print((int*) ": malloc "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8)); + println(); + } +} + +void emitGetchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "getchar", 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_GETCHAR); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_getchar() { + int c; + + c = getchar(); + + *(registers+REG_V0) = c; + + if (debug_getchar) { + print(binaryName); + print((int*) ": getchar "); + printCharacter(c); + println(); + } +} + +void emitPutchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes + + emitIFormat(OP_ADDIU, REG_SP, REG_A1, 0); // pointer to character + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 1); // stdout file descriptor + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +//----------------------------------------------------------------------------------------- +//---------------------------ASSIGNEMENT 3, CONTAINS BUGS --------------------------------- +//----------------------------------------------------------------------------------------- + + +void emitSwitch(){ + 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + //emitIFormat(OP_LW, REG_SP, REG_T1, 0); + //emitIFormat(OP_LW, REG_SP, REG_T2, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SWITCH); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_switch(){ + + saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); + + if(*(memory+communicationSegment+12) == 0){ + registers = malloc(32*4); + } + else{ + registers = *(memory+communicationSegment+12); + } + + if(*(memory+communicationSegment+20) == 0){ + pageTable = malloc(4*1024); //ADDED A5 + + print("allocating in emulator pageTable "); + print(itoa(process,string_buffer,10,0)); + println(); + + exit(0); + } + else{ + pageTable = memory + (*(memory+communicationSegment+20))/4; + } + + + pc = *(memory+communicationSegment+11); + reg_hi = *(memory+communicationSegment+13); + reg_lo = *(memory+communicationSegment+14); + segmentStart = *(memory+communicationSegment+15); + process = *(memory+communicationSegment+16); + *(registers+REG_GP) = *(memory+communicationSegment+17); + *(registers+REG_SP) = *(memory+communicationSegment+18); + *(registers+REG_K1) = *(memory+communicationSegment+19); + + numberofInstructions = 0; //reset number of instructions + + *(memory+communicationSegment+10) = 0; //exit + + +} + + +void emitYield(){ + 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_YIELD); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_yield(){ + + + *(memory+communicationSegment+11) = pc; + *(memory+communicationSegment+12) = registers; + *(memory+communicationSegment+13) = reg_hi; + *(memory+communicationSegment+14) = reg_lo; + *(memory+communicationSegment+15) = segmentStart; + *(memory+communicationSegment+16) = process; + *(memory+communicationSegment+17) = *(registers+REG_GP); + *(memory+communicationSegment+18) = *(registers+REG_SP); + *(memory+communicationSegment+19) = *(registers+REG_K1); + *(memory+communicationSegment+20) = (int)(pageTable)-(int)(memory);//pageTable; + + restoreKernelState(); + +} +void emitLock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "lock", 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_LOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_lock(){ + *(memory+communicationSegment+30) = 1; //lock flag + + syscall_yield(); + + +} + +void emitUnlock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "unlock", 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_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_UNLOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_unlock(){ + *(memory+communicationSegment+30) = 2; //unlock flag + + syscall_yield(); +} + + + +//------------------------------------------------------------------------ +// MEMORY LAYOUT +// ---------------------------------------------------------------- +// | || | | || || || || +// | OS ||KP| NP| || P1 || P2 || P3 ... PN || +// ---------------------------------------------------------------- +// 0 2MB 4MB 6MB 8MB 32MB +// +// OS - KERNEL +// KP - KERNEL PROCESS +// NP - NEXT PROCESS +// +// ----------------------------------------------------------------------- + + + +// Kernel Process Data Structure : +// +----+------------+ +// | 0 | pc | +// | 1 | reg | +// | 2 | reg_hi | +// | 3 | reg_lo | +// | 4 | segStart | +// | 5 | global p | +// | 6 | stack p | +// +----+------------+ + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ + + *(memory+communicationSegment) = pc; + *(memory + communicationSegment+1) = reg; + *(memory + communicationSegment+2) = reg_hi; + *(memory + communicationSegment+3) = reg_lo; + *(memory + communicationSegment+4) = segStart; + *(memory + communicationSegment+5) = gp; + *(memory + communicationSegment+6) = sp; + *(memory + communicationSegment+7) = k1; + +} + +void restoreKernelState(){ + process =0; + pc = *(memory + communicationSegment); + registers = *(memory + communicationSegment + 1); + reg_hi = *(memory + communicationSegment + 2); + reg_lo = *(memory + communicationSegment + 3); + segmentStart = 0; + *(registers+REG_GP) = *(memory + communicationSegment + 5); + *(registers+REG_SP) = *(memory + communicationSegment + 6); + *(registers+REG_K1) = *(memory + communicationSegment + 7); + +} + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- KOS --------------------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +int main_os(){ + int *program; + int *segment; + int *secondSegmentStart; + + secondSegmentStart = 4*1024*1024; + segSize = 4*1024*1024; + segmentStart = 4*1024*1024*2; + + segPointer =segmentStart; + memory = 0; + initInterpreter(); + readyqueue = 0; + + loadFlag = 1; + freeListKernel = 2097152; + + + init_mcqueue(); + + loadProcess("test.mips",2); + segmentStart = segmentStart + segSize; + loadProcess("test.mips",3); + segmentStart = segmentStart + segSize; + loadProcess("test.mips",4); + segmentStart = segmentStart + segSize; + //loadProcess("test.mips",5); + loadProcess("selfieForTesting.mips",5); + + loadFlag = 0; + + *(secondSegmentStart+40) = 1;//turn on paging + + *(secondSegmentStart+30) = -1; //set flag to -1 + + + while(1){ + + interpretEnvent(); + + } + + exit(0); +} + +void interpretEnvent(){ + int *program; + int *segment; + int *secondSegmentStart; + int flag; + + int frame; + + secondSegmentStart = 4*1024*1024; + flag = *(secondSegmentStart+30); + + //FLAGS + // -1 START, FIRST PROCESS TO BE LOADED + // 1 PROCESS CALLED LOCK + // 2 PROCESS CALLED UNLOCK + // 4 PAGE FAULT + // 0 ELSE , LOAD NEW PROCESS + + if(flag == -1){ + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+30) = 0; + + *(secondSegmentStart+10) = 1; //switch + } + + else if(flag == 1){ + + processLock = getProcessId(process); + *(secondSegmentStart+10) = 1; //switch + } + else if(flag == 2){ + + if(processLock == getProcessId(process)){ + processLock = 0; + *(secondSegmentStart+30) = 0; + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } + + } + else if(flag == 4){ //page fault + + pageTable = *(secondSegmentStart+20); + frame = *(secondSegmentStart+41) / 4096; //adr saved before in *(secondSegmentStart+41) + + *(pageTable+frame) = freeListKernel; + + freeListKernel = freeListKernel + 4096; + + *(secondSegmentStart+30) = 0; //set flag back to 0 + *(secondSegmentStart+10) = 1; //switch + + + } + + else{ + + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } +} + +void loadProcess(int * name, int id){ + int *segment; + + binaryName = name; + binaryLength = 0; + pageTable = getPageTableStart(id); + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the second segment! + *(registers+REG_SP) = segSize-4; + + segment = insertSegment(id,segPointer,segSize,segmentTable); + segPointer = segPointer + segSize; //increment segmentPointer + push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + +} + +int *getPageTableStart(int pId){ + int *pageTableStart; + int *pageTableProcess; + + pageTableStart= 6*1024*1024; // second part of the communication segment + pageTableProcess= pageTableStart + (pId * 1024); + + return pageTableProcess; +} + +//----------------------MICHAEL-SCOTT QUEUE ------------------------ + +void init_mcqueue(){ + int * ab; + + queue_t = 4*1024*1024 + 100; + q_tail = malloc(1*4); + q_head = malloc(1*4); + mc_bump = *(4*1024*1024 + 92);// = mc_bump; + + *(q_head) = queue_t; + *(q_tail) = queue_t; + + + +} + + +void mc_enqueue(int * queue_t, int value ){ + int * node; + int * tail; + int tail_count; + int * tail_next; + int tail_next_count; + int l_break; + int next; + + l_break = 0; + node = init_node(queue_t, value); + + while(l_break == 0){ + + tail = *(q_tail); + tail_count = *(tail+1); + tail_next = *(tail); + tail_count = *(tail_next+1); + + if(firstInsertFlag == 1){ + firstInsertFlag = 0; + return; + } + + if(tail == *(q_tail)){ + if(tail_next == 0){ + + if(CAS(tail,(int)(tail_next),(int)(node)) == 1){ + l_break = 1; + } + + } + else{ + + CAS(q_tail,(int)(tail),(int)(tail_next)); + } + } + + } + CAS(q_tail,(int)(tail),(int)(node)); + +} + +void mc_decueue(int * queue_t, int * pvalue){ + int * head; + int * tail; + int * head_next; + int l_break; + l_break= 0; + + + + while(l_break == 0){ + head = *(q_head); + tail = *(q_tail); + head_next = *(head); + + if(head == *(q_head)){ + if(head == tail){ + if(*head_next == 0){ + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + l_break =1; //queue empty! + } + CAS(q_tail, tail+12, (int)(*(tail))); + } + else{ + + pvalue = head_next + 2; + if(CAS(q_head,(int)(head),(int)(head_next)) == 1){ + l_break = 1; + } + } + } + } + + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + + + +} + + + +int * init_node(int * queue_t, int value){ + *(queue_t + mc_bump+1) = *(queue_t + mc_bump+1) + 1; //ref counter + *(queue_t + mc_bump+2) = value; // value + mc_bump = mc_bump + 3; + + *(4*1024*1024 + 92) = mc_bump; + + return queue_t+(mc_bump-3); +} + +void print_mc_queue(int * queue_t){ + int *queue; + queue= *(q_head); + + + while((int)(queue) !=0){ + print(itoa(*(queue+2),string_buffer,10,0)); + print(" , "); + queue = *(queue); + } + + println(); + +} + +int CAS(int * node, int old, int new){ + + if(*(node) != old){ + return 0; + } + + + *(node) = new; + + + return 1; +} + + + + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ------------------------- INSTRUCTIONS -------------------------- +// ----------------------------------------------------------------- + +void fct_syscall() { + if (debug_disassemble) { + printFunction(function); + println(); + } + + if (*(registers+REG_V0) == SYSCALL_EXIT) { + syscall_exit(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_READ) { + syscall_read(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_WRITE) { + syscall_write(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_OPEN) { + syscall_open(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { + syscall_malloc(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { + syscall_getchar(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_YIELD) { + pc = pc + 4; + syscall_yield(); + } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { + pc = pc + 4; + syscall_switch(); + }else if (*(registers+REG_V0) == SYSCALL_LOCK) { + pc = pc + 4; + syscall_lock(); + }else if (*(registers+REG_V0) == SYSCALL_UNLOCK) { + pc = pc + 4; + syscall_unlock(); + }else { + exception_handler(EXCEPTION_UNKNOWNSYSCALL); + } + +} + +void fct_nop() { + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + println(); + } +} + +void op_jal() { + *(registers+REG_RA) = pc + 8; + + pc = instr_index * 4; + + // TODO: execute delay slot + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 8)); + println(); + } +} + +void op_j() { + pc = instr_index * 4; + + // TODO: execute delay slot + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 8)); + println(); + } +} + +void op_beq() { + pc = pc + 4; + + if (*(registers+rs) == *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; + + // TODO: execute delay slot + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void op_bne() { + pc = pc + 4; + + if (*(registers+rs) != *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; + + // TODO: execute delay slot + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void op_addiu() { + *(registers+rt) = *(registers+rs) + signExtend(immediate); + + // TODO: check for overflow + + pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + printRegister(rs); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void fct_jr() { + pc = *(registers+rs); + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + println(); + } +} + +void op_lui() { + *(registers+rt) = leftShift(immediate, 16); + + pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void fct_mfhi() { + *(registers+rd) = reg_hi; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); + } +} + +void fct_mflo() { + *(registers+rd) = reg_lo; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); + } +} + +void fct_multu() { + // TODO: 64-bit resolution currently not supported + reg_lo = *(registers+rs) * *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_divu() { + reg_lo = *(registers+rs) / *(registers+rt); + reg_hi = *(registers+rs) % *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_addu() { + *(registers+rd) = *(registers+rs) + *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_subu() { + *(registers+rd) = *(registers+rs) - *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void op_lw() { + int vaddr; + + vaddr = *(registers+rs) + signExtend(immediate); + + *(registers+rt) = loadMemory(vaddr); + + if(pageFault == 0){ + pc = pc + 4; + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + putchar('('); + printRegister(rs); + putchar(')'); + println(); + } +} + +void fct_slt() { + if (*(registers+rs) < *(registers+rt)) + *(registers+rd) = 1; + else + *(registers+rd) = 0; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void op_sw() { + int vaddr; + + vaddr = *(registers+rs) + signExtend(immediate); + + storeMemory(vaddr, *(registers+rt)); + + if(pageFault == 0){ + pc = pc + 4; + } + //pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + putchar('('); + printRegister(rs); + putchar(')'); + println(); + } +} + +void fct_teq() { + if (*(registers+rs) == *(registers+rt)) + exception_handler(EXCEPTION_SIGNAL); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +// ----------------------------------------------------------------- +// -------------------------- INTERPRETER -------------------------- +// ----------------------------------------------------------------- + +void printException(int enumber) { + print((int*) *(EXCEPTIONS + enumber)); +} + +void exception_handler(int enumber) { + print(binaryName); + print((int*) ": exception: "); + printException(enumber); + println(); + + exit(enumber); +} + +void pre_debug() { + if (debug_disassemble) { + print(binaryName); + print((int*) ": $pc="); + print(itoa(pc, string_buffer, 16, 8)); + print((int*) ": "); + } +} + +void post_debug() { + int i; + if (debug_registers) { + i = 0; + + while (i < 32) { + if (*(registers+i) != 0) { + print(binaryName); + print((int*) ": "); + printRegister(i); + putchar(CHAR_EQUAL); + print(itoa(*(registers+i), string_buffer, 16, 8)); + println(); + } + i = i + 1; + } + println(); + } +} + +void fetch() { + ir = loadMemory(pc); +} + +void execute() { + if (opcode == OP_SPECIAL) { + if (function == FCT_NOP) { + fct_nop(); + } else if (function == FCT_ADDU) { + fct_addu(); + } else if (function == FCT_SUBU) { + fct_subu(); + } else if (function == FCT_MULTU) { + fct_multu(); + } else if (function == FCT_DIVU) { + fct_divu(); + } else if (function == FCT_MFHI) { + fct_mfhi(); + } else if (function == FCT_MFLO) { + fct_mflo(); + } else if (function == FCT_SLT) { + fct_slt(); + } else if (function == FCT_JR) { + fct_jr(); + } else if (function == FCT_SYSCALL) { + fct_syscall(); + } else if (function == FCT_TEQ) { + fct_teq(); + } else { + exception_handler(EXCEPTION_UNKNOWNINSTRUCTION); + } + } else if (opcode == OP_ADDIU) { + op_addiu(); + } else if (opcode == OP_LW) { + op_lw(); + } else if (opcode == OP_SW) { + op_sw(); + } else if (opcode == OP_BEQ) { + op_beq(); + } else if (opcode == OP_BNE) { + op_bne(); + } else if (opcode == OP_JAL) { + op_jal(); + } else if (opcode == OP_J) { + op_j(); + } else { + exception_handler(EXCEPTION_UNKNOWNINSTRUCTION); + } +} + +//A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH +void run(){ + + while (1) { + fetch(); + + if(pageFault == 0){ + decode(); + pre_debug(); + execute(); + post_debug(); + + if(*(memory+communicationSegment+10) == 1){ + syscall_switch(); + } + + + if(*(memory+communicationSegment+40) == 1){ + turnOnPaging(); + } + + } + + if(pageFault == 1){ + pageFault = 0; + numberofInstructions = numberofInstructions + 1; + *(memory+communicationSegment+30) = 4; + syscall_yield(); + } + + //if(numberofInstructions > 2){ + // if(process !=0){ + // syscall_yield(); + // } + + //} + + numberofInstructions = numberofInstructions + 1; + + } + +} + +void parse_args(int argc, int *argv) { + // assert: ./selfie -m size executable {-m size executable} + + // memory size in bytes and executable file name + initMemory(atoi((int*) *(argv+2)) * 1024 * 1024, (int*) *(argv+3)); + + // initialize stack pointer + *(registers+REG_SP) = memorySize - 4; + + memSize = atoi((int*) *(argv+2)) * 1024 * 1024; //ADDED A1 + + + print(binaryName); + print((int*) ": memory size "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0)); + print((int*) "MB"); + println(); +} + +void up_push(int value) { + int vaddr; + + print("stack"); + println(); + + // allocate space for one value on the stack + *(registers+REG_SP) = *(registers+REG_SP) - 4; + + // compute address + vaddr = *(registers+REG_SP); + + // store value + + storeMemory(vaddr, value); +} + +int up_malloc(int size) { + *(registers+REG_A0) = size; + + syscall_malloc(); + + return *(registers+REG_V0); +} + +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_malloc(stringLength((int*) *argv) + 1)); + + copyStringToMemory((int*) *argv, loadMemory(vaddr)); + + vaddr = vaddr + 4; + + argv = argv + 1; + argc = argc - 1; + } +} + +void insertInProcessTable(int *process, int gp, int sp, int *head){ + int *adr; + + adr = malloc(4*4); + + + setProcessTableNext(adr,head); + setProcessTableProcess(adr,process); + setProcessTableGp(adr,gp); + setProcessTableSp(adr,sp); + + processTable = adr; + +} + +void setProcessTableNext(int *processEntry, int *next){ + *processEntry = (int)(next); +} + +void setProcessTableProcess(int *processEntry, int *process){ + *(processEntry+1) = process; +} + +void setProcessTableGp(int *processEntry, int gp){ + *(processEntry+2) = gp; +} + +void setProcessTableSp(int *processEntry, int sp){ + *(processEntry+3) = sp; +} + +int* getProcessTableNext(int *processEntry){ + return (int*) *processEntry; +} + +int *getProcessTableProcess(int *processEntry){ + return (int*) *(processEntry+1); +} + +int getProcessTableGp(int *processEntry){ + return *(processEntry+2); +} + +int getProcessTableSp(int *processEntry){ + return *(processEntry+3); +} + + + +int main_emulator(int argc, int *argv) { + int*segment; + int i; + + initInterpreter(); + + initMemory(64 * 1024 * 1024,"selfie.mips"); + binaryLength = 0; + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the firs segment! + *(registers+REG_SP) = segSize - 4; + + run(); + + exit(0); + +} + +void turnOnPaging(){ + + pagingFlag = 1; + *(memory+communicationSegment+40) = 2; //turn of syscall + +} + +void printMemory(int *adr, int length, int from){ + int i; + int j; + j = 0; + i=from; + print("Memory number, Memory adress, Memory value"); + println(); + while(i 1) { + firstParameter = (int*) *(argv+1); + + if (getCharacter(firstParameter, 0) == '-') { + if (getCharacter(firstParameter, 1) == 'c') + main_compiler(); + else if (getCharacter(firstParameter, 1) == 'm') { + if (argc > 3) + main_emulator(argc, (int*) argv); + else + exit(-1); + } + else if(getCharacter(firstParameter, 1) == 'k'){ + if (argc > 3) + main_os(); + else + exit(-1); + } + else { + exit(-1); + } + } else { + exit(-1); + } + } else{ + test(); + } +} \ No newline at end of file diff --git a/test.c b/test.c new file mode 100644 index 0000000..2984970 --- /dev/null +++ b/test.c @@ -0,0 +1,263 @@ +int main(); +int *string_buffer; +int CHAR_LF; +int CHAR_TAB; +int CHAR_CR; +int INT_MIN; +int INT_MAX; +int result; +int *power_of_two_table; +int a; + + + +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 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); + + +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) { + + *(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; +} + +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) { + + assignString(string_buffer, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + + print(string_buffer); +} + +void print(int *s) { + while (*s != 0) { + putchar(*s); + s = s + 1; + } +} + +int stringLength(int *s) { + int i; + + i = 0; + + while (*(s+i) != 0) + i = i + 1; + + return i; +} + +void reverseString(int *s) { + int tmp; + int i; + int j; + + i = 0; + j = stringLength(s) - 1; + + while (i < j) { + tmp = *(s+i); + *(s+i) = *(s+j); + *(s+j) = tmp; + i = i + 1; + j = j - 1; + } +} + +int* itoa(int n, int *s, int b, int a) { + // assert: b in {2,4,8,10,16} + + int i; + int sign; + + i = 0; + + sign = 0; + + if (n == 0) { + *s = '0'; + + i = 1; + } else if (n < 0) { + sign = 1; + + if (b == 10) { + if (n == INT_MIN) { + *s = '8'; // rightmost decimal digit of 32-bit INT_MIN + + n = -(n / 10); + i = i + 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + *s = '0'; // rightmost non-decimal digit of INT_MIN + + n = (rightShift(INT_MIN, 1) / b) * 2; + i = i + 1; + } else + n = rightShift(leftShift(n, 1), 1); + } + } + + while (n != 0) { + *(s+i) = n % b; + + if (*(s+i) > 9) + *(s+i) = *(s+i) - 10 + 'A'; + else + *(s+i) = *(s+i) + '0'; + + n = n / b; + i = i + 1; + + if (i == 1) { + if (sign) { + if (b != 10) + n = n + (rightShift(INT_MIN, 1) / b) * 2; + } + } + } + + if (b != 10) { + while (i < a) { + *(s+i) = '0'; // align with zeros + + i = i + 1; + } + } else if (sign) { + *(s+i) = '-'; + + i = i + 1; + } + + *(s+i) = 0; // null terminated string + + reverseString(s); + + return s; +} + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + + +void init (){ + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + 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 + + string_buffer = malloc(33*4); + + +} + + + + + +int main(){ + int* head; + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + init(); + + //lock(); + //print("something"); + //putchar(CHAR_LF); + + printString('W','i','t','h',' ','L','o','c','k',' ',0,0,0,0,0,0,0,0,0,0); + putchar(CHAR_LF); + + //unlock(); + + //lock(); + //print("somethingElse"); + + + printString('W','i','t','h','o','u','t',' ','L','o','c','k',' ',0,0,0,0,0,0,0); + + putchar(CHAR_LF); + + // + + print(itoa(1, string_buffer, 10, 0)); + + print(itoa(2, string_buffer, 10, 0)); + print(itoa(3, string_buffer, 10, 0)); + print(itoa(4, string_buffer, 10, 0)); + print(itoa(5, string_buffer, 10, 0)); + putchar(CHAR_LF); + sched_yield(); + print(itoa(6, string_buffer, 10, 0)); + print(itoa(7, string_buffer, 10, 0)); + print(itoa(8, string_buffer, 10, 0)); + print(itoa(9, string_buffer, 10, 0)); + putchar(CHAR_LF); + + //switch(); + sched_yield(); + + + + exit(0); +} \ No newline at end of file