diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..83676fa --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +CC_OSX := clang +CC_OPT_OSX := -w -m32 -g -undefined dynamic_lookup -D'main(a, b)=main(int argc, char **argv)' +CC_LINUX := gcc +CC_OPT_LINUX := -w -m32 -Wl,--unresolved-symbols=ignore-in-object-files -D'main(a, b)=main(int argc, char **argv)' +EXEC := selfie +MEM_SIZE := 32 +RTS1 := 2 +RTS2 := 10 +RTS3 := 100 +TEST_INPUT := treiber.c +TEST_BINARY := myprog.mips +OS_BINARY := os.mips +KERNEL_BINARY := kernel.mips + +all: test_binary_linux + +clena: clean +clan: clean +clane: clean +claen: clean +cean: clean +calen: clean +clea: clean +cclean: clean +lcean: clean + +compile_osx: + $(CC_OSX) $(CC_OPT_OSX) $(EXEC).c -o $(EXEC) + +test_binary_osx: + $(CC_OSX) $(CC_OPT_OSX) $(EXEC).c -o $(EXEC) + touch $(TEST_BINARY) + touch $(KERNEL_BINARY) + ./$(EXEC) -c $(TEST_INPUT) -o $(TEST_BINARY) + ./$(EXEC) -c $(EXEC).c -o $(KERNEL_BINARY) + ./$(EXEC) -k 64 $(KERNEL_BINARY) -l $(TEST_BINARY) -m 16 + +compile_linux: + $(CC_LINUX) $(CC_OPT_LINUX) $(EXEC).c -o $(EXEC) + +test_binary_linux: + $(CC_LINUX) $(CC_OPT_LINUX) $(EXEC).c -o $(EXEC) + touch $(TEST_BINARY) + touch $(KERNEL_BINARY) + ./$(EXEC) -c $(TEST_INPUT) -o $(TEST_BINARY) + ./$(EXEC) -c $(EXEC).c -o $(KERNEL_BINARY) + ./$(EXEC) -k 64 $(KERNEL_BINARY) -l $(TEST_BINARY) -m 16 + +debug: + ggdb --args ./$(EXEC) -k 64 $(KERNEL_BINARY) -l $(TEST_BINARY) -m 16 + +clean: + rm -f *.mips* + rm -f $(EXEC) + rm -f out + rm -f $(TEST_BINARY) + rm -f out.txt + rm -f *~ + rm -f *.s diff --git a/selfie.c b/selfie.c index f433dff..f8328b6 100644 --- a/selfie.c +++ b/selfie.c @@ -82,11 +82,11 @@ int twoToThePowerOf(int p); int leftShift(int n, int b); int rightShift(int n, int b); -int stringLength(int *s); +int stringLength(int *s); void stringReverse(int *s); -int stringCompare(int *s, int *t); +int stringCompare(int *s, int *t); -int atoi(int *s); +int atoi(int *s); int* itoa(int n, int *s, int b, int a, int p); void putCharacter(int character); @@ -102,30 +102,30 @@ 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_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 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; @@ -148,35 +148,35 @@ int S_IRUSR_IWUSR_IRGRP_IROTH = 420; // flags for rw-r--r-- file permissions // ------------------------ GLOBAL VARIABLES ----------------------- int *outputName = (int*) 0; -int outputFD = 1; +int outputFD = 1; // ------------------------- INITIALIZATION ------------------------ void initLibrary() { - int i; + int i; - power_of_two_table = malloc(31*4); + power_of_two_table = malloc(31 * 4); - *power_of_two_table = 1; // 2^0 + *power_of_two_table = 1; // 2^0 - i = 1; + i = 1; - while (i < 31) { - *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; - i = i + 1; - } + i = i + 1; + } - // computing INT_MAX and INT_MIN without overflows - INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; - INT_MIN = -INT_MAX - 1; + // computing INT_MAX and INT_MIN without overflows + INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; + INT_MIN = -INT_MAX - 1; - character_buffer = malloc(1); + character_buffer = malloc(1); - // accommodate at least 32-bit numbers for itoa - string_buffer = malloc(33); + // accommodate at least 32-bit numbers for itoa + string_buffer = malloc(33); - io_buffer = malloc(4); + io_buffer = malloc(4); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -213,106 +213,106 @@ 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_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 SYM_LBRACE = 15; // { +int SYM_RBRACE = 16; // } +int SYM_WHILE = 17; // WHILE +int SYM_RETURN = 18; // RETURN +int SYM_COMMA = 19; // , +int SYM_LT = 20; // < +int SYM_LEQ = 21; // <= +int SYM_GT = 22; // > +int SYM_GEQ = 23; // >= +int SYM_NOTEQ = 24; // != +int SYM_MOD = 25; // % +int SYM_CHARACTER = 26; // character +int SYM_STRING = 27; // string int *SYMBOLS; // array of strings representing symbols int maxIdentifierLength = 64; // maximum number of characters in an identifier -int maxIntegerLength = 10; // maximum number of characters in an integer -int maxStringLength = 128; // maximum number of characters in a string +int maxIntegerLength = 10; // maximum number of characters in an integer +int maxStringLength = 128; // 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 *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 isINTMINConstant = 0; int character; // most recently read character int symbol; // most recently recognized symbol int *sourceName = (int*) 0; // name of source file -int sourceFD = 0; // file descriptor of open source file +int sourceFD = 0; // file descriptor of open source file // ------------------------- 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 = CHAR_EOF; - symbol = SYM_EOF; +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 = CHAR_EOF; + symbol = SYM_EOF; } void resetScanner() { - lineNumber = 1; + lineNumber = 1; - getCharacter(); - getSymbol(); + getCharacter(); + getSymbol(); } // ----------------------------------------------------------------- @@ -321,7 +321,8 @@ void resetScanner() { void resetGlobalSymbolTable(); -void createSymbolTableEntry(int which, int *string, int line, int class, int type, int value, int reference); +void createSymbolTableEntry(int which, int *string, int line, int class, + int type, int value, int reference); int* getSymbolTableEntry(int *string, int class, int *symbol_table); int isUndefinedProcedure(int *entry); @@ -329,12 +330,12 @@ int reportUndefinedProcedures(int *symbol_table); int* getNext(int *entry); int* getString(int *entry); -int getLineNumber(int *entry); -int getClass(int *entry); -int getType(int *entry); -int getValue(int *entry); -int getReference(int *entry); -int getRegister(int *entry); +int getLineNumber(int *entry); +int getClass(int *entry); +int getType(int *entry); +int getValue(int *entry); +int getReference(int *entry); +int getRegister(int *entry); void setNext(int *entry, int *next); void setString(int *entry, int *identifier); @@ -350,27 +351,27 @@ void setRegister(int *entry, int reg); // classes int VARIABLE = 1; int FUNCTION = 2; -int STRING = 3; +int STRING = 3; // types -int INT_T = 1; +int INT_T = 1; int INTSTAR_T = 2; -int VOID_T = 3; +int VOID_T = 3; // symbol tables int GLOBAL_TABLE = 1; -int LOCAL_TABLE = 2; +int LOCAL_TABLE = 2; // ------------------------ GLOBAL VARIABLES ----------------------- // table pointers int *global_symbol_table = (int*) 0; -int *local_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; // ------------------------- INITIALIZATION ------------------------ void resetGlobalSymbolTable() { - global_symbol_table = (int*) 0; + global_symbol_table = (int*) 0; } // ----------------------------------------------------------------- @@ -396,24 +397,24 @@ int* putType(int type); void typeWarning(int expected, int found); int* getVariable(int *variable); -int load_variable(int *variable); +int load_variable(int *variable); void load_integer(); void load_string(); -int help_call_codegen(int *entry, int *procedure); +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(); +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(); +int gr_type(); void gr_variable(int offset); void gr_initialization(int *name, int offset, int type); void gr_procedure(int *procedure, int returnType); @@ -425,7 +426,7 @@ int allocatedTemporaries = 0; // number of allocated temporaries int allocatedMemory = 0; // number of bytes for global variables and strings -int returnBranches = 0; // fixup chain for return statements +int returnBranches = 0; // fixup chain for return statements int *currentProcedureName = (int*) 0; // name of currently parsed procedure @@ -496,40 +497,40 @@ 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"; + 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"; } // ----------------------------------------------------------------- @@ -566,74 +567,75 @@ 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 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_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 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 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"; + 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"; } // ----------------------------------------------------------------- // ----------------------------- CODE ------------------------------ // ----------------------------------------------------------------- -int loadBinary(int addr); +int loadBinary(int addr); +int loadKernelBinary(int addr); void storeBinary(int addr, int instruction); void storeInstruction(int addr, int instruction); @@ -653,11 +655,18 @@ void emitGlobalsStrings(); void emit(); void load(); +void loadKernel(); // ------------------------ GLOBAL CONSTANTS ----------------------- int maxBinaryLength = 131072; // 128KB +int maxKernelBinaryLength = 131072; // 128KB + +int PAGE_FRAME_SIZE = 4096; // 4kB + +int SHARED_MEMORY_SIZE = 4096; + // ------------------------ GLOBAL VARIABLES ----------------------- int *binary = (int*) 0; // binary of emitted instructions @@ -666,12 +675,22 @@ int binaryLength = 0; // length of binary in bytes incl. globals & strings int codeLength = 0; // length of code portion of binary in bytes -int *binaryName = (int*) 0; // file name of binary +int *binaryName = (int*) 0; // file name of binary int *sourceLineNumber = (int*) 0; // source line number per emitted instruction int *assemblyName = (int*) 0; // name of assembly file -int assemblyFD = 0; // file descriptor of open assembly file +int assemblyFD = 0; // file descriptor of open assembly file + +int *kernelBinary = (int*) 0; // binary of the kernel + +int kernelBinaryLength = 0; // length of kernel binary in bytes incl. globals & strings + +int kernelCodeLength = 0; // length of code portion of kernel binary in bytes + +int *kernelBinaryName = (int*) 0; // file name of kernel binary + +int* lockOwner = (int*) 0; // ----------------------------------------------------------------- // --------------------------- SYSCALLS ---------------------------- @@ -692,15 +711,60 @@ void syscall_open(); void emitMalloc(); void syscall_malloc(); +void emitPMem(); +void syscall_pmem(); + void emitPutchar(); +void emitFork(); +void syscall_fork(); + +void emitWait(); +void syscall_wait(); + +void emitLock(); +void syscall_lock(); + +void emitUnlock(); +void syscall_unlock(); + +void emitYield(); +void syscall_yield(); + +void emitCAS(); +void compare_and_swap(); + +void emitThreadFork(); +void syscall_thread_fork(); + // ------------------------ GLOBAL CONSTANTS ----------------------- -int SYSCALL_EXIT = 4001; -int SYSCALL_READ = 4003; -int SYSCALL_WRITE = 4004; -int SYSCALL_OPEN = 4005; +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; int SYSCALL_MALLOC = 5001; +int SYSCALL_PMEM = 5002; + +int SYSCALL_FORK = 4006; +int SYSCALL_WAIT = 4007; +int SYSCALL_LOCK = 4008; +int SYSCALL_YIELD = 4009; +int SYSCALL_UNLOCK = 4010; +int SYSCALL_FORK_THREAD = 4011; + +int COMPARE_AND_SWAP = 9001; + +int PAGE_FAULT = 6001; + +int HYPERCALL_CREATE_CONTEXT = 7003; +int HYPERCALL_SWITCH_CONTEXT = 7002; +int HYPERCALL_MAP_PAGE_IN_CONTEXT = 7004; +int DEL_CTXT = 7004; +int FLUSH_PAGE = 7005; + +int LOCK_BLOCK = 8001; +int WAIT_FOR_CHILD_BLOCK = 8002; // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -716,30 +780,126 @@ void initMemory(int bytes); int tlb(int vaddr); -int loadMemory(int vaddr); +int loadMemory(int vaddr); void storeMemory(int vaddr, int data); +int* palloc(); + +// ----------------------------------------------------------------- +// --------------------------- Context ----------------------------- +// ----------------------------------------------------------------- + +int* contextInsert(int contextId, int pc, int* registers, int* page_table, + int* prev, int* next); +int* contextFindContextByPID(int* contexts, int contextId); +int* processFindByPID(int pid); + +void context_setPID(int* node, int contextId); +void context_setPC(int* node, int pc); +void context_setRegisters(int* node, int registers); +void context_setPageTable(int* node, int page_table); +void context_setPrev(int* node, int prev); +void context_setNext(int* node, int next); + +int context_getPC(int* node); +int* context_getRegisters(int* node); +int* context_getPageTable(int* node); +int* context_getPrev(int* node); +int* context_getNext(int* node); +int context_getPID(int* node); + +int* osCreateProcess(int pid, int* prev, int* next); +int* osProcessForkThread(int* osProcess, int pid); +int* osProcessReady(int* unblockedProcess); +int* osDeleteProcess(int* node, int* processList); +int* osFindProcess(int pid, int* processList); + +int* osBlockedQFindProcess(int pid); +int* osBlockedQFindProcessByReason(int pid, int reason); + +int* osBlockProcess(int* process, int reason, int arg); +int* osUnBlockProcess(int pid); + +int* osZombifyProcess(int pid); +int* osUnzombifyProcess(int pid); + +int* tPageTable(int* threadPT, int* parentProcessPT); + +void freePageTable(int* page_table, int pid); + +// ----------------------------------------------------------------- +// ------------------------- PAGE TABLE --------------------------- +// ----------------------------------------------------------------- + +int* pagetable_getAddrAtIndex(int* pagetable, int idx); +void pagetable_setAddrAtIndex(int* pagetable, int idx, int data); + +int* pagetable_create(); + +void copyPageFrame(int* oldFrame, int* newFrame); + +// ----------------------------------------------------------------- +// -------------------- Emulator Helper Functions ------------------ +// ----------------------------------------------------------------- + +int* scheduleNextContext(int* list, int contextId); +void saveContext(); +void restoreContext(int contextId); +int createKernelContext(); + +// ----------------------------------------------------------------- +// -------------------------- HYPERCALLS --------------------------- +// ----------------------------------------------------------------- + +void emitCreateContext(); +void emitSwitchContext(); +void emitMapPageInContext(); + +void hypercall_create_context(); +void hypercall_switch_context(); +void hypercall_map_page_in_context(); +void delete_context(); +void flush_page_in_context(); + // ------------------------ GLOBAL CONSTANTS ----------------------- int MEGABYTE = 1048576; +int PAGE_TABLE_SIZE = 1024; + // ------------------------ GLOBAL VARIABLES ----------------------- int memorySize = 0; // size of memory in bytes int *memory = (int*) 0; // mipster memory +int *osProcessList = (int*) 0; // List of contexts +int *osBlockedQueue = (int*) 0; +int *osZombieQueue = (int*) 0; + +int nextFreeContextId = 0; + +int* current_page_table; + +int* osCurrentProcess; + +int kernel_mode; // Set to true because we boot into the kernel mode + +int *free_list; // List of free page frames + // ------------------------- INITIALIZATION ------------------------ void initMemory(int bytes) { - if (bytes < 0) - memorySize = 64 * MEGABYTE; - else if (bytes > 1024 * MEGABYTE) - memorySize = 1024 * MEGABYTE; - else - memorySize = bytes; - memory = malloc(memorySize); + if (bytes < 0) + memorySize = 64 * MEGABYTE; + else if (bytes > 1024 * MEGABYTE) + memorySize = 1024 * MEGABYTE; + else + memorySize = bytes; + + memory = malloc(memorySize); + } // ----------------------------------------------------------------- @@ -781,16 +941,17 @@ void execute(); void run(); void up_push(int value); -int up_malloc(int size); -int up_copyString(int *s); +int up_malloc(int size); +int up_copyString(int *s); void up_copyArguments(int argc, int *argv); void copyBinaryToMemory(); +void copyKernelBinaryToMemory(); int addressWithMaxCounter(int *counters, int max); int fixedPointRatio(int a, int b); -int printCounters(int total, int *counters, int max); +int printCounters(int total, int *counters, int max); void printProfile(int *message, int total, int *counters); void disassemble(); @@ -798,17 +959,17 @@ void emulate(int argc, int *argv); // ------------------------ GLOBAL CONSTANTS ----------------------- -int debug_read = 0; -int debug_write = 0; -int debug_open = 0; -int debug_malloc = 0; +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; -int EXCEPTION_SIGNAL = 1; -int EXCEPTION_ADDRESSERROR = 2; +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_HEAPOVERFLOW = 4; +int EXCEPTION_UNKNOWNSYSCALL = 5; +int EXCEPTION_UNKNOWNFUNCTION = 6; int *EXCEPTIONS; // array of strings representing exceptions @@ -828,52 +989,54 @@ int interpret = 0; int debug = 0; -int calls = 0; // total number of executed procedure calls +int calls = 0; // total number of executed procedure calls int *callsPerAddress = (int*) 0; // number of executed calls of each procedure -int loops = 0; // total number of executed loop iterations +int loops = 0; // total number of executed loop iterations int *loopsPerAddress = (int*) 0; // number of executed iterations of each loop -int loads = 0; // total number of executed memory loads +int loads = 0; // total number of executed memory loads int *loadsPerAddress = (int*) 0; // number of executed loads per load operation -int stores = 0; // total number of executed memory stores +int stores = 0; // total number of executed memory stores int *storesPerAddress = (int*) 0; // number of executed stores per store operation +int nextContextId = -1; + // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { - EXCEPTIONS = malloc(7*4); + EXCEPTIONS = malloc(7 * 4); - *(EXCEPTIONS + EXCEPTION_SIGNAL) = (int) "signal"; - *(EXCEPTIONS + EXCEPTION_ADDRESSERROR) = (int) "address error"; - *(EXCEPTIONS + EXCEPTION_UNKNOWNINSTRUCTION) = (int) "unknown instruction"; - *(EXCEPTIONS + EXCEPTION_HEAPOVERFLOW) = (int) "heap overflow"; - *(EXCEPTIONS + EXCEPTION_UNKNOWNSYSCALL) = (int) "unknown syscall"; - *(EXCEPTIONS + EXCEPTION_UNKNOWNFUNCTION) = (int) "unknown function"; + *(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); + registers = malloc(32 * 4); } void resetInterpreter() { - pc = 0; + pc = 0; - reg_hi = 0; - reg_lo = 0; + reg_hi = 0; + reg_lo = 0; - if (interpret) { - calls = 0; - callsPerAddress = malloc(maxBinaryLength); + if (interpret) { + calls = 0; + callsPerAddress = malloc(maxBinaryLength); - loops = 0; - loopsPerAddress = malloc(maxBinaryLength); + loops = 0; + loopsPerAddress = malloc(maxBinaryLength); - loads = 0; - loadsPerAddress = malloc(maxBinaryLength); + loads = 0; + loadsPerAddress = malloc(maxBinaryLength); - stores = 0; - storesPerAddress = malloc(maxBinaryLength); - } + stores = 0; + storesPerAddress = malloc(maxBinaryLength); + } } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -887,319 +1050,320 @@ void resetInterpreter() { // ----------------------------------------------------------------- int twoToThePowerOf(int p) { - // assert: 0 <= p < 31 - return *(power_of_two_table + p); + // assert: 0 <= p < 31 + return *(power_of_two_table + p); } int leftShift(int n, int b) { - // assert: b >= 0; + // assert: b >= 0; - if (b > 30) - return 0; - else - return n * twoToThePowerOf(b); + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); } int rightShift(int n, int b) { - // assert: b >= 0 + // assert: b >= 0 - if (b > 30) - return 0; - else if (n >= 0) - return n / twoToThePowerOf(b); - else - // works even if n == INT_MIN: - // shift right n with msb reset and then restore msb - return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + - (INT_MAX / twoToThePowerOf(b) + 1); + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN: + // shift right n with msb reset and then restore msb + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); } int loadCharacter(int *s, int i) { - // assert: i >= 0 - int a; + // assert: i >= 0 + int a; - a = i / 4; + a = i / 4; - return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); } int* storeCharacter(int *s, int i, int c) { - // assert: i >= 0, all characters are 7-bit - int a; + // assert: i >= 0, all characters are 7-bit + int a; - a = i / 4; + a = i / 4; - *(s + a) = (*(s + a) - leftShift(loadCharacter(s, i), (i % 4) * 8)) + leftShift(c, (i % 4) * 8); - - return s; + *(s + a) = (*(s + a) - leftShift(loadCharacter(s, i), (i % 4) * 8)) + + leftShift(c, (i % 4) * 8); + + return s; } int stringLength(int *s) { - int i; + int i; - i = 0; + i = 0; - while (loadCharacter(s, i) != 0) - i = i + 1; + while (loadCharacter(s, i) != 0) + i = i + 1; - return i; + return i; } void stringReverse(int *s) { - int i; - int j; - int tmp; + int i; + int j; + int tmp; + + i = 0; + j = stringLength(s) - 1; - i = 0; - j = stringLength(s) - 1; + while (i < j) { + tmp = loadCharacter(s, i); - while (i < j) { - tmp = loadCharacter(s, i); - - storeCharacter(s, i, loadCharacter(s, j)); - storeCharacter(s, j, tmp); + storeCharacter(s, i, loadCharacter(s, j)); + storeCharacter(s, j, tmp); - i = i + 1; - j = j - 1; - } + i = i + 1; + j = j - 1; + } } int stringCompare(int *s, int *t) { - int i; + int i; - i = 0; + i = 0; - while (1) - if (loadCharacter(s, i) == 0) - if (loadCharacter(t, i) == 0) - return 1; - else - return 0; - else if (loadCharacter(s, i) == loadCharacter(t, i)) - i = i + 1; - else - return 0; + while (1) + if (loadCharacter(s, i) == 0) + if (loadCharacter(t, i) == 0) + return 1; + else + return 0; + else if (loadCharacter(s, i) == loadCharacter(t, i)) + i = i + 1; + else + return 0; } int atoi(int *s) { - int i; - int n; - int c; + int i; + int n; + int c; - i = 0; + i = 0; - n = 0; + n = 0; - c = loadCharacter(s, i); + c = loadCharacter(s, i); - while (c != 0) { - c = c - '0'; + while (c != 0) { + c = c - '0'; - if (c < 0) - return -1; - else if (c > 9) - return -1; + if (c < 0) + return -1; + else if (c > 9) + return -1; - n = n * 10 + c; - - i = i + 1; + n = n * 10 + c; - c = loadCharacter(s, i); + i = i + 1; - if (n < 0) { - if (n != INT_MIN) - return -1; - else if (c != 0) - return -1; - } - } + c = loadCharacter(s, i); + + if (n < 0) { + if (n != INT_MIN) + return -1; + else if (c != 0) + return -1; + } + } - return n; + return n; } int* itoa(int n, int *s, int b, int a, int p) { - // assert: b in {2,4,8,10,16} + // assert: b in {2,4,8,10,16} + + int i; + int sign; + int msb; + + i = 0; + + sign = 0; + + msb = 0; + + if (n == 0) { + storeCharacter(s, 0, '0'); + + i = 1; + } else if (n < 0) { + sign = 1; - int i; - int sign; - int msb; + if (b == 10) { + if (n == INT_MIN) { + // rightmost decimal digit of 32-bit INT_MIN + storeCharacter(s, 0, '8'); - i = 0; + // avoids overflow + n = -(n / 10); + i = 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + // rightmost non-decimal digit of INT_MIN + storeCharacter(s, 0, '0'); - sign = 0; + // avoids setting n to 0 + n = (rightShift(INT_MIN, 1) / b) * 2; + i = 1; + } else { + // reset msb, restore below + n = rightShift(leftShift(n, 1), 1); + msb = 1; + } + } - msb = 0; + // assert: n > 0 + } - if (n == 0) { - storeCharacter(s, 0, '0'); + while (n != 0) { + if (p > 0) + if (i == p) { + storeCharacter(s, i, '.'); // set point of fixed point number - i = 1; - } else if (n < 0) { - sign = 1; + i = i + 1; + p = 0; + } - if (b == 10) { - if (n == INT_MIN) { - // rightmost decimal digit of 32-bit INT_MIN - storeCharacter(s, 0, '8'); + if (n % b > 9) + storeCharacter(s, i, n % b - 10 + 'A'); + else + storeCharacter(s, i, n % b + '0'); - // avoids overflow - n = -(n / 10); - i = 1; - } else - n = -n; - } else { - if (n == INT_MIN) { - // rightmost non-decimal digit of INT_MIN - storeCharacter(s, 0, '0'); - - // avoids setting n to 0 - n = (rightShift(INT_MIN, 1) / b) * 2; - i = 1; - } else { - // reset msb, restore below - n = rightShift(leftShift(n, 1), 1); - msb = 1; - } - } - - // assert: n > 0 - } - - while (n != 0) { - if (p > 0) - if (i == p) { - storeCharacter(s, i, '.'); // set point of fixed point number - - i = i + 1; - p = 0; - } - - if (n % b > 9) - storeCharacter(s, i, n % b - 10 + 'A'); - else - storeCharacter(s, i, n % b + '0'); - - n = n / b; - i = i + 1; - - if (msb == 1) { - // restore msb from above - n = n + (rightShift(INT_MIN, 1) / b) * 2; - msb = 0; - } - } - - if (p > 0) { - while (i < p) { - storeCharacter(s, i, '0'); // no point yet, fill with 0s + n = n / b; + i = i + 1; - i = i + 1; - } + if (msb == 1) { + // restore msb from above + n = n + (rightShift(INT_MIN, 1) / b) * 2; + msb = 0; + } + } - storeCharacter(s, i, '.'); // set point - storeCharacter(s, i + 1, '0'); // leading 0 + if (p > 0) { + while (i < p) { + storeCharacter(s, i, '0'); // no point yet, fill with 0s - i = i + 2; - p = 0; - } + i = i + 1; + } - if (b == 10) { - if (sign) { - storeCharacter(s, i, '-'); // negative decimal numbers start with - + storeCharacter(s, i, '.'); // set point + storeCharacter(s, i + 1, '0'); // leading 0 - i = i + 1; - } + i = i + 2; + p = 0; + } - while (i < a) { - storeCharacter(s, i, ' '); // align with spaces + if (b == 10) { + if (sign) { + storeCharacter(s, i, '-'); // negative decimal numbers start with - - i = i + 1; - } - } else { - while (i < a) { - storeCharacter(s, i, '0'); // align with 0s + i = i + 1; + } - i = i + 1; - } + while (i < a) { + storeCharacter(s, i, ' '); // align with spaces - if (b == 8) { - storeCharacter(s, i, '0'); // octal numbers start with 00 - storeCharacter(s, i + 1, '0'); + i = i + 1; + } + } else { + while (i < a) { + storeCharacter(s, i, '0'); // align with 0s - i = i + 2; - } else if (b == 16) { - storeCharacter(s, i, 'x'); // hexadecimal numbers start with 0x - storeCharacter(s, i + 1, '0'); + i = i + 1; + } - i = i + 2; - } - } - - storeCharacter(s, i, 0); // null terminated string + if (b == 8) { + storeCharacter(s, i, '0'); // octal numbers start with 00 + storeCharacter(s, i + 1, '0'); - stringReverse(s); + i = i + 2; + } else if (b == 16) { + storeCharacter(s, i, 'x'); // hexadecimal numbers start with 0x + storeCharacter(s, i + 1, '0'); + + i = i + 2; + } + } + + storeCharacter(s, i, 0); // null terminated string - return s; + stringReverse(s); + + return s; } void putCharacter(int character) { - if (outputFD == 1) - putchar(character); - else { - *character_buffer = character; + if (outputFD == 1) + putchar(character); + else { + *character_buffer = character; - if (write(outputFD, character_buffer, 1) != 1) { - outputFD = 1; + if (write(outputFD, character_buffer, 1) != 1) { + outputFD = 1; - print(selfieName); - print((int*) ": could not write character to output file "); - print(outputName); - println(); + print(selfieName); + print((int*) ": could not write character to output file "); + print(outputName); + println(); - exit(-1); - } - } + exit(-1); + } + } } void print(int *s) { - int i; + int i; - i = 0; + i = 0; - while (loadCharacter(s, i) != 0) { - putCharacter(loadCharacter(s, i)); + while (loadCharacter(s, i) != 0) { + putCharacter(loadCharacter(s, i)); - i = i + 1; - } + i = i + 1; + } } void println() { - putCharacter(CHAR_LF); + putCharacter(CHAR_LF); } void printCharacter(int character) { - putCharacter(CHAR_SINGLEQUOTE); + putCharacter(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 - putCharacter(character); + if (character == CHAR_EOF) + print((int*) "end of file"); + else if (character == CHAR_TAB) + print((int*) "tabulator"); + else if (character == CHAR_LF) + print((int*) "line feed"); + else if (character == CHAR_CR) + print((int*) "carriage return"); + else + putCharacter(character); - putCharacter(CHAR_SINGLEQUOTE); + putCharacter(CHAR_SINGLEQUOTE); } void printString(int *s) { - putCharacter(CHAR_DOUBLEQUOTE); + putCharacter(CHAR_DOUBLEQUOTE); - print(s); - - putCharacter(CHAR_DOUBLEQUOTE); + print(s); + + putCharacter(CHAR_DOUBLEQUOTE); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -1213,572 +1377,574 @@ void printString(int *s) { // ----------------------------------------------------------------- void printSymbol(int symbol) { - putCharacter(CHAR_DOUBLEQUOTE); + putCharacter(CHAR_DOUBLEQUOTE); - if (symbol == SYM_EOF) - print((int*) "end of file"); - else - print((int*) *(SYMBOLS + symbol)); + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); - putCharacter(CHAR_DOUBLEQUOTE); + putCharacter(CHAR_DOUBLEQUOTE); } void printLineNumber(int* message, int line) { - print(selfieName); - print((int*) ": "); - print(message); - print((int*) " in "); - print(sourceName); - print((int*) " in line "); - print(itoa(line, string_buffer, 10, 0, 0)); - print((int*) ": "); + print(selfieName); + print((int*) ": "); + print(message); + print((int*) " in "); + print(sourceName); + print((int*) " in line "); + print(itoa(line, string_buffer, 10, 0, 0)); + print((int*) ": "); } void syntaxErrorMessage(int *message) { - printLineNumber((int*) "error", lineNumber); + printLineNumber((int*) "error", lineNumber); + + print(message); - print(message); - - println(); + println(); } void syntaxErrorCharacter(int expected) { - printLineNumber((int*) "error", lineNumber); + printLineNumber((int*) "error", lineNumber); - printCharacter(expected); - print((int*) " expected but "); + printCharacter(expected); + print((int*) " expected but "); - printCharacter(character); - print((int*) " found"); + printCharacter(character); + print((int*) " found"); - println(); + println(); } void getCharacter() { - int numberOfReadBytes; + int numberOfReadBytes; - numberOfReadBytes = read(sourceFD, character_buffer, 1); + numberOfReadBytes = read(sourceFD, character_buffer, 1); - if (numberOfReadBytes == 1) - character = *character_buffer; - else if (numberOfReadBytes == 0) - character = CHAR_EOF; - else { - print(selfieName); - print((int*) ": could not read character from input file "); - print(sourceName); - println(); + if (numberOfReadBytes == 1) + character = *character_buffer; + else if (numberOfReadBytes == 0) + character = CHAR_EOF; + else { + print(selfieName); + print((int*) ": could not read character from input file "); + print(sourceName); + println(); - exit(-1); - } + exit(-1); + } } int isCharacterWhitespace() { - if (character == CHAR_SPACE) - return 1; - else if (character == CHAR_TAB) - return 1; - else if (character == CHAR_LF) - return 1; - else if (character == CHAR_CR) - return 1; - else - return 0; + 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; + int inComment; - inComment = 0; + inComment = 0; - while (1) { - if (inComment) { - getCharacter(); + while (1) { + if (inComment) { + getCharacter(); - if (character == CHAR_LF) - inComment = 0; - else if (character == CHAR_CR) - inComment = 0; - else if (character == CHAR_EOF) - return character; + 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; + } else if (isCharacterWhitespace()) { + if (character == CHAR_LF) + lineNumber = lineNumber + 1; + else if (character == CHAR_CR) + lineNumber = lineNumber + 1; - getCharacter(); + getCharacter(); - } else if (character == CHAR_HASH) { - getCharacter(); + } else if (character == CHAR_HASH) { + getCharacter(); - inComment = 1; + inComment = 1; - } else if (character == CHAR_SLASH) { - getCharacter(); + } else if (character == CHAR_SLASH) { + getCharacter(); - if (character == CHAR_SLASH) - inComment = 1; - else { - symbol = SYM_DIV; - return character; - } + if (character == CHAR_SLASH) + inComment = 1; + else { + symbol = SYM_DIV; + return character; + } - } else - 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; + 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; + 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; + 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; + 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)); + 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; + 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; + int i; - symbol = SYM_EOF; + 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 (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); + if (isCharacterLetter()) { + identifier = malloc(maxIdentifierLength + 1); - i = 0; + i = 0; - while (isCharacterLetterOrDigitOrUnderscore()) { - if (i >= maxIdentifierLength) { - syntaxErrorMessage((int*) "identifier too long"); - exit(-1); - } + while (isCharacterLetterOrDigitOrUnderscore()) { + if (i >= maxIdentifierLength) { + syntaxErrorMessage((int*) "identifier too long"); + exit(-1); + } - storeCharacter(identifier, i, character); + storeCharacter(identifier, i, character); - i = i + 1; + i = i + 1; - getCharacter(); - } + getCharacter(); + } - storeCharacter(identifier, i, 0); // null terminated string + storeCharacter(identifier, i, 0); // null terminated string - symbol = identifierOrKeyword(); + symbol = identifierOrKeyword(); - } else if (isCharacterDigit()) { - integer = malloc(maxIntegerLength + 1); + } else if (isCharacterDigit()) { + integer = malloc(maxIntegerLength + 1); - i = 0; + i = 0; - while (isCharacterDigit()) { - if (i >= maxIntegerLength) { - syntaxErrorMessage((int*) "integer out of bound"); - exit(-1); - } + while (isCharacterDigit()) { + if (i >= maxIntegerLength) { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } - storeCharacter(integer, i, character); + storeCharacter(integer, i, character); - i = i + 1; - - getCharacter(); - } + i = i + 1; - storeCharacter(integer, i, 0); // null terminated string + getCharacter(); + } - constant = atoi(integer); + storeCharacter(integer, i, 0); // null terminated string - 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); - } - } + constant = atoi(integer); - symbol = SYM_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); + } + } - } else if (character == CHAR_SINGLEQUOTE) { - getCharacter(); + symbol = SYM_INTEGER; - constant = 0; + } else if (character == CHAR_SINGLEQUOTE) { + getCharacter(); - if (character == CHAR_EOF) { - syntaxErrorMessage((int*) "reached end of file looking for a character constant"); + constant = 0; - exit(-1); - } else - constant = character; + if (character == CHAR_EOF) { + syntaxErrorMessage( + (int*) "reached end of file looking for a character constant"); - getCharacter(); + exit(-1); + } else + constant = character; - if (character == CHAR_SINGLEQUOTE) - getCharacter(); - else if (character == CHAR_EOF) { - syntaxErrorCharacter(CHAR_SINGLEQUOTE); + getCharacter(); - exit(-1); - } else - syntaxErrorCharacter(CHAR_SINGLEQUOTE); + if (character == CHAR_SINGLEQUOTE) + getCharacter(); + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); - symbol = SYM_CHARACTER; + exit(-1); + } else + syntaxErrorCharacter(CHAR_SINGLEQUOTE); - } else if (character == CHAR_DOUBLEQUOTE) { - getCharacter(); + symbol = SYM_CHARACTER; - string = malloc(maxStringLength + 1); + } else if (character == CHAR_DOUBLEQUOTE) { + getCharacter(); - i = 0; + string = malloc(maxStringLength + 1); - while (isNotDoubleQuoteOrEOF()) { - if (i >= maxStringLength) { - syntaxErrorMessage((int*) "string too long"); - exit(-1); - } + i = 0; - storeCharacter(string, i, character); + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } - i = i + 1; - - getCharacter(); - } + storeCharacter(string, i, character); - if (character == CHAR_DOUBLEQUOTE) - getCharacter(); - else { - syntaxErrorCharacter(CHAR_DOUBLEQUOTE); + i = i + 1; - exit(-1); - } + getCharacter(); + } - storeCharacter(string, i, 0); // null terminated string + if (character == CHAR_DOUBLEQUOTE) + getCharacter(); + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); - symbol = SYM_STRING; + exit(-1); + } - } else if (character == CHAR_SEMICOLON) { - getCharacter(); + storeCharacter(string, i, 0); // null terminated string - symbol = SYM_SEMICOLON; + symbol = SYM_STRING; - } else if (character == CHAR_PLUS) { - getCharacter(); + } else if (character == CHAR_SEMICOLON) { + getCharacter(); - symbol = SYM_PLUS; + symbol = SYM_SEMICOLON; - } else if (character == CHAR_DASH) { - getCharacter(); + } else if (character == CHAR_PLUS) { + getCharacter(); - symbol = SYM_MINUS; + symbol = SYM_PLUS; - } else if (character == CHAR_ASTERISK) { - getCharacter(); + } else if (character == CHAR_DASH) { + getCharacter(); - symbol = SYM_ASTERISK; + symbol = SYM_MINUS; - } else if (character == CHAR_EQUAL) { - getCharacter(); + } else if (character == CHAR_ASTERISK) { + getCharacter(); - if (character == CHAR_EQUAL) { - getCharacter(); + symbol = SYM_ASTERISK; - symbol = SYM_EQUALITY; - } else - symbol = SYM_ASSIGN; + } else if (character == CHAR_EQUAL) { + getCharacter(); - } else if (character == CHAR_LPARENTHESIS) { - getCharacter(); + if (character == CHAR_EQUAL) { + getCharacter(); - symbol = SYM_LPARENTHESIS; + symbol = SYM_EQUALITY; + } else + symbol = SYM_ASSIGN; - } else if (character == CHAR_RPARENTHESIS) { - getCharacter(); + } else if (character == CHAR_LPARENTHESIS) { + getCharacter(); - symbol = SYM_RPARENTHESIS; + symbol = SYM_LPARENTHESIS; - } else if (character == CHAR_LBRACE) { - getCharacter(); + } else if (character == CHAR_RPARENTHESIS) { + getCharacter(); - symbol = SYM_LBRACE; + symbol = SYM_RPARENTHESIS; - } else if (character == CHAR_RBRACE) { - getCharacter(); + } else if (character == CHAR_LBRACE) { + getCharacter(); - symbol = SYM_RBRACE; + symbol = SYM_LBRACE; - } else if (character == CHAR_COMMA) { - getCharacter(); + } else if (character == CHAR_RBRACE) { + getCharacter(); - symbol = SYM_COMMA; + symbol = SYM_RBRACE; - } else if (character == CHAR_LT) { - getCharacter(); + } else if (character == CHAR_COMMA) { + getCharacter(); - if (character == CHAR_EQUAL) { - getCharacter(); + symbol = SYM_COMMA; - symbol = SYM_LEQ; - } else - symbol = SYM_LT; + } else if (character == CHAR_LT) { + getCharacter(); - } else if (character == CHAR_GT) { - getCharacter(); + if (character == CHAR_EQUAL) { + getCharacter(); - if (character == CHAR_EQUAL) { - getCharacter(); + symbol = SYM_LEQ; + } else + symbol = SYM_LT; - symbol = SYM_GEQ; - } else - symbol = SYM_GT; + } else if (character == CHAR_GT) { + getCharacter(); - } else if (character == CHAR_EXCLAMATION) { - getCharacter(); + if (character == CHAR_EQUAL) { + getCharacter(); - if (character == CHAR_EQUAL) - getCharacter(); - else - syntaxErrorCharacter(CHAR_EQUAL); + symbol = SYM_GEQ; + } else + symbol = SYM_GT; - symbol = SYM_NOTEQ; + } else if (character == CHAR_EXCLAMATION) { + getCharacter(); - } else if (character == CHAR_PERCENTAGE) { - getCharacter(); + if (character == CHAR_EQUAL) + getCharacter(); + else + syntaxErrorCharacter(CHAR_EQUAL); - symbol = SYM_MOD; + symbol = SYM_NOTEQ; - } else { - printLineNumber((int*) "error", lineNumber); - print((int*) "found unknown character "); - printCharacter(character); - - println(); + } else if (character == CHAR_PERCENTAGE) { + getCharacter(); - exit(-1); - } + symbol = SYM_MOD; - return symbol; + } else { + printLineNumber((int*) "error", lineNumber); + print((int*) "found unknown character "); + printCharacter(character); + + println(); + + exit(-1); + } + + return symbol; } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void createSymbolTableEntry(int whichTable, int *string, int line, int class, int type, int value, int reference) { - int *newEntry; - - // symbol table entry: - // +----+-----------+ - // | 0 | next | pointer to next entry - // | 1 | string | identifier string, string constant - // | 2 | line | source line number - // | 3 | class | VARIABLE, FUNCTION, STRING - // | 4 | type | INT_T, INTSTAR_T, VOID_T - // | 5 | value | VARIABLE: constant value - // | 6 | reference | VARIABLE: offset, FUNCTION: address, STRING: offset - // | 7 | register | REG_GP, REG_FP - // +----+-----------+ - - newEntry = malloc(8 * 4); - - setString(newEntry, string); - setLineNumber(newEntry, line); - setClass(newEntry, class); - setType(newEntry, type); - setValue(newEntry, value); - setReference(newEntry, reference); - - // 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; - } +void createSymbolTableEntry(int whichTable, int *string, int line, int class, + int type, int value, int reference) { + int *newEntry; + + // symbol table entry: + // +----+-----------+ + // | 0 | next | pointer to next entry + // | 1 | string | identifier string, string constant + // | 2 | line | source line number + // | 3 | class | VARIABLE, FUNCTION, STRING + // | 4 | type | INT_T, INTSTAR_T, VOID_T + // | 5 | value | VARIABLE: constant value + // | 6 | reference | VARIABLE: offset, FUNCTION: address, STRING: offset + // | 7 | register | REG_GP, REG_FP + // +----+-----------+ + + newEntry = malloc(8 * 4); + + setString(newEntry, string); + setLineNumber(newEntry, line); + setClass(newEntry, class); + setType(newEntry, type); + setValue(newEntry, value); + setReference(newEntry, reference); + + // 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); - } + 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; + return (int*) 0; } int isUndefinedProcedure(int *entry) { - if (getClass(entry) == FUNCTION) { - if (getReference(entry) == 0) - return 1; - else if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) - return 1; - } - - return 0; + if (getClass(entry) == FUNCTION) { + if (getReference(entry) == 0) + return 1; + else if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) + return 1; + } + + return 0; } int reportUndefinedProcedures(int *symbol_table) { - int undefined; + int undefined; - undefined = 0; + undefined = 0; - while ((int) symbol_table != 0) { - if (isUndefinedProcedure(symbol_table)) { - undefined = 1; + while ((int) symbol_table != 0) { + if (isUndefinedProcedure(symbol_table)) { + undefined = 1; - printLineNumber((int*) "error", getLineNumber(symbol_table)); - print(getString(symbol_table)); - print((int*) " undefined"); - println(); - } + printLineNumber((int*) "error", getLineNumber(symbol_table)); + print(getString(symbol_table)); + print((int*) " undefined"); + println(); + } - // keep looking - symbol_table = getNext(symbol_table); - } + // keep looking + symbol_table = getNext(symbol_table); + } - return undefined; + return undefined; } int* getNext(int *entry) { - // cast only works if size of int and int* is equivalent - return (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); + // cast only works if size of int and int* is equivalent + return (int*) *(entry + 1); } int getLineNumber(int *entry) { - return *(entry + 2); + return *(entry + 2); } int getClass(int *entry) { - return *(entry + 3); + return *(entry + 3); } int getType(int *entry) { - return *(entry + 4); + return *(entry + 4); } int getValue(int *entry) { - return *(entry + 5); + return *(entry + 5); } int getReference(int *entry) { - return *(entry + 6); + return *(entry + 6); } int getRegister(int *entry) { - return *(entry + 7); + return *(entry + 7); } void setNext(int *entry, int *next) { - // cast only works if size of int and int* is equivalent - *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; + // cast only works if size of int and int* is equivalent + *(entry + 1) = (int) identifier; } void setLineNumber(int *entry, int line) { - *(entry + 2) = line; + *(entry + 2) = line; } void setClass(int *entry, int class) { - *(entry + 3) = class; + *(entry + 3) = class; } void setType(int *entry, int type) { - *(entry + 4) = type; + *(entry + 4) = type; } void setValue(int *entry, int value) { - *(entry + 5) = value; + *(entry + 5) = value; } void setReference(int *entry, int reference) { - *(entry + 6) = reference; + *(entry + 6) = reference; } void setRegister(int *entry, int reg) { - *(entry + 7) = reg; + *(entry + 7) = reg; } // ----------------------------------------------------------------- @@ -1786,1470 +1952,1503 @@ void setRegister(int *entry, int reg) { // ----------------------------------------------------------------- int isNotRbraceOrEOF() { - if (symbol == SYM_RBRACE) - return 0; - else if(symbol == SYM_EOF) - return 0; - else - return 1; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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_T7 for temporaries - if (allocatedTemporaries < REG_T7 - REG_A3) - allocatedTemporaries = allocatedTemporaries + 1; - else { - syntaxErrorMessage((int*) "out of registers"); + // we use registers REG_T0-REG_T7 for temporaries + if (allocatedTemporaries < REG_T7 - REG_A3) + allocatedTemporaries = allocatedTemporaries + 1; + else { + syntaxErrorMessage((int*) "out of registers"); - exit(-1); - } + exit(-1); + } } int currentTemporary() { - if (allocatedTemporaries > 0) - return allocatedTemporaries + REG_A3; - else { - syntaxErrorMessage((int*) "illegal register access"); + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); - exit(-1); - } + exit(-1); + } } int previousTemporary() { - if (allocatedTemporaries > 1) - return currentTemporary() - 1; - else { - syntaxErrorMessage((int*) "illegal register access"); + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); - exit(-1); - } + exit(-1); + } } int nextTemporary() { - if (allocatedTemporaries < REG_T7 - REG_A3) - return currentTemporary() + 1; - else { - syntaxErrorMessage((int*) "out of registers"); + if (allocatedTemporaries < REG_T7 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); - exit(-1); - } + exit(-1); + } } void tfree(int numberOfTemporaries) { - allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; + allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; - if (allocatedTemporaries < 0) { - syntaxErrorMessage((int*) "illegal register deallocation"); + if (allocatedTemporaries < 0) { + syntaxErrorMessage((int*) "illegal register deallocation"); - exit(-1); - } + exit(-1); + } } void save_temporaries() { - while (allocatedTemporaries > 0) { - // push temporary onto stack - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + while (allocatedTemporaries > 0) { + // push temporary onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); - tfree(1); - } + tfree(1); + } } void restore_temporaries(int numberOfTemporaries) { - while (allocatedTemporaries < numberOfTemporaries) { - talloc(); + while (allocatedTemporaries < numberOfTemporaries) { + talloc(); - // restore temporary from stack - emitIFormat(OP_LW, REG_SP, currentTemporary(), 0); - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - } + // restore temporary from stack + emitIFormat(OP_LW, REG_SP, currentTemporary(), 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + } } void syntaxErrorSymbol(int expected) { - printLineNumber((int*) "error", lineNumber); + printLineNumber((int*) "error", lineNumber); - printSymbol(expected); - print((int*) " expected but "); + printSymbol(expected); + print((int*) " expected but "); - printSymbol(symbol); - print((int*) " found"); + printSymbol(symbol); + print((int*) " found"); - println(); + println(); } void syntaxErrorUnexpected() { - printLineNumber((int*) "error", lineNumber); + printLineNumber((int*) "error", lineNumber); - print((int*) "unexpected symbol "); - printSymbol(symbol); - print((int*) " found"); + print((int*) "unexpected symbol "); + printSymbol(symbol); + print((int*) " found"); - println(); + 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"; + 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", lineNumber); + printLineNumber((int*) "warning", lineNumber); - print((int*) "type mismatch, "); + print((int*) "type mismatch, "); - print(putType(expected)); + print(putType(expected)); - print((int*) " expected but "); + print((int*) " expected but "); - print(putType(found)); + print(putType(found)); - print((int*) " found"); + print((int*) " found"); - println(); + println(); } int* getVariable(int *variable) { - int *entry; + int *entry; - entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); + entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); - if (entry == (int*) 0) { - entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); + if (entry == (int*) 0) { + entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); - if (entry == (int*) 0) { - printLineNumber((int*) "error", lineNumber); - print(variable); - print((int*) " undeclared"); - println(); + if (entry == (int*) 0) { + printLineNumber((int*) "error", lineNumber); + print(variable); + print((int*) " undeclared"); + println(); - exit(-1); - } - } + exit(-1); + } + } - return entry; + return entry; } int load_variable(int *variable) { - int *entry; + int *entry; - entry = getVariable(variable); + entry = getVariable(variable); - talloc(); + talloc(); - emitIFormat(OP_LW, getRegister(entry), currentTemporary(), getReference(entry)); + emitIFormat(OP_LW, getRegister(entry), currentTemporary(), + getReference(entry)); - return getType(entry); + return getType(entry); } void load_integer() { - // assert: constant >= 0 or constant == INT_MIN + // assert: constant >= 0 or constant == INT_MIN - talloc(); + 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)); + 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); + // 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)); + // 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); + emitLeftShiftBy(14); - // then add the next 14 msbs - emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 15), 18)); + // then add the next 14 msbs + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), + rightShift(leftShift(constant, 15), 18)); - emitLeftShiftBy(3); + 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 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); - } + // 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; + int l; - l = stringLength(string) + 1; + l = stringLength(string) + 1; - allocatedMemory = allocatedMemory + l; + allocatedMemory = allocatedMemory + l; - if (l % 4 != 0) - allocatedMemory = allocatedMemory + 4 - l % 4; + if (l % 4 != 0) + allocatedMemory = allocatedMemory + 4 - l % 4; - createSymbolTableEntry(GLOBAL_TABLE, string, lineNumber, STRING, INTSTAR_T, 0, -allocatedMemory); + createSymbolTableEntry(GLOBAL_TABLE, string, lineNumber, STRING, INTSTAR_T, + 0, -allocatedMemory); - talloc(); + talloc(); - emitIFormat(OP_ADDIU, REG_GP, currentTemporary(), -allocatedMemory); + emitIFormat(OP_ADDIU, REG_GP, currentTemporary(), -allocatedMemory); } int help_call_codegen(int *entry, int *procedure) { - int type; + int type; - if (entry == (int*) 0) { - // CASE 1: function call, no definition, no declaration. - createSymbolTableEntry(GLOBAL_TABLE, procedure, lineNumber, FUNCTION, INT_T, 0, binaryLength); + if (entry == (int*) 0) { + // CASE 1: function call, no definition, no declaration. + createSymbolTableEntry(GLOBAL_TABLE, procedure, lineNumber, FUNCTION, + INT_T, 0, binaryLength); - emitJFormat(OP_JAL, 0); + emitJFormat(OP_JAL, 0); - type = INT_T; //assume default return type 'int' + type = INT_T; //assume default return type 'int' - } else { - type = getType(entry); + } else { + type = getType(entry); - if (getReference(entry) == 0) { - // CASE 2: function call, no definition, but declared. - setReference(entry, binaryLength); + if (getReference(entry) == 0) { + // CASE 2: function call, no definition, but declared. + setReference(entry, binaryLength); - emitJFormat(OP_JAL, 0); - } else if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) { - // CASE 3: function call, no declaration - emitJFormat(OP_JAL, getReference(entry) / 4); + emitJFormat(OP_JAL, 0); + } else if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) { + // CASE 3: function call, no declaration + emitJFormat(OP_JAL, getReference(entry) / 4); - setReference(entry, binaryLength - 8); - } else - // CASE 4: function defined, use the address - emitJFormat(OP_JAL, getReference(entry) / 4); - } + setReference(entry, binaryLength - 8); + } else + // CASE 4: function defined, use the address + emitJFormat(OP_JAL, getReference(entry) / 4); + } - return type; + return type; } void help_procedure_prologue(int localVariables) { - // allocate space for return address - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + // allocate space for return address + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - // save return address - emitIFormat(OP_SW, REG_SP, REG_RA, 0); + // 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); + // 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); + // 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); + // 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); + // 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); + // 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); + // 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); + // 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); + // 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); + // 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); + // return + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } int gr_call(int *procedure) { - int *entry; - int numberOfTemporaries; - int type; + int *entry; + int numberOfTemporaries; + int type; - // assert: n = allocatedTemporaries + // assert: n = allocatedTemporaries - entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); + entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); - numberOfTemporaries = allocatedTemporaries; + numberOfTemporaries = allocatedTemporaries; - save_temporaries(); + save_temporaries(); - // assert: allocatedTemporaries == 0 + // assert: allocatedTemporaries == 0 - if (isExpression()) { - gr_expression(); + 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); + // 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); + tfree(1); - while (symbol == SYM_COMMA) { - getSymbol(); + while (symbol == SYM_COMMA) { + getSymbol(); - gr_expression(); + gr_expression(); - // push more parameters onto stack - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + // push more parameters onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); - tfree(1); - } + tfree(1); + } - if (symbol == SYM_RPARENTHESIS) { - getSymbol(); - - type = help_call_codegen(entry, procedure); - } else { - syntaxErrorSymbol(SYM_RPARENTHESIS); + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - type = INT_T; - } - } else if (symbol == SYM_RPARENTHESIS) { - getSymbol(); + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); - type = help_call_codegen(entry, procedure); - } else { - syntaxErrorSymbol(SYM_RPARENTHESIS); + type = INT_T; + } + } else if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - type = INT_T; - } + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); - // assert: allocatedTemporaries == 0 + type = INT_T; + } - restore_temporaries(numberOfTemporaries); + // assert: allocatedTemporaries == 0 - // assert: allocatedTemporaries == n - return type; + restore_temporaries(numberOfTemporaries); + + // assert: allocatedTemporaries == n + return type; } int gr_factor() { - int hasCast; - int cast; - int type; + int hasCast; + int cast; + int type; - int *variableOrProcedureName; + int *variableOrProcedureName; - // assert: n = allocatedTemporaries + // assert: n = allocatedTemporaries - hasCast = 0; + hasCast = 0; - type = INT_T; + type = INT_T; - while (lookForFactor()) { - syntaxErrorUnexpected(); + while (lookForFactor()) { + syntaxErrorUnexpected(); - if (symbol == SYM_EOF) - exit(-1); - else - getSymbol(); - } + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } - // optional cast: [ cast ] - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - // cast: "(" "int" [ "*" ] ")" - if (symbol == SYM_INT) { - hasCast = 1; + // cast: "(" "int" [ "*" ] ")" + if (symbol == SYM_INT) { + hasCast = 1; - cast = gr_type(); + cast = gr_type(); - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); - // not a cast: "(" expression ")" - } else { - type = gr_expression(); + // not a cast: "(" expression ")" + } else { + type = gr_expression(); - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); - // assert: allocatedTemporaries == n + 1 + // assert: allocatedTemporaries == n + 1 - return type; - } - } + return type; + } + } + + // dereference? + if (symbol == SYM_ASTERISK) { + getSymbol(); - // dereference? - if (symbol == SYM_ASTERISK) { - getSymbol(); + // ["*"] identifier + if (symbol == SYM_IDENTIFIER) { + type = load_variable(identifier); - // ["*"] identifier - if (symbol == SYM_IDENTIFIER) { - type = load_variable(identifier); + getSymbol(); - getSymbol(); + // * "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - // * "(" expression ")" - } else if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + type = gr_expression(); - type = gr_expression(); + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); - } else - syntaxErrorUnexpected(); + if (type != INTSTAR_T) + typeWarning(INTSTAR_T, type); - if (type != INTSTAR_T) - typeWarning(INTSTAR_T, type); + // dereference + emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); - // dereference - emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); + type = INT_T; - type = INT_T; + // identifier? + } else if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; - // identifier? - } else if (symbol == SYM_IDENTIFIER) { - variableOrProcedureName = identifier; + getSymbol(); - getSymbol(); + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + // function call: identifier "(" ... ")" + type = gr_call(variableOrProcedureName); - // function call: identifier "(" ... ")" - type = gr_call(variableOrProcedureName); + talloc(); - talloc(); + emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); + } else + // variable access: identifier + type = load_variable(variableOrProcedureName); - emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); - } else - // variable access: identifier - type = load_variable(variableOrProcedureName); + // integer? + } else if (symbol == SYM_INTEGER) { + load_integer(); - // integer? - } else if (symbol == SYM_INTEGER) { - load_integer(); + getSymbol(); - getSymbol(); + type = INT_T; - type = INT_T; + // character? + } else if (symbol == SYM_CHARACTER) { + talloc(); - // character? - } else if (symbol == SYM_CHARACTER) { - talloc(); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); - emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); + getSymbol(); - getSymbol(); - - type = INT_T; - - // string? - } else if (symbol == SYM_STRING) { - load_string(); + type = INT_T; - getSymbol(); + // string? + } else if (symbol == SYM_STRING) { + load_string(); - type = INTSTAR_T; + getSymbol(); - // "(" expression ")" - } else if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + type = INTSTAR_T; - type = gr_expression(); + // "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); - } else - syntaxErrorUnexpected(); + type = gr_expression(); - // assert: allocatedTemporaries == n + 1 + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); - if (hasCast) - return cast; - else - return type; + // assert: allocatedTemporaries == n + 1 + + if (hasCast) + return cast; + else + return type; } int gr_term() { - int ltype; - int operatorSymbol; - int rtype; + int ltype; + int operatorSymbol; + int rtype; - // assert: n = allocatedTemporaries + // assert: n = allocatedTemporaries - ltype = gr_factor(); + ltype = gr_factor(); - // assert: allocatedTemporaries == n + 1 + // assert: allocatedTemporaries == n + 1 - // * / or % ? - while (isStarOrDivOrModulo()) { - operatorSymbol = symbol; + // * / or % ? + while (isStarOrDivOrModulo()) { + operatorSymbol = symbol; - getSymbol(); + getSymbol(); - rtype = gr_factor(); + rtype = gr_factor(); - // assert: allocatedTemporaries == n + 2 - - if (ltype != rtype) - typeWarning(ltype, rtype); + // assert: allocatedTemporaries == n + 2 - if (operatorSymbol == SYM_ASTERISK) { - emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_MULTU); - emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + if (ltype != rtype) + typeWarning(ltype, rtype); - } else if (operatorSymbol == SYM_DIV) { - emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + if (operatorSymbol == SYM_ASTERISK) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, + FCT_MULTU); + 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); - } + } else if (operatorSymbol == SYM_DIV) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, + FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); - tfree(1); - } + } else if (operatorSymbol == SYM_MOD) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, + FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFHI); + } - // assert: allocatedTemporaries == n + 1 + tfree(1); + } - return ltype; + // assert: allocatedTemporaries == n + 1 + + return ltype; } int gr_simpleExpression() { - int sign; - int ltype; - int operatorSymbol; - int rtype; + int sign; + int ltype; + int operatorSymbol; + int rtype; - // assert: n = allocatedTemporaries + // assert: n = allocatedTemporaries - // optional: - - if (symbol == SYM_MINUS) { - sign = 1; + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; - mayBeINTMINConstant = 1; - isINTMINConstant = 0; + mayBeINTMINConstant = 1; + isINTMINConstant = 0; - getSymbol(); + getSymbol(); - mayBeINTMINConstant = 0; + 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 (isINTMINConstant) { + isINTMINConstant = 0; - ltype = gr_term(); + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; - // assert: allocatedTemporaries == n + 1 + ltype = gr_term(); - if (sign == 1) { - if (ltype != INT_T) { - typeWarning(INT_T, ltype); + // assert: allocatedTemporaries == n + 1 - ltype = INT_T; - } + if (sign == 1) { + if (ltype != INT_T) { + typeWarning(INT_T, ltype); - emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), currentTemporary(), FCT_SUBU); - } + ltype = INT_T; + } - // + or -? - while (isPlusOrMinus()) { - operatorSymbol = symbol; + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), currentTemporary(), + FCT_SUBU); + } - getSymbol(); + // + or -? + while (isPlusOrMinus()) { + operatorSymbol = symbol; - rtype = gr_term(); + getSymbol(); - // assert: allocatedTemporaries == n + 2 + rtype = gr_term(); - 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); + // assert: allocatedTemporaries == n + 2 - emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_ADDU); + 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); - } else if (operatorSymbol == SYM_MINUS) { - if (ltype != rtype) - typeWarning(ltype, rtype); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_ADDU); - emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); - } + } else if (operatorSymbol == SYM_MINUS) { + if (ltype != rtype) + typeWarning(ltype, rtype); - tfree(1); - } + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_SUBU); + } - // assert: allocatedTemporaries == n + 1 + tfree(1); + } - return ltype; + // assert: allocatedTemporaries == n + 1 + + return ltype; } int gr_expression() { - int ltype; - int operatorSymbol; - int rtype; + int ltype; + int operatorSymbol; + int rtype; - // assert: n = allocatedTemporaries + // assert: n = allocatedTemporaries - ltype = gr_simpleExpression(); + ltype = gr_simpleExpression(); - // assert: allocatedTemporaries == n + 1 + // assert: allocatedTemporaries == n + 1 - //optional: ==, !=, <, >, <=, >= simpleExpression - if (isComparison()) { - operatorSymbol = symbol; + //optional: ==, !=, <, >, <=, >= simpleExpression + if (isComparison()) { + operatorSymbol = symbol; - getSymbol(); + getSymbol(); - rtype = gr_simpleExpression(); + rtype = gr_simpleExpression(); - // assert: allocatedTemporaries == n + 2 + // assert: allocatedTemporaries == n + 2 - if (ltype != rtype) - typeWarning(ltype, rtype); + 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); + if (operatorSymbol == SYM_EQUALITY) { + // subtract, if result = 0 then 1, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_SUBU); - tfree(1); + 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); + 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); + } else if (operatorSymbol == SYM_NOTEQ) { + // subtract, if result = 0 then 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_SUBU); - tfree(1); + 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); + 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); + } else if (operatorSymbol == SYM_LT) { + // set to 1 if a < b, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_SLT); - tfree(1); + tfree(1); - } else if (operatorSymbol == SYM_GT) { - // set to 1 if b < a, else 0 - emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + } else if (operatorSymbol == SYM_GT) { + // set to 1 if b < a, else 0 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), + previousTemporary(), FCT_SLT); - tfree(1); + tfree(1); - } else if (operatorSymbol == SYM_LEQ) { - // if b < a set 0, else 1 - emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + } else if (operatorSymbol == SYM_LEQ) { + // if b < a set 0, else 1 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), + previousTemporary(), FCT_SLT); - tfree(1); + 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); + 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); + } else if (operatorSymbol == SYM_GEQ) { + // if a < b set 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), + previousTemporary(), FCT_SLT); - tfree(1); + 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 + 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); + } + } - return ltype; + // assert: allocatedTemporaries == n + 1 + + return ltype; } void gr_while() { - int brBackToWhile; - int brForwardToEnd; + int brBackToWhile; + int brForwardToEnd; - // assert: allocatedTemporaries == 0 + // assert: allocatedTemporaries == 0 - brBackToWhile = binaryLength; + brBackToWhile = binaryLength; - brForwardToEnd = 0; + brForwardToEnd = 0; - // while ( expression ) - if (symbol == SYM_WHILE) { - getSymbol(); + // while ( expression ) + if (symbol == SYM_WHILE) { + getSymbol(); - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - gr_expression(); + gr_expression(); - // do not know where to branch, fixup later - brForwardToEnd = binaryLength; + // do not know where to branch, fixup later + brForwardToEnd = binaryLength; - emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); - tfree(1); + tfree(1); - if (symbol == SYM_RPARENTHESIS) { - getSymbol(); + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - // zero or more statements: { statement } - if (symbol == SYM_LBRACE) { - getSymbol(); + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); - while (isNotRbraceOrEOF()) - gr_statement(); + while (isNotRbraceOrEOF()) + gr_statement(); - if (symbol == SYM_RBRACE) - getSymbol(); - else { - syntaxErrorSymbol(SYM_RBRACE); + 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); + 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, REG_ZR, REG_ZR, (brBackToWhile - binaryLength - 4) / 4); + // unconditional branch to beginning of while + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, (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); + 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 + // assert: allocatedTemporaries == 0 } void gr_if() { - int brForwardToElseOrEnd; - int brForwardToEnd; + int brForwardToElseOrEnd; + int brForwardToEnd; - // assert: allocatedTemporaries == 0 + // assert: allocatedTemporaries == 0 - // if ( expression ) - if (symbol == SYM_IF) { - getSymbol(); + // if ( expression ) + if (symbol == SYM_IF) { + getSymbol(); - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - gr_expression(); + gr_expression(); - // if the "if" case is not true, we jump to "else" (if provided) - brForwardToElseOrEnd = binaryLength; + // if the "if" case is not true, we jump to "else" (if provided) + brForwardToElseOrEnd = binaryLength; - emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); - tfree(1); + tfree(1); - if (symbol == SYM_RPARENTHESIS) { - getSymbol(); + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - // zero or more statements: { statement } - if (symbol == SYM_LBRACE) { - getSymbol(); + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); - while (isNotRbraceOrEOF()) - gr_statement(); + while (isNotRbraceOrEOF()) + gr_statement(); - if (symbol == SYM_RBRACE) - getSymbol(); - else { - syntaxErrorSymbol(SYM_RBRACE); + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); - exit(-1); - } - } - // only one statement without {} - else - gr_statement(); + exit(-1); + } + } + // only one statement without {} + else + gr_statement(); - //optional: else - if (symbol == SYM_ELSE) { - getSymbol(); + //optional: else + if (symbol == SYM_ELSE) { + getSymbol(); - // if the "if" case was true, we jump to the end - brForwardToEnd = binaryLength; - emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 0); + // if the "if" case was true, we jump to the end + brForwardToEnd = binaryLength; + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 0); - // if the "if" case was not true, we jump here - fixup_relative(brForwardToElseOrEnd); + // if the "if" case was not true, we jump here + fixup_relative(brForwardToElseOrEnd); - // zero or more statements: { statement } - if (symbol == SYM_LBRACE) { - getSymbol(); + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); - while (isNotRbraceOrEOF()) - gr_statement(); + while (isNotRbraceOrEOF()) + gr_statement(); - if (symbol == SYM_RBRACE) - getSymbol(); - else { - syntaxErrorSymbol(SYM_RBRACE); + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); - exit(-1); - } + exit(-1); + } - // only one statement without {} - } else - gr_statement(); + // 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); + // 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 + // assert: allocatedTemporaries == 0 } void gr_return(int returnType) { - int type; + int type; - // assert: allocatedTemporaries == 0 + // assert: allocatedTemporaries == 0 - if (symbol == SYM_RETURN) - getSymbol(); - else - syntaxErrorSymbol(SYM_RETURN); + if (symbol == SYM_RETURN) + getSymbol(); + else + syntaxErrorSymbol(SYM_RETURN); - // optional: expression - if (symbol != SYM_SEMICOLON) { - type = gr_expression(); + // optional: expression + if (symbol != SYM_SEMICOLON) { + type = gr_expression(); - if (returnType == VOID_T) - typeWarning(type, returnType); - else if (type != returnType) - typeWarning(returnType, type); + 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); - } + // save value of expression in return register + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), REG_V0, FCT_ADDU); - // unconditional branch to procedure epilogue - // maintain fixup chain for later fixup - emitJFormat(OP_J, returnBranches / 4); + tfree(1); + } - // new head of fixup chain - // offest is 8 rather than 4 bytes because of delay slot NOP - returnBranches = binaryLength - 8; + // unconditional branch to procedure epilogue + // maintain fixup chain for later fixup + emitJFormat(OP_J, returnBranches / 4); - // assert: allocatedTemporaries == 0 + // 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; + int ltype; + int rtype; + int *variableOrProcedureName; + int *entry; - // assert: allocatedTemporaries == 0; + // assert: allocatedTemporaries == 0; - while (lookForStatement()) { - syntaxErrorUnexpected(); + while (lookForStatement()) { + syntaxErrorUnexpected(); - if (symbol == SYM_EOF) - exit(-1); - else - getSymbol(); - } + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } - // ["*"] - if (symbol == SYM_ASTERISK) { - getSymbol(); + // ["*"] + if (symbol == SYM_ASTERISK) { + getSymbol(); - // "*" identifier - if (symbol == SYM_IDENTIFIER) { - ltype = load_variable(identifier); + // "*" identifier + if (symbol == SYM_IDENTIFIER) { + ltype = load_variable(identifier); - if (ltype != INTSTAR_T) - typeWarning(INTSTAR_T, ltype); + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); - getSymbol(); + getSymbol(); - // "*" identifier "=" - if (symbol == SYM_ASSIGN) { - getSymbol(); + // "*" identifier "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); - rtype = gr_expression(); + rtype = gr_expression(); - if (rtype != INT_T) - typeWarning(INT_T, rtype); + if (rtype != INT_T) + typeWarning(INT_T, rtype); - emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); - tfree(2); - } else - syntaxErrorSymbol(SYM_ASSIGN); + tfree(2); + } else + syntaxErrorSymbol(SYM_ASSIGN); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxErrorSymbol(SYM_SEMICOLON); + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); - // "*" "(" expression ")" - } else if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + // "*" "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - ltype = gr_expression(); + ltype = gr_expression(); - if (ltype != INTSTAR_T) - typeWarning(INTSTAR_T, ltype); + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); - if (symbol == SYM_RPARENTHESIS) { - getSymbol(); + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - // "*" "(" expression ")" "=" - if (symbol == SYM_ASSIGN) { - getSymbol(); + // "*" "(" expression ")" "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); - rtype = gr_expression(); + rtype = gr_expression(); - if (rtype != INT_T) - typeWarning(INT_T, rtype); + if (rtype != INT_T) + typeWarning(INT_T, rtype); - emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), + 0); - tfree(2); - } else - syntaxErrorSymbol(SYM_ASSIGN); + 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; + 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(); + getSymbol(); - // call - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + // call + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - gr_call(variableOrProcedureName); + gr_call(variableOrProcedureName); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxErrorSymbol(SYM_SEMICOLON); + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); - // identifier = expression - } else if (symbol == SYM_ASSIGN) { - entry = getVariable(variableOrProcedureName); + // identifier = expression + } else if (symbol == SYM_ASSIGN) { + entry = getVariable(variableOrProcedureName); - ltype = getType(entry); + ltype = getType(entry); - getSymbol(); + getSymbol(); - rtype = gr_expression(); + rtype = gr_expression(); - if (ltype != rtype) - typeWarning(ltype, rtype); + if (ltype != rtype) + typeWarning(ltype, rtype); - emitIFormat(OP_SW, getRegister(entry), currentTemporary(), getReference(entry)); + emitIFormat(OP_SW, getRegister(entry), currentTemporary(), + getReference(entry)); - tfree(1); + 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); + 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)); + gr_return(getType(entry)); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxErrorSymbol(SYM_SEMICOLON); - } + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } } int gr_type() { - int type; + int type; - type = INT_T; - - if (symbol == SYM_INT) { - getSymbol(); + type = INT_T; - if (symbol == SYM_ASTERISK) { - type = INTSTAR_T; + if (symbol == SYM_INT) { + getSymbol(); - getSymbol(); - } - } else - syntaxErrorSymbol(SYM_INT); + if (symbol == SYM_ASTERISK) { + type = INTSTAR_T; - return type; + getSymbol(); + } + } else + syntaxErrorSymbol(SYM_INT); + + return type; } void gr_variable(int offset) { - int type; + int type; - type = gr_type(); + type = gr_type(); - if (symbol == SYM_IDENTIFIER) { - createSymbolTableEntry(LOCAL_TABLE, identifier, lineNumber, VARIABLE, type, 0, offset); + if (symbol == SYM_IDENTIFIER) { + createSymbolTableEntry(LOCAL_TABLE, identifier, lineNumber, VARIABLE, + type, 0, offset); - getSymbol(); - } else { - syntaxErrorSymbol(SYM_IDENTIFIER); + getSymbol(); + } else { + syntaxErrorSymbol(SYM_IDENTIFIER); - createSymbolTableEntry(LOCAL_TABLE, (int*) "missing variable name", lineNumber, VARIABLE, type, 0, offset); - } + createSymbolTableEntry(LOCAL_TABLE, (int*) "missing variable name", + lineNumber, VARIABLE, type, 0, offset); + } } void gr_initialization(int *name, int offset, int type) { - int actualLineNumber; - int hasCast; - int cast; - int sign; + int actualLineNumber; + int hasCast; + int cast; + int sign; - actualLineNumber = lineNumber; + actualLineNumber = lineNumber; - initialValue = 0; + initialValue = 0; - hasCast = 0; + hasCast = 0; - if (symbol == SYM_ASSIGN) { - getSymbol(); + if (symbol == SYM_ASSIGN) { + getSymbol(); - // optional cast: [ cast ] - if (symbol == SYM_LPARENTHESIS) { - hasCast = 1; + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + hasCast = 1; - getSymbol(); + getSymbol(); - cast = gr_type(); + cast = gr_type(); - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); - } + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } - // optional: - - if (symbol == SYM_MINUS) { - sign = 1; + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; - mayBeINTMINConstant = 1; - isINTMINConstant = 0; + mayBeINTMINConstant = 1; + isINTMINConstant = 0; - getSymbol(); + getSymbol(); - mayBeINTMINConstant = 0; + 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 (isINTMINConstant) { + isINTMINConstant = 0; - if (isConstant()) { - initialValue = constant; + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; - getSymbol(); + if (isConstant()) { + initialValue = constant; - if (sign == 1) - initialValue = -initialValue; - } else - syntaxErrorUnexpected(); + getSymbol(); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxErrorSymbol(SYM_SEMICOLON); - } else - syntaxErrorSymbol(SYM_ASSIGN); + if (sign == 1) + initialValue = -initialValue; + } else + syntaxErrorUnexpected(); - if (hasCast) { - if (type != cast) - typeWarning(type, cast); - } else if (type != INT_T) - typeWarning(type, INT_T); + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorSymbol(SYM_ASSIGN); - createSymbolTableEntry(GLOBAL_TABLE, name, actualLineNumber, VARIABLE, type, initialValue, offset); + if (hasCast) { + if (type != cast) + typeWarning(type, cast); + } else if (type != INT_T) + typeWarning(type, INT_T); + + createSymbolTableEntry(GLOBAL_TABLE, name, actualLineNumber, VARIABLE, type, + initialValue, offset); } void gr_procedure(int *procedure, int returnType) { - int numberOfParameters; - int parameters; - int localVariables; - int functionStart; - int *entry; + int numberOfParameters; + int parameters; + int localVariables; + int functionStart; + int *entry; - currentProcedureName = procedure; + currentProcedureName = procedure; - numberOfParameters = 0; + numberOfParameters = 0; - // ( variable , variable ) ; - if (symbol == SYM_LPARENTHESIS) { - getSymbol(); + // ( variable , variable ) ; + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); - if (symbol != SYM_RPARENTHESIS) { - gr_variable(0); + if (symbol != SYM_RPARENTHESIS) { + gr_variable(0); - numberOfParameters = 1; + numberOfParameters = 1; - while (symbol == SYM_COMMA) { - getSymbol(); + while (symbol == SYM_COMMA) { + getSymbol(); - gr_variable(0); + gr_variable(0); - numberOfParameters = numberOfParameters + 1; - } + numberOfParameters = numberOfParameters + 1; + } - entry = local_symbol_table; + entry = local_symbol_table; - parameters = 0; + parameters = 0; - while (parameters < numberOfParameters) { - // 8 bytes offset to skip frame pointer and link - setReference(entry, parameters * 4 + 8); + while (parameters < numberOfParameters) { + // 8 bytes offset to skip frame pointer and link + setReference(entry, parameters * 4 + 8); - parameters = parameters + 1; - entry = getNext(entry); - } + parameters = parameters + 1; + entry = getNext(entry); + } - if (symbol == SYM_RPARENTHESIS) - getSymbol(); - else - syntaxErrorSymbol(SYM_RPARENTHESIS); - } else - getSymbol(); - } else - syntaxErrorSymbol(SYM_LPARENTHESIS); + 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 (symbol == SYM_SEMICOLON) { + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, + global_symbol_table); - if (entry == (int*) 0) - createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, lineNumber, FUNCTION, returnType, 0, 0); + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, + lineNumber, FUNCTION, returnType, 0, 0); - getSymbol(); + getSymbol(); - // ( variable, variable ) { variable; variable; statement } - } else if (symbol == SYM_LBRACE) { - functionStart = binaryLength; - - entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + // ( variable, variable ) { variable; variable; statement } + } else if (symbol == SYM_LBRACE) { + functionStart = binaryLength; - if (entry == (int*) 0) - createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, lineNumber, FUNCTION, returnType, 0, binaryLength); - else { - if (getReference(entry) != 0) { - if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) - fixlink_absolute(getReference(entry), functionStart); - else { - printLineNumber((int*) "error", lineNumber); - print((int*) "multiple definitions of "); - print(currentProcedureName); - println(); - } - } + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, + global_symbol_table); - setLineNumber(entry, lineNumber); - setReference(entry, functionStart); + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, + lineNumber, FUNCTION, returnType, 0, binaryLength); + else { + if (getReference(entry) != 0) { + if (getOpcode(loadBinary(getReference(entry))) == OP_JAL) + fixlink_absolute(getReference(entry), functionStart); + else { + printLineNumber((int*) "error", lineNumber); + print((int*) "multiple definitions of "); + print(currentProcedureName); + println(); + } + } - if (getType(entry) != returnType) - typeWarning(getType(entry), returnType); + setLineNumber(entry, lineNumber); + setReference(entry, functionStart); - setType(entry, returnType); - } + if (getType(entry) != returnType) + typeWarning(getType(entry), returnType); - getSymbol(); + setType(entry, returnType); + } - localVariables = 0; + getSymbol(); - while (symbol == SYM_INT) { - localVariables = localVariables + 1; + localVariables = 0; - gr_variable(-4 * localVariables); + while (symbol == SYM_INT) { + localVariables = localVariables + 1; - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxErrorSymbol(SYM_SEMICOLON); - } + gr_variable(-4 * localVariables); - help_procedure_prologue(localVariables); + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } - // create a fixup chain for return statements - returnBranches = 0; + help_procedure_prologue(localVariables); - while (isNotRbraceOrEOF()) - gr_statement(); + // create a fixup chain for return statements + returnBranches = 0; - if (symbol == SYM_RBRACE) - getSymbol(); - else { - syntaxErrorSymbol(SYM_RBRACE); + while (isNotRbraceOrEOF()) + gr_statement(); - exit(-1); - } + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } - fixlink_absolute(returnBranches, binaryLength); + fixlink_absolute(returnBranches, binaryLength); - returnBranches = 0; + returnBranches = 0; - help_procedure_epilogue(numberOfParameters); + help_procedure_epilogue(numberOfParameters); - } else - syntaxErrorUnexpected(); + } else + syntaxErrorUnexpected(); - local_symbol_table = (int*) 0; + local_symbol_table = (int*) 0; - // assert: allocatedTemporaries == 0 + // assert: allocatedTemporaries == 0 } void gr_cstar() { - int type; - int *variableOrProcedureName; + int type; + int *variableOrProcedureName; - while (symbol != SYM_EOF) { - while (lookForType()) { - syntaxErrorUnexpected(); + while (symbol != SYM_EOF) { + while (lookForType()) { + syntaxErrorUnexpected(); - if (symbol == SYM_EOF) - exit(-1); - else - getSymbol(); - } + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } - // void identifier procedure - if (symbol == SYM_VOID) { - type = VOID_T; + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; - getSymbol(); + getSymbol(); - if (symbol == SYM_IDENTIFIER) { - variableOrProcedureName = identifier; + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; - getSymbol(); + getSymbol(); - gr_procedure(variableOrProcedureName, type); - } else - syntaxErrorSymbol(SYM_IDENTIFIER); - } else { - type = gr_type(); + gr_procedure(variableOrProcedureName, type); + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); - if (symbol == SYM_IDENTIFIER) { - variableOrProcedureName = identifier; + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; - getSymbol(); + getSymbol(); - // type identifier "(" procedure declaration or definition - if (symbol == SYM_LPARENTHESIS) - gr_procedure(variableOrProcedureName, type); - else { - allocatedMemory = allocatedMemory + 4; + // 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) { - createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, lineNumber, VARIABLE, type, 0, -allocatedMemory); + // type identifier ";" global variable declaration + if (symbol == SYM_SEMICOLON) { + createSymbolTableEntry(GLOBAL_TABLE, + variableOrProcedureName, lineNumber, VARIABLE, + type, 0, -allocatedMemory); - getSymbol(); + getSymbol(); - // type identifier "=" global variable definition - } else - gr_initialization(variableOrProcedureName, -allocatedMemory, type); - } - } else - syntaxErrorSymbol(SYM_IDENTIFIER); - } - } + // type identifier "=" global variable definition + } else + gr_initialization(variableOrProcedureName, + -allocatedMemory, type); + } + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } + } } // ----------------------------------------------------------------- @@ -3257,26 +3456,27 @@ void gr_cstar() { // ----------------------------------------------------------------- void emitLeftShiftBy(int b) { - // assert: 0 <= b < 15 + // 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); + // 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, so just put a NOP there - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); + // instruction at address zero cannot be fixed up, so just put a NOP there + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); - createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", 0, FUNCTION, INT_T, 0, binaryLength); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", 0, FUNCTION, INT_T, 0, + binaryLength); - // jump and link to main, will return here only if there is no exit call - emitJFormat(OP_JAL, 0); + // jump and link to main, will return here only if there is no exit call + emitJFormat(OP_JAL, 0); - // we exit cleanly with error code 0 pushed onto the stack - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, REG_ZR, 0); + // we exit cleanly with error code 0 pushed onto the stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, REG_ZR, 0); } // ----------------------------------------------------------------- @@ -3284,62 +3484,73 @@ void emitMainEntry() { // ----------------------------------------------------------------- void compile() { - print(selfieName); - print((int*) ": this is selfie's cstarc compiling "); - print(sourceName); - println(); - - sourceFD = open(sourceName, O_RDONLY, 0); - - if (sourceFD < 0) { - print(selfieName); - print((int*) ": could not open input file "); - print(sourceName); - println(); - - exit(-1); - } - - // reset scanner - resetScanner(); - - // reset global symbol table - resetGlobalSymbolTable(); - - // allocate space for storing binary - binary = malloc(maxBinaryLength); - binaryLength = 0; - - // reset code length - codeLength = 0; - - // allocate space for storing source code line numbers - sourceLineNumber = malloc(maxBinaryLength); - - // jump to main - emitMainEntry(); - - // library: - // exit must be first to exit main - // if exit call in main is missing - emitExit(); - emitRead(); - emitWrite(); - emitOpen(); - emitMalloc(); - emitPutchar(); - - // parser - gr_cstar(); - - // set code length - codeLength = binaryLength; - - // emit global variables and strings - emitGlobalsStrings(); - - if (reportUndefinedProcedures(global_symbol_table)) - exit(-1); + print(selfieName); + print((int*) ": this is selfie's cstarc compiling "); + print(sourceName); + println(); + + sourceFD = open(sourceName, O_RDONLY, 0); + + if (sourceFD < 0) { + print(selfieName); + print((int*) ": could not open input file "); + print(sourceName); + println(); + + exit(-1); + } + + // reset scanner + resetScanner(); + + // reset global symbol table + resetGlobalSymbolTable(); + + // allocate space for storing binary + binary = malloc(maxBinaryLength); + binaryLength = 0; + + // reset code length + codeLength = 0; + + // allocate space for storing source code line numbers + sourceLineNumber = malloc(maxBinaryLength); + + // jump to main + emitMainEntry(); + + // library: + // exit must be first to exit main + // if exit call in main is missing + emitExit(); + emitRead(); + emitWrite(); + emitOpen(); + emitMalloc(); + emitPutchar(); + emitCreateContext(); + emitSwitchContext(); + emitMapPageInContext(); + emitPMem(); + emitFork(); + emitLock(); + emitUnlock(); + emitWait(); + emitYield(); + emitCAS(); + emitThreadFork(); + + // parser + gr_cstar(); + + // set code length + codeLength = binaryLength; + + // emit global variables and strings + emitGlobalsStrings(); + + if (reportUndefinedProcedures(global_symbol_table)) + exit(-1); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -3353,7 +3564,7 @@ void compile() { // ----------------------------------------------------------------- void printRegister(int reg) { - print((int*) *(REGISTERS + reg)); + print((int*) *(REGISTERS + reg)); } // ----------------------------------------------------------------- @@ -3368,12 +3579,14 @@ void printRegister(int reg) { // +------+-----+-----+-----+-----+------+ // 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; + // 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; } // ----------------------------------------------------------------- @@ -3384,15 +3597,16 @@ int encodeRFormat(int opcode, int rs, int rt, int rd, int function) { // +------+-----+-----+----------------+ // 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); + // 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; + return leftShift(leftShift(leftShift(opcode, 5) + rs, 5) + rt, 16) + + immediate; } // -------------------------------------------------------------- @@ -3403,45 +3617,45 @@ int encodeIFormat(int opcode, int rs, int rt, int immediate) { // +------+--------------------------+ // 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; + // assert: 0 <= opcode < 2^6 + // assert: 0 <= immediate < 2^26 + return leftShift(opcode, 26) + instr_index; } int getOpcode(int instruction) { - return rightShift(instruction, 26); + return rightShift(instruction, 26); } int getRS(int instruction) { - return rightShift(leftShift(instruction, 6), 27); + return rightShift(leftShift(instruction, 6), 27); } int getRT(int instruction) { - return rightShift(leftShift(instruction, 11), 27); + return rightShift(leftShift(instruction, 11), 27); } int getRD(int instruction) { - return rightShift(leftShift(instruction, 16), 27); + return rightShift(leftShift(instruction, 16), 27); } int getFunction(int instruction) { - return rightShift(leftShift(instruction, 26), 26); + return rightShift(leftShift(instruction, 26), 26); } int getImmediate(int instruction) { - return rightShift(leftShift(instruction, 16), 16); + return rightShift(leftShift(instruction, 16), 16); } int getInstrIndex(int instruction) { - return rightShift(leftShift(instruction, 6), 6); + 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); + // sign-extend from 16-bit to 32-bit two's complement + if (immediate < twoToThePowerOf(15)) + return immediate; + else + return immediate - twoToThePowerOf(16); } // ----------------------------------------------------------------- @@ -3449,24 +3663,24 @@ int signExtend(int immediate) { // ----------------------------------------------------------------- void printOpcode(int opcode) { - print((int*) *(OPCODES + opcode)); + print((int*) *(OPCODES + opcode)); } void printFunction(int function) { - print((int*) *(FUNCTIONS + function)); + print((int*) *(FUNCTIONS + function)); } void decode() { - opcode = getOpcode(ir); + opcode = getOpcode(ir); - if (opcode == 0) - decodeRFormat(); - else if (opcode == OP_JAL) - decodeJFormat(); - else if (opcode == OP_J) - decodeJFormat(); - else - decodeIFormat(); + if (opcode == 0) + decodeRFormat(); + else if (opcode == OP_JAL) + decodeJFormat(); + else if (opcode == OP_J) + decodeJFormat(); + else + decodeIFormat(); } // -------------------------------------------------------------- @@ -3477,12 +3691,12 @@ void decode() { // +------+-----+-----+-----+-----+------+ // 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; + rs = getRS(ir); + rt = getRT(ir); + rd = getRD(ir); + immediate = 0; + function = getFunction(ir); + instr_index = 0; } // -------------------------------------------------------------- @@ -3493,12 +3707,12 @@ void decodeRFormat() { // +------+-----+-----+----------------+ // 6 5 5 16 void decodeIFormat() { - rs = getRS(ir); - rt = getRT(ir); - rd = 0; - immediate = getImmediate(ir); - function = 0; - instr_index = 0; + rs = getRS(ir); + rt = getRT(ir); + rd = 0; + immediate = getImmediate(ir); + function = 0; + instr_index = 0; } // -------------------------------------------------------------- @@ -3509,12 +3723,12 @@ void decodeIFormat() { // +------+--------------------------+ // 6 26 void decodeJFormat() { - rs = 0; - rt = 0; - rd = 0; - immediate = 0; - function = 0; - instr_index = getInstrIndex(ir); + rs = 0; + rt = 0; + rd = 0; + immediate = 0; + function = 0; + instr_index = getInstrIndex(ir); } // ----------------------------------------------------------------- @@ -3522,1158 +3736,2307 @@ void decodeJFormat() { // ----------------------------------------------------------------- int loadBinary(int addr) { - return *(binary + addr / 4); + return *(binary + addr / 4); +} + +int loadKernelBinary(int addr) { + return *(kernelBinary + addr / 4); } void storeBinary(int addr, int instruction) { - *(binary + addr / 4) = instruction; + *(binary + addr / 4) = instruction; } void storeInstruction(int addr, int instruction) { - *(sourceLineNumber + addr / 4) = lineNumber; + *(sourceLineNumber + addr / 4) = lineNumber; - storeBinary(addr, instruction); + storeBinary(addr, instruction); } void emitInstruction(int instruction) { - if (binaryLength >= maxBinaryLength) { - syntaxErrorMessage((int*) "exceeded maximum binary length"); - exit(-1); - } else { - storeInstruction(binaryLength, instruction); - - binaryLength = binaryLength + 4; - } + if (binaryLength >= maxBinaryLength) { + syntaxErrorMessage((int*) "exceeded maximum binary length"); + exit(-1); + } else { + storeInstruction(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 - } - } + 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)); + 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 + 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)); + emitInstruction(encodeJFormat(opcode, instr_index)); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot } void fixup_relative(int fromAddress) { - int instruction; + int instruction; - instruction = loadBinary(fromAddress); + instruction = loadBinary(fromAddress); - storeBinary(fromAddress, - encodeIFormat(getOpcode(instruction), - getRS(instruction), - getRT(instruction), - (binaryLength - fromAddress - 4) / 4)); + storeBinary(fromAddress, + encodeIFormat(getOpcode(instruction), getRS(instruction), + getRT(instruction), (binaryLength - fromAddress - 4) / 4)); } void fixup_absolute(int fromAddress, int toAddress) { - storeBinary(fromAddress, - encodeJFormat(getOpcode(loadBinary(fromAddress)), toAddress / 4)); + storeBinary(fromAddress, + encodeJFormat(getOpcode(loadBinary(fromAddress)), toAddress / 4)); } void fixlink_absolute(int fromAddress, int toAddress) { - int previousAddress; + int previousAddress; - while (fromAddress != 0) { - previousAddress = getInstrIndex(loadBinary(fromAddress)) * 4; - fixup_absolute(fromAddress, toAddress); - fromAddress = previousAddress; - } + while (fromAddress != 0) { + previousAddress = getInstrIndex(loadBinary(fromAddress)) * 4; + fixup_absolute(fromAddress, toAddress); + fromAddress = previousAddress; + } } int copyStringToBinary(int *s, int a) { - int l; - int w; + int l; + int w; - l = stringLength(s) + 1; + l = stringLength(s) + 1; - w = a + l; + w = a + l; - if (l % 4 != 0) - // making sure w is a multiple of 4 bytes - w = w + 4 - l % 4; + if (l % 4 != 0) + // making sure w is a multiple of 4 bytes + w = w + 4 - l % 4; - while (a < w) { - storeBinary(a, *s); + while (a < w) { + storeBinary(a, *s); - s = s + 1; - a = a + 4; - } + s = s + 1; + a = a + 4; + } - return w; + return w; } void emitGlobalsStrings() { - int *entry; + int *entry; - entry = global_symbol_table; + entry = global_symbol_table; - // assert: n = binaryLength + // assert: n = binaryLength - // allocate space for global variables and copy strings - while ((int) entry != 0) { - if (getClass(entry) == VARIABLE) { - storeBinary(binaryLength, getValue(entry)); + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeBinary(binaryLength, getValue(entry)); - binaryLength = binaryLength + 4; - } else if (getClass(entry) == STRING) - binaryLength = copyStringToBinary(getString(entry), binaryLength); + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToBinary(getString(entry), binaryLength); - entry = getNext(entry); - } + entry = getNext(entry); + } - // assert: binaryLength == n + allocatedMemory + // assert: binaryLength == n + allocatedMemory - allocatedMemory = 0; + allocatedMemory = 0; } void emit() { - int fd; - - fd = open(binaryName, O_CREAT_WRONLY_TRUNC, S_IRUSR_IWUSR_IRGRP_IROTH); + int fd; - if (fd < 0) { - print(selfieName); - print((int*) ": could not create output file "); - print(binaryName); - println(); + fd = open(binaryName, O_CREAT_WRONLY_TRUNC, S_IRUSR_IWUSR_IRGRP_IROTH); - exit(-1); - } + if (fd < 0) { + print(selfieName); + print((int*) ": could not create output file "); + print(binaryName); + println(); - print(selfieName); - print((int*) ": writing code into output file "); - print(binaryName); - println(); + exit(-1); + } - *io_buffer = codeLength; + print(selfieName); + print((int*) ": writing code into output file "); + print(binaryName); + println(); - // first write code length - write(fd, io_buffer, 4); + *io_buffer = codeLength; - // then write binary - write(fd, binary, binaryLength); + // first write code length + write(fd, io_buffer, 4); + + // then write binary + write(fd, binary, binaryLength); } void load() { - int fd; - int numberOfReadBytes; + int fd; + int numberOfReadBytes; - fd = open(binaryName, O_RDONLY, 0); + fd = open(binaryName, O_RDONLY, 0); - if (fd < 0) { - print(selfieName); - print((int*) ": could not open input file "); - print(binaryName); - println(); + if (fd < 0) { + print(selfieName); + print((int*) ": could not open input file "); + print(binaryName); + println(); - exit(-1); - } + exit(-1); + } - binary = malloc(maxBinaryLength); - binaryLength = 0; + binary = malloc(maxBinaryLength); + binaryLength = 0; - codeLength = 0; + codeLength = 0; - sourceLineNumber = (int*) 0; + sourceLineNumber = (int*) 0; - print(selfieName); - print((int*) ": loading code from input file "); - print(binaryName); - println(); + print(selfieName); + print((int*) ": loading code from input file "); + print(binaryName); + println(); - // read code length first - numberOfReadBytes = read(fd, io_buffer, 4); + // read code length first + numberOfReadBytes = read(fd, io_buffer, 4); - if (numberOfReadBytes == 4) { - codeLength = *io_buffer; - - // now read binary - numberOfReadBytes = read(fd, binary, maxBinaryLength); + if (numberOfReadBytes == 4) { + codeLength = *io_buffer; - if (numberOfReadBytes > 0) { - binaryLength = numberOfReadBytes; + // now read binary + numberOfReadBytes = read(fd, binary, maxBinaryLength); - return; - } - } + if (numberOfReadBytes > 0) { + binaryLength = numberOfReadBytes; - print(selfieName); - print((int*) ": failed to load code from input file "); - print(binaryName); - println(); + return; + } + } - exit(-1); + print(selfieName); + print((int*) ": failed to load code from input file "); + print(binaryName); + println(); + + exit(-1); } -// ----------------------------------------------------------------- -// --------------------------- SYSCALLS ---------------------------- -// ----------------------------------------------------------------- +void loadKernel() { + int fd; + int numberOfReadBytes; -void emitExit() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "exit", 0, FUNCTION, INT_T, 0, binaryLength); + fd = open(kernelBinaryName, O_RDONLY, 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); + if (fd < 0) { + print(selfieName); + print((int*) ": could not open input file "); + print(kernelBinaryName); + println(); - // load argument for exit - emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + exit(-1); + } - // remove the argument from the stack - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + kernelBinary = malloc(maxKernelBinaryLength); + kernelBinaryLength = 0; - // load the correct syscall number and invoke syscall - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_EXIT); - emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + kernelCodeLength = 0; - // never returns here -} + print(selfieName); + print((int*) ": loading code from input file "); + print(kernelBinaryName); + println(); -void syscall_exit() { - int exitCode; + // read code length first + numberOfReadBytes = read(fd, io_buffer, 4); - exitCode = *(registers+REG_A0); + if (numberOfReadBytes == 4) { + kernelCodeLength = *io_buffer; - *(registers+REG_V0) = exitCode; + // now read binary + numberOfReadBytes = read(fd, kernelBinary, maxKernelBinaryLength); - print(binaryName); - print((int*) ": exiting with error code "); - print(itoa(exitCode, string_buffer, 10, 0, 0)); - println(); + if (numberOfReadBytes > 0) { + kernelBinaryLength = numberOfReadBytes; - halt = 1; -} + return; + } + } -void emitRead() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", 0, FUNCTION, INT_T, 0, binaryLength); + print(selfieName); + print((int*) ": failed to load code from input file "); + print(kernelBinaryName); + println(); + + exit(-1); +} - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); +// ----------------------------------------------------------------- +// --------------------------- KERNEL ------------------------------ +// ----------------------------------------------------------------- - emitIFormat(OP_LW, REG_SP, REG_A2, 0); // count - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); +void kernel(int argc, int* argv); +void kernel_event_loop(); +void trap(int hypercallId, int argument); - emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); +int* kernelCurrentContext = (int*) 0; +int* kernelProcessList = (int*) 0; - emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); +int kernelPC = 0; - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); +// ----------------------------------------------------------------- +// --------------------------- PROCESS ----------------------------- +// ----------------------------------------------------------------- - // jump back to caller, return value is in REG_V0 - emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); -} +// ------------------------ GLOBAL VARIABLES ----------------------- -void syscall_read() { - int count; - int vaddr; - int fd; - int *buffer; - int size; +// ----------------------------------------------------------------- +// --------------------------- SYSCALLS ---------------------------- +// ----------------------------------------------------------------- - count = *(registers+REG_A2); - vaddr = *(registers+REG_A1); - fd = *(registers+REG_A0); +void shout() { + println(); + print((int*) "I'm process with PID: "); + printNumber(*osCurrentProcess); +} - buffer = memory + tlb(vaddr); +int getListLength(int* list, int next) { + int* cursor; + int count; - size = read(fd, buffer, count); + cursor = list; + count = 0; - *(registers+REG_V0) = size; + while ((int) cursor != 0) { + count = count + 1; + cursor = (int*) *(cursor + next); + } - if (debug_read) { - print(binaryName); - print((int*) ": read "); - print(itoa(size, string_buffer, 10, 0, 0)); - print((int*) " bytes from file with descriptor "); - print(itoa(fd, string_buffer, 10, 0, 0)); - print((int*) " into buffer at address "); - print(itoa((int) buffer, string_buffer, 16, 8, 0)); - println(); - } + return count; } -void emitWrite() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", 0, FUNCTION, INT_T, 0, binaryLength); +void printList(int* list) { + int* cursor; + int* prevCursor; - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + cursor = list; - emitIFormat(OP_LW, REG_SP, REG_A2, 0); // size - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + while (*cursor != 0) { + print((int*) "PID: "); + printNumber(*cursor); - emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + print((int*) "PT: "); + printNumber(*(cursor+1)); - emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + print((int*) "Prev: "); + printNumber(*(cursor+2)); + *(cursor + 2) = (int) prevCursor; - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + print((int*) "Next: "); + printNumber(*(cursor+3)); - emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + prevCursor = cursor; + cursor = (int*) *(cursor + 3); + } } -void syscall_write() { - int size; - int vaddr; - int fd; - int *buffer; +void printBlockedQueue() { + int* cursor; + int* prevCursor; - size = *(registers+REG_A2); - vaddr = *(registers+REG_A1); - fd = *(registers+REG_A0); + cursor = osBlockedQueue; - buffer = memory + tlb(vaddr); + while (*cursor != 0) { + print((int*) "PID: "); + printNumber(*cursor); - size = write(fd, buffer, size); + print((int*) "PT: "); + printNumber(*(cursor+1)); - *(registers+REG_V0) = size; + print((int*) "Prev: "); + printNumber(*(cursor+2)); - if (debug_write) { - print(binaryName); - print((int*) ": wrote "); - print(itoa(size, string_buffer, 10, 0, 0)); - print((int*) " bytes from buffer at address "); - print(itoa((int) buffer, string_buffer, 16, 8, 0)); - print((int*) " into file with descriptor "); - print(itoa(fd, string_buffer, 10, 0, 0)); - println(); - } -} + print((int*) "Next: "); + printNumber(*(cursor+3)); -void emitOpen() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "open", 0, FUNCTION, INT_T, 0, binaryLength); + print((int*) "Reason: "); + printNumber(*(cursor+4)); + + print((int*) "WAIT FOR: "); + printNumber(*(cursor+5)); + + prevCursor = cursor; + cursor = (int*) *(cursor + 3); + } - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); +} + +void printNumber (int nr) { + print(itoa(nr, string_buffer, 10, 0, 0)); + println(); +} - emitIFormat(OP_LW, REG_SP, REG_A2, 0); // mode - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); +void printPageTable(int* pt) { + int count; + int div; - emitIFormat(OP_LW, REG_SP, REG_A1, 0); // flags - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + count = 0; + div = 0; - emitIFormat(OP_LW, REG_SP, REG_A0, 0); // filename - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + while ((int) pagetable_getAddrAtIndex(pt, count) != 0) { + print("{"); + print(itoa(count, string_buffer, 10, 0, 0)); + print((int*) " -> "); + print(itoa(pagetable_getAddrAtIndex(pt, count), string_buffer, 10, 0, 0)); + print("}, "); - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + if (div == 5) { + println(); + div = 0; + } - emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + count = count + 1; + div = div + 1; + } } -void syscall_open() { - int mode; - int flags; - int vaddr; - int *filename; - int fd; +void emitExit() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "exit", 0, FUNCTION, INT_T, 0, + binaryLength); - mode = *(registers+REG_A2); - flags = *(registers+REG_A1); - vaddr = *(registers+REG_A0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); - filename = memory + tlb(vaddr); + // load argument for exit + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code - fd = open(filename, flags, mode); + // remove the argument from the stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - *(registers+REG_V0) = fd; + // load the correct syscall number and invoke syscall + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_EXIT); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); - if (debug_open) { - print(binaryName); - print((int*) ": opened file "); - printString(filename); - print((int*) " with flags "); - print(itoa(flags, string_buffer, 16, 0, 0)); - print((int*) " and mode "); - print(itoa(mode, string_buffer, 8, 0, 0)); - print((int*) " returning file descriptor "); - print(itoa(fd, string_buffer, 10, 0, 0)); - println(); - } + // never returns here } -void emitMalloc() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "malloc", 0, FUNCTION, INTSTAR_T, 0, binaryLength); +void syscall_exit() { + int* waitingProcess; + int exitCode; - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); - emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + exitCode = *(registers + REG_A0); + *(registers + REG_V0) = exitCode; - emitIFormat(OP_LW, REG_SP, REG_A0, 0); - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + if (context_getPID(osCurrentProcess) == 0) { + halt = 1; + } - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MALLOC); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + trap(SYSCALL_EXIT,exitCode); - emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -void syscall_malloc() { - int size; - int bump; +void emitRead() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", 0, FUNCTION, INT_T, 0, binaryLength); - size = *(registers+REG_A0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - if (size % 4 != 0) - size = size + 4 - size % 4; + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // count + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - bump = *(registers+REG_K1); + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - if (bump + size >= *(registers+REG_SP)) - exception_handler(EXCEPTION_HEAPOVERFLOW); + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - *(registers+REG_K1) = bump + size; - *(registers+REG_V0) = bump; + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - if (debug_malloc) { - print(binaryName); - print((int*) ": malloc "); - print(itoa(size, string_buffer, 10, 0, 0)); - print((int*) " bytes returning address "); - print(itoa(bump, string_buffer, 16, 8, 0)); - println(); - } + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -void emitPutchar() { - createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", 0, FUNCTION, INT_T, 0, binaryLength); - - emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); +void syscall_read() { + int count; + int vaddr; + int fd; + int *buffer; + int size; - emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes + count = *(registers + REG_A2); + vaddr = *(registers + REG_A1); + fd = *(registers + REG_A0); - emitIFormat(OP_ADDIU, REG_SP, REG_A1, 0); // pointer to character - emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + buffer = memory + tlb(vaddr); - emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 1); // stdout file descriptor + size = read(fd, buffer, count); - emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + *(registers + REG_V0) = size; - emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + if (debug_read) { + print(binaryName); + print((int*) ": read "); + print(itoa(size, string_buffer, 10, 0, 0)); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8, 0)); + println(); + } } -// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ -// ----------------------------------------------------------------- -// --------------------- E M U L A T O R --------------------- -// ----------------------------------------------------------------- -// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +void emitWrite() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", 0, FUNCTION, INT_T, 0, + binaryLength); -// ----------------------------------------------------------------- -// ---------------------------- MEMORY ----------------------------- -// ----------------------------------------------------------------- + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); -int tlb(int vaddr) { - if (vaddr % 4 != 0) - exception_handler(EXCEPTION_ADDRESSERROR); + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // size + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // physical memory is word-addressed for lack of byte-sized data type - return vaddr / 4; -} + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); -int loadMemory(int vaddr) { - int paddr; + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - paddr = tlb(vaddr); + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - return *(memory + paddr); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -void storeMemory(int vaddr, int data) { - int paddr; - - paddr = tlb(vaddr); - - *(memory + paddr) = data; -} +void syscall_write() { + int size; + int vaddr; + int fd; + int *buffer; -// ----------------------------------------------------------------- -// ------------------------- INSTRUCTIONS -------------------------- -// ----------------------------------------------------------------- + size = *(registers + REG_A2); + vaddr = *(registers + REG_A1); + fd = *(registers + REG_A0); -void fct_syscall() { - if (debug) { - printFunction(function); - println(); - } - - if (interpret) { - if (*(registers+REG_V0) == SYSCALL_EXIT) { - syscall_exit(); - } else if (*(registers+REG_V0) == SYSCALL_READ) { - syscall_read(); - } else if (*(registers+REG_V0) == SYSCALL_WRITE) { - syscall_write(); - } else if (*(registers+REG_V0) == SYSCALL_OPEN) { - syscall_open(); - } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { - syscall_malloc(); - } else { - exception_handler(EXCEPTION_UNKNOWNSYSCALL); - } + buffer = memory + tlb(vaddr); - pc = pc + 4; - } -} + size = write(fd, buffer, size); -void fct_nop() { - if (debug) { - printFunction(function); - println(); - } + *(registers + REG_V0) = size; - if (interpret) - pc = pc + 4; + if (debug_write) { + print(binaryName); + print((int*) ": wrote "); + print(itoa(size, string_buffer, 10, 0, 0)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8, 0)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + println(); + } } -void op_jal() { - if (debug) { - printOpcode(opcode); - print((int*) " "); - print(itoa(instr_index, string_buffer, 16, 0, 0)); - print((int*) "["); - print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); - print((int*) "]"); - if (interpret) { - print((int*) ": "); - printRegister(REG_RA); - print((int*) "="); - print(itoa(*(registers+REG_RA), string_buffer, 16, 0, 0)); - } - } - - if (interpret) { - *(registers+REG_RA) = pc + 8; +void emitOpen() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "open", 0, FUNCTION, INT_T, 0, + binaryLength); - pc = instr_index * 4; + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - // keep track of number of procedure calls - calls = calls + 1; + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // mode + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - *(callsPerAddress + pc / 4) = *(callsPerAddress + pc / 4) + 1; + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // flags + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // TODO: execute delay slot - } + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // filename + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(REG_RA); - print((int*) "="); - print(itoa(*(registers+REG_RA), string_buffer, 16, 0, 0)); - print((int*) ",$pc="); - print(itoa(pc, string_buffer, 16, 0, 0)); - } - println(); - } -} + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); -void op_j() { - if (debug) { - printOpcode(opcode); - print((int*) " "); - print(itoa(instr_index, string_buffer, 16, 0, 0)); - print((int*) "["); - print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); - print((int*) "]"); - } - - if (interpret) { - pc = instr_index * 4; - - // TODO: execute delay slot - } - - if (debug) { - if (interpret) { - print((int*) ": -> $pc="); - print(itoa(pc, string_buffer, 16, 0, 0)); - } - println(); - } + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -void op_beq() { - if (debug) { - printOpcode(opcode); - print((int*) " "); - printRegister(rs); - print((int*) ","); - printRegister(rt); - print((int*) ","); - print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); - print((int*) "["); - print(itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, 0)); - print((int*) "]"); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } - - if (interpret) { - pc = pc + 4; +void syscall_open() { + int mode; + int flags; + int vaddr; + int *filename; + int fd; - if (*(registers+rs) == *(registers+rt)) { - pc = pc + signExtend(immediate) * 4; + mode = *(registers + REG_A2); + flags = *(registers + REG_A1); + vaddr = *(registers + REG_A0); - if (signExtend(immediate) < 0) { - // keep track of number of loop iterations - loops = loops + 1; + filename = memory + tlb(vaddr); - *(loopsPerAddress + pc / 4) = *(loopsPerAddress + pc / 4) + 1; - } + fd = open(filename, flags, mode); - // TODO: execute delay slot - } - } + *(registers + REG_V0) = fd; - if (debug) { - if (interpret) { - print((int*) " -> $pc="); - print(itoa(pc, string_buffer, 16, 0, 0)); - } - println(); - } + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 16, 0, 0)); + print((int*) " and mode "); + print(itoa(mode, string_buffer, 8, 0, 0)); + print((int*) " returning file descriptor "); + print(itoa(fd, string_buffer, 10, 0, 0)); + println(); + } } -void op_bne() { - if (debug) { - printOpcode(opcode); - print((int*) " "); - printRegister(rs); - print((int*) ","); - printRegister(rt); - print((int*) ","); - print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); - print((int*) "["); - print(itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, 0)); - print((int*) "]"); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } +void emitMalloc() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "malloc", 0, FUNCTION, + INTSTAR_T, 0, binaryLength); - if (interpret) { - pc = pc + 4; + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); - if (*(registers+rs) != *(registers+rt)) { - pc = pc + signExtend(immediate) * 4; + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // TODO: execute delay slot - } - } + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MALLOC); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - if (debug) { - if (interpret) { - print((int*) " -> $pc="); - print(itoa(pc, string_buffer, 16, 0, 0)); - } - println(); - } + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } -void op_addiu() { - if (debug) { - printOpcode(opcode); - print((int*) " "); - printRegister(rt); - print((int*) ","); - printRegister(rs); - print((int*) ","); - print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); - if (interpret) { - print((int*) ": "); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - } - } +void syscall_malloc() { + int size; + int bump; - if (interpret) { - *(registers+rt) = *(registers+rs) + signExtend(immediate); + size = *(registers + REG_A0); - // TODO: check for overflow + if (size % 4 != 0) + size = size + 4 - size % 4; - pc = pc + 4; - } + bump = *(registers + REG_K1); - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - println(); - } + 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, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8, 0)); + println(); + } } -void fct_jr() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rs); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); - } - } +void emitPMem() { - if (interpret) - pc = *(registers+rs); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "pmem", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); - if (debug) { - if (interpret) { - print((int*) " -> $pc="); - print(itoa(pc, string_buffer, 16, 0, 0)); - } - println(); - } -} + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); -void fct_mfhi() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rd); - if (interpret) { - print((int*) ": "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - print((int*) ",$hi="); - print(itoa(reg_hi, string_buffer, 10, 0, 0)); - } - } + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - if (interpret) { - *(registers+rd) = reg_hi; + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_PMEM); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - pc = pc + 4; - } + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - } - println(); - } } -void fct_mflo() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rd); - if (interpret) { - print((int*) ": "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - print((int*) ",$lo="); - print(itoa(reg_lo, string_buffer, 10, 0, 0)); - } - } +void syscall_pmem() { - if (interpret) { - *(registers+rd) = reg_lo; + int a; - pc = pc + 4; - } + a = *(registers + REG_A0); + + *(registers + REG_V0) = (int) memory + 4 * tlb(a); - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - } - println(); - } } -void fct_multu() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) ",$lo="); - print(itoa(reg_lo, string_buffer, 10, 0, 0)); - } - } +void emitPutchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", 0, FUNCTION, INT_T, + 0, binaryLength); - if (interpret) { - // TODO: 64-bit resolution currently not supported - reg_lo = *(registers+rs) * *(registers+rt); + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); - pc = pc + 4; - } + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes - if (debug) { - if (interpret) { - print((int*) " -> $lo="); - print(itoa(reg_lo, string_buffer, 10, 0, 0)); + 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); +} + +void emitFork(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "fork", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_FORK); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void copyRegisters (int* oldRegisters, int* newRegisters) { + int* cursor; + + cursor = oldRegisters; + + while ((int) cursor != (int) oldRegisters + 4*32) { + *newRegisters = *cursor; + + newRegisters = newRegisters + 1; + cursor = cursor + 1; + } +} + +void syscall_fork() { + int childPID; + int* childRegisters; + int* childPageTable; + int childPC; + + childRegisters = malloc(32*4); + childPageTable = pagetable_create(); + + copyRegisters(registers, childRegisters); + + childPC = *(registers + REG_RA); + childPID = nextFreeContextId; + + *(registers + REG_V0) = childPID; + *(childRegisters + REG_V0) = 0; + + kernelProcessList = contextInsert(childPID, childPC, childRegisters, childPageTable, kernelProcessList, (int*) 0); + + nextFreeContextId = nextFreeContextId + 1; + + trap(HYPERCALL_CREATE_CONTEXT, childPID); + +} + +void emitWait() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "wait", 0, FUNCTION, INTSTAR_T, 0, binaryLength); + + 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); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WAIT); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_wait() { + trap(SYSCALL_WAIT, *(registers+REG_A0)); +} + +void emitLock() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "lock", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_LOCK); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_lock() { + trap(SYSCALL_LOCK, -1); +} + +void emitUnlock() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "unlock", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_UNLOCK); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_unlock() { + trap(SYSCALL_UNLOCK, -1); +} + +void emitYield() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "yield", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_YIELD); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + +} + +void syscall_yield() { + trap(HYPERCALL_SWITCH_CONTEXT, -1); +} + +void emitCAS() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "cas", 0, FUNCTION, INTSTAR_T, 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, COMPARE_AND_SWAP); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void compare_and_swap() { + int* sourceAddr; + int* expected; + int newVal; + + print((int*) "CAS - ADDRESS EXPECTED NEW\n"); + + printNumber(*(registers+REG_A0)); + printNumber(*(registers+REG_A1)); + printNumber(*(registers+REG_A2)); + + sourceAddr = (int*) *(registers + REG_A0); + expected = (int*) *(registers + REG_A1); + newVal = *(registers + REG_A2); + + if (sourceAddr == expected) { + *sourceAddr = newVal; + *(registers + REG_V0) = 1; + } else { + *(registers + REG_V0) = 0; + } +} + +void emitThreadFork() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "tfork", 0, FUNCTION, INTSTAR_T, + 0, binaryLength); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_FORK_THREAD); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_thread_fork() { + int childPID; + int* childRegisters; + int* childPageTable; + int childPC; + + childRegisters = malloc(32*4); + childPageTable = pagetable_create(); + + copyRegisters(registers, childRegisters); + + childPC = *(registers + REG_RA); + childPID = nextFreeContextId; + + *(registers + REG_V0) = childPID; + *(childRegisters + REG_V0) = 0; + + kernelProcessList = contextInsert(childPID, childPC, childRegisters, childPageTable, kernelProcessList, (int*) 0); + + childPID = nextFreeContextId + 1; + + nextFreeContextId = nextFreeContextId + 1; + + trap(SYSCALL_FORK_THREAD, childPID); +} + +void trap(int hypercallId, int argument) { + // save User Process context + // before unsetting kernel_mode again, save kernel context (kernel_pc, essentially) + *memory = hypercallId; + *(memory + 1) = argument; + *(memory + 2) = context_getPID(osCurrentProcess); + + nextContextId = 0; +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +int tlb(int vaddr) { + + int offset; + int index; + int page_addr; + + if (kernel_mode) { + return (vaddr + SHARED_MEMORY_SIZE) / 4; + } + + if (vaddr < 0) { + exception_handler(EXCEPTION_ADDRESSERROR); + } + if (vaddr >= 67108863) { // 0x3FFFFFF + exception_handler(EXCEPTION_ADDRESSERROR); + } + if (vaddr % 4 != 0) { + exception_handler(EXCEPTION_ADDRESSERROR); + } + + offset = vaddr % PAGE_FRAME_SIZE; + index = vaddr / PAGE_FRAME_SIZE; + + page_addr = (int) pagetable_getAddrAtIndex(current_page_table, index); + + if ((int) page_addr != (-1)) { + return (page_addr + offset + SHARED_MEMORY_SIZE) / 4; + } else { + print(" --------------- PAGE FAULT ---------------------"); + println(); + + trap(PAGE_FAULT, vaddr); + + return -1; + } +} + +int loadMemory(int vaddr) { + int* paddr; + + paddr = memory + tlb(vaddr); + + return *paddr; +} + +void storeMemory(int vaddr, int data) { + int* paddr; + + paddr = memory + tlb(vaddr); + + *paddr = data; +} + +// Returns a free page frame from the physical memory +int* palloc() { + int* free_page; + int* cursor; + + free_page = free_list; + + if ((int) *free_list == 0) { + free_list = free_list + (PAGE_FRAME_SIZE / 4); + } else { + free_list = (int*) *free_list; + } + + return free_page; + +} + +// ----------------------------------------------------------------- +// --------------------------- Context ----------------------------- +// ----------------------------------------------------------------- + +int* contextInsert(int contextId, int pc, int* registers, int* page_table, + int* prev, int* next) { + int* node; + + node = malloc(6 * 4); + + context_setPID(node, contextId); + context_setPC(node, pc); + context_setRegisters(node, (int) registers); + context_setPageTable(node, (int) page_table); + context_setPrev(node, (int) prev); + context_setNext(node, (int) next); + + if ((int) prev != 0) { + context_setNext(prev, (int) node); + } + if ((int) next != 0) { + context_setPrev(next, (int) node); + } + + return node; +} + +int* contextFindContextByPID(int* contexts, int contextId) { + int* cursor; + + cursor = contexts; + + while ((int) cursor != 0) { + + if (context_getPID(cursor) == contextId) { + return cursor; + } + + cursor = (int*) *(cursor + 3); + } + + cursor = contexts; + + return (int*) 0; +} + +int* processFindByPID(int pid) { + int* cursor; + + cursor = osProcessList; + + while ((int) cursor != 0) { + if (*cursor == pid) { + return cursor; + } + + cursor = (int*) *(cursor + 3); + } + + return (int*) 0; +} + +void context_setPC(int* node, int pc) { + *node = pc; +} + +void context_setRegisters(int* node, int registers) { + *(node + 1) = registers; +} + +void context_setPageTable(int* node, int pageTable) { + *(node + 2) = pageTable; +} + +void context_setPrev(int* node, int prev) { + *(node + 3) = prev; +} + +void context_setNext(int* node, int next) { + *(node + 4) = next; +} + +void context_setPID(int* node, int contextId) { + *(node + 5) = contextId; +} + +int context_getPC(int* node) { + return *node; +} + +int* context_getRegisters(int* node) { + return (int*) *(node + 1); +} + +int* context_getPageTable(int* node) { + return (int*) *(node + 2); +} + +int* context_getPrev(int* node) { + return (int*) *(node + 3); +} + +int* context_getNext(int* node) { + return (int*) *(node + 4); +} + +int context_getPID(int* node) { + return *(node + 5); +} + +// ----------------------------------------------------------------- +// ------------------------ Context List --------------------------- +// ----------------------------------------------------------------- + +int* remove_context(int* context_list, int pid) { + int* next; + int* prev; + int* node; + + node = context_list; + + if ((int) node == 0) + return context_list; + + next = (int*) context_getNext(node); + prev = (int*) context_getPrev(node); + + if ((int) prev != 0) { + context_setNext(prev, (int) next); + } else { + context_list = next; + } + + if ((int) next != 0) { + context_setPrev(next, (int) prev); + } +} + +// ----------------------------------------------------------------- +// ------------------------- Page Table ---------------------------- +// ----------------------------------------------------------------- + +int* pagetable_create() { + int* pagetable; + int index; + + pagetable = malloc(PAGE_TABLE_SIZE * 4); + + index = 0; + + while (index < PAGE_TABLE_SIZE) { + *(pagetable + index) = -1; + index = index + 1; + } + + return pagetable; + +} + +int* pagetable_getAddrAtIndex(int* pagetable, int idx) { + return (int*)*(pagetable + idx); +} + +void pagetable_setAddrAtIndex(int* pagetable, int idx, int data) { + *(pagetable + idx) = data; +} + +// ----------------------------------------------------------------- +// -------------------- Kernel Helper Functions -------------------- +// ----------------------------------------------------------------- + + +void saveContext() { + context_setPC(osCurrentProcess, pc); +} + +void restoreContext(int contextId) { + int* next_context; + + if (contextId == 0) + kernel_mode = 1; + else + kernel_mode = 0; + + next_context = scheduleNextContext(kernelProcessList, contextId); + registers = context_getRegisters(next_context); + + current_page_table = context_getPageTable(next_context); + pc = context_getPC(next_context); + + osCurrentProcess = next_context; + +} + +int* scheduleNextContext(int* list, int contextId) { + return contextFindContextByPID(list, contextId); +} + +int createKernelContext() { + + int* page_table; + int pc; + int pid; + + page_table = (int*) 0; + pc = 0; + + kernelProcessList = contextInsert(nextFreeContextId, pc, registers, page_table, kernelProcessList, (int*) 0); + kernelCurrentContext = kernelProcessList; + + pid = nextFreeContextId; + + nextFreeContextId = nextFreeContextId + 1; + + return pid; + +} + +// ----------------------------------------------------------------- +// ------------------------- HYPERCALLS ---------------------------- +// ----------------------------------------------------------------- + +void emitCreateContext() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "create_context", 0, FUNCTION, + INTSTAR_T, 0, binaryLength); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, HYPERCALL_CREATE_CONTEXT); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void emitSwitchContext() { + + createSymbolTableEntry(GLOBAL_TABLE, (int*) "switch_context", 0, FUNCTION, + INTSTAR_T, 0, binaryLength); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, HYPERCALL_SWITCH_CONTEXT); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + +} + +void emitMapPageInContext() { + + createSymbolTableEntry(GLOBAL_TABLE, (int*) "map_page_in_context", 0, + FUNCTION, INTSTAR_T, 0, binaryLength); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, HYPERCALL_MAP_PAGE_IN_CONTEXT); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + +} + +int* osCreateProcess(int pid, int* prev, int* next) { + int* node; + + node = malloc(5 * 4); + + *node = pid; + *(node + 1) = (int) pagetable_create(); + *(node + 2) = (int) prev; + *(node + 3) = (int) next; + + if ((int) osProcessList != 0) { + *(osProcessList + 2) = (int) node; + } + + if ((int) prev != 0) { + *(prev + 3) = (int) node; + } + + if ((int) next != 0) { + *(next + 2) = (int) node; + } + + return node; +} + +int* tPageTable(int* threadPageTable, int* processPageTable) { + int* page; + int count; + + count = 0; + + // Setting page table for new thread for code, globals and heap + while ((int) pagetable_getAddrAtIndex(processPageTable, count) != -1) { + pagetable_setAddrAtIndex(threadPageTable, count, pagetable_getAddrAtIndex(processPageTable, count)); + + count = count + 1; + } + + // Setting page table for new thread for empty part between heap and stack + while ((int) pagetable_getAddrAtIndex(processPageTable, count) == -1) { + pagetable_setAddrAtIndex(threadPageTable, count, -1); + + count = count + 1; + } + + // Setting page table for new thread for the stack + // Allocate new frames, copy frames from the OS process + while ((int) pagetable_getAddrAtIndex(processPageTable, count) != 0) { + page = palloc(); + + pagetable_setAddrAtIndex(threadPageTable, count, page); + + copyPageFrame(pagetable_getAddrAtIndex(processPageTable, count), page); + + count = count + 1; + } +} + +void pfree(int* frame) { + int* cursor; + + cursor = frame; + + while ((int) cursor != (int) frame + PAGE_FRAME_SIZE) { + *cursor = 0; + cursor = cursor + 1; + } + + *frame = (int) free_list; + + free_list = frame; +} + +void freePageTable(int* page_table, int pid) { + int index; + + index = 0; + + while (index < PAGE_TABLE_SIZE) { + if (*(page_table + index) != -1) { + pfree(*(page_table + index)); + flush_page_in_context(pid, index); + } + + index = index + 1; + } +} + +int* osProcessForkThread(int* osProcess, int pid) { + int* threadNode; + int* threadListOfOSProcess; + int* threadPageTable; + int* threadPrevious; + + int* processPageTable; + + threadNode = malloc(4 * 4); + threadListOfOSProcess = (int*) *(osProcess + 4); + threadPageTable = (int*) malloc(4 * PAGE_TABLE_SIZE + 4); + + processPageTable = (int*) *(osProcess + 1); + + *threadNode = pid; + *(threadNode + 1) = (int) tPageTable(threadPageTable, processPageTable); + *(threadNode + 2) = (int) 0; + *(threadNode + 3) = (int) threadListOfOSProcess; + + if ((int) threadListOfOSProcess != 0) { + *(threadListOfOSProcess + 2) = threadNode; + } + + return threadNode; +} + +int* osProcessReady(int* unblockedProcess) { + int* node; + + node = malloc(4 * 4); + + *node = *unblockedProcess; + *(node + 1) = *(unblockedProcess + 1); + *(node + 2) = (int) 0; + *(node + 3) = (int) osProcessList; + + if ((int) osProcessList != 0) { + *(osProcessList + 2) = (int) node; + } + + return node; +} + +int* osDeleteProcess(int* node, int* processList) { + int* next; + int* prev; + + if ((int) node == 0) + return processList; + + next = (int*) *(node + 3); + prev = (int*) *(node + 2); + + if ((int) prev != 0) { + *(prev + 3) = (int) next; + } else { + processList = next; + } + + if ((int) next != 0) { + *(next + 2) = (int) prev; + } + + + return processList; +} + +int* osFindProcess(int pid, int* processList) { + + int* cursor; + + cursor = processList; + + while ((int) cursor != 0) { + if (*cursor == pid) { + return cursor; + } + + cursor = (int*) *(cursor + 3); + } + + return (int*) 0; +} + +int* osBlockedQFindProcess(int pid) { + int* cursor; + + cursor = osBlockedQueue; + + while ((int) cursor != 0) { + if (*cursor == pid) { + return cursor; + } + + cursor = (int*) *(cursor + 3); } - println(); - } + + return (int*) 0; + } -void fct_divu() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) ",$lo="); - print(itoa(reg_lo, string_buffer, 10, 0, 0)); - print((int*) ",$hi="); - print(itoa(reg_hi, string_buffer, 10, 0, 0)); +int* osBlockedQFindProcessByReason(int pid, int reason) { + int* cursor; + + cursor = osBlockedQueue; + + while ((int) cursor != 0) { + if (*(cursor + 5) == pid) { + if (*(cursor + 4) == reason) { + return cursor; + } + } + + cursor = (int*) *(cursor + 3); + } + + return (int*) 0; +} + +int* osBlockProcess(int* blockedProcess, int reason, int waitForPid) { + int* blockingNode; + + blockingNode = malloc(6 * 4); + + *blockingNode = *blockedProcess; + *(blockingNode + 1) = (int) *(blockedProcess + 1); + *(blockingNode + 2) = (int) 0; + *(blockingNode + 3) = (int) osBlockedQueue; + *(blockingNode + 4) = reason; + *(blockingNode + 5) = waitForPid; + + if ((int) osBlockedQueue != 0) { + *(osBlockedQueue + 2) = (int) blockingNode; + } + + return blockingNode; +} + +int* osUnBlockProcess(int pid) { + int* unblockedProcess; + int* next; + int* prev; + + unblockedProcess = osBlockedQFindProcess(pid); + + if ((int) unblockedProcess == 0) + return osBlockedQueue; + + next = (int*) *(unblockedProcess + 3); + prev = (int*) *(unblockedProcess + 2); + + if ((int) prev != 0) { + *(prev + 3) = (int) next; + } else { + osBlockedQueue = next; } - } - if (interpret) { - reg_lo = *(registers+rs) / *(registers+rt); - reg_hi = *(registers+rs) % *(registers+rt); + if ((int) next != 0) { + *(next + 2) = (int) prev; + } + + return osBlockedQueue; +} + +int* osZombifyProcess(int pid) { + int* zombieNode; + int* zombieProcess; + + zombieNode = malloc(5 * 4); + zombieProcess = osFindProcess(pid, osZombieQueue); + + *zombieNode = pid; + *(zombieNode + 1) = (int) context_getPageTable(zombieProcess); + *(zombieNode + 2) = (int) context_getRegisters(zombieProcess); + *(zombieNode + 3) = (int) 0; + *(zombieNode + 4) = (int) osZombieQueue; + + if ((int) osZombieQueue != 0) { + *(osZombieQueue + 3) = (int) zombieNode; + } + + return zombieNode; +} + +int* osUnzombifyProcess(int pid) { + int* zombieProcess; + + int* next; + int* prev; + + zombieProcess = osFindProcess(pid, osZombieQueue); - pc = pc + 4; - } + if ((int) zombieProcess == 0) + return osZombieQueue; - if (debug) { - if (interpret) { - print((int*) " -> $lo="); - print(itoa(reg_lo, string_buffer, 10, 0, 0)); - print((int*) ",$hi="); - print(itoa(reg_hi, string_buffer, 10, 0, 0)); + next = (int*) *(zombieProcess + 2); + prev = (int*) *(zombieProcess + 3); + + if ((int) prev != 0) { + *(prev + 4) = (int) next; + } else { + osZombieQueue = next; + } + + if ((int) next != 0) { + *(next + 3) = (int) prev; } - println(); - } + + return osZombieQueue; +} + +void hypercall_create_context() { + + int* new_registers; + int* new_page_table; + int new_pc; + + new_registers = malloc(32 * 4); + new_page_table = pagetable_create(); + new_pc = 0; + + *(new_registers + REG_SP) = *(registers + REG_A1); + *(new_registers + REG_GP) = *(registers + REG_A0); + *(new_registers + REG_K1) = *(new_registers + REG_GP); + + kernelProcessList = contextInsert(nextFreeContextId, new_pc, new_registers, new_page_table, kernelProcessList, (int*) 0); + + *(registers + REG_V0) = nextFreeContextId; + + nextFreeContextId = nextFreeContextId + 1; + +} + +void hypercall_switch_context() { + nextContextId = *(registers + REG_A0); +} + +void delete_context(int pid) { + kernelProcessList = remove_context(kernelProcessList, pid); +} + +void hypercall_map_page_in_context() { + + int pid; + int paddr; + int index; + int* page_table; + int* context; + + pid = *(registers + REG_A2); + index = *(registers + REG_A1); + paddr = *(registers + REG_A0); + + context = contextFindContextByPID(kernelProcessList, pid); + page_table = context_getPageTable(context); + pagetable_setAddrAtIndex(page_table, index, paddr); +} + +void flush_page_in_context(int pid, int index) { + int* context; + int* page_table; + + context = contextFindContextByPID(kernelProcessList, pid); + page_table = context_getPageTable(context); + + pagetable_setAddrAtIndex(page_table, index, -1); +} + +// ----------------------------------------------------------------- +// ------------------------- INSTRUCTIONS -------------------------- +// ----------------------------------------------------------------- + +void fct_syscall() { + if (debug) { + printFunction(function); + println(); + } + + if (interpret) { + if (*(registers + REG_V0) == SYSCALL_EXIT) { + syscall_exit(); + } else if (*(registers + REG_V0) == SYSCALL_READ) { + syscall_read(); + } else if (*(registers + REG_V0) == SYSCALL_WRITE) { + syscall_write(); + } else if (*(registers + REG_V0) == SYSCALL_OPEN) { + syscall_open(); + } else if (*(registers + REG_V0) == SYSCALL_MALLOC) { + syscall_malloc(); + } else if (*(registers + REG_V0) == HYPERCALL_CREATE_CONTEXT) { + hypercall_create_context(); + } else if (*(registers + REG_V0) == HYPERCALL_SWITCH_CONTEXT) { + hypercall_switch_context(); + } else if (*(registers + REG_V0) == HYPERCALL_MAP_PAGE_IN_CONTEXT) { + hypercall_map_page_in_context(); + } else if (*(registers + REG_V0) == SYSCALL_PMEM) { + syscall_pmem(); + } else if (*(registers + REG_V0) == SYSCALL_LOCK) { + syscall_lock(); + } else if (*(registers + REG_V0) == SYSCALL_YIELD) { + syscall_yield(); + } else if (*(registers + REG_V0) == SYSCALL_WAIT) { + syscall_wait(); + } else if (*(registers + REG_V0) == SYSCALL_FORK) { + syscall_fork(); + } else if (*(registers + REG_V0) == SYSCALL_UNLOCK) { + syscall_unlock(); + } else if (*(registers + REG_V0) == COMPARE_AND_SWAP) { + compare_and_swap(); + } else if (*(registers + REG_V0) == SYSCALL_FORK_THREAD) { + syscall_thread_fork(); + } else { + exception_handler(EXCEPTION_UNKNOWNSYSCALL); + } + + pc = pc + 4; + + } } -void fct_addu() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rd); - print((int*) ","); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } +void fct_nop() { + if (debug) { + printFunction(function); + println(); + } - if (interpret) { - *(registers+rd) = *(registers+rs) + *(registers+rt); + if (interpret) + pc = pc + 4; +} - pc = pc + 4; - } +void op_jal() { + if (debug) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 0, 0)); + print((int*) "["); + print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(REG_RA); + print((int*) "="); + print(itoa(*(registers + REG_RA), string_buffer, 16, 0, 0)); + } + } + + if (interpret) { + *(registers + REG_RA) = pc + 8; + + pc = instr_index * 4; + + // keep track of number of procedure calls + calls = calls + 1; + + *(callsPerAddress + pc / 4) = *(callsPerAddress + pc / 4) + 1; + + // TODO: execute delay slot + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(REG_RA); + print((int*) "="); + print(itoa(*(registers + REG_RA), string_buffer, 16, 0, 0)); + print((int*) ",$pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); + } +} - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - } - println(); - } +void op_j() { + if (debug) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 0, 0)); + print((int*) "["); + print(itoa(instr_index * 4, string_buffer, 16, 0, 0)); + print((int*) "]"); + } + + if (interpret) { + pc = instr_index * 4; + + // TODO: execute delay slot + } + + if (debug) { + if (interpret) { + print((int*) ": -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); + } } -void fct_subu() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rd); - print((int*) ","); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } +void op_beq() { + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "["); + print( + itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, + 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + pc = pc + 4; + + if (*(registers + rs) == *(registers + rt)) { + pc = pc + signExtend(immediate) * 4; + + if (signExtend(immediate) < 0) { + // keep track of number of loop iterations + loops = loops + 1; + + *(loopsPerAddress + pc / 4) = *(loopsPerAddress + pc / 4) + 1; + } + + // TODO: execute delay slot + } + } + + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); + } +} - if (interpret) { - *(registers+rd) = *(registers+rs) - *(registers+rt); +void op_bne() { + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "["); + print( + itoa(pc + 4 + signExtend(immediate) * 4, string_buffer, 16, 0, + 0)); + print((int*) "]"); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + pc = pc + 4; + + if (*(registers + rs) != *(registers + rt)) { + pc = pc + signExtend(immediate) * 4; + + // TODO: execute delay slot + } + } + + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); + } +} - pc = pc + 4; - } +void op_addiu() { + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + printRegister(rs); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + *(registers + rt) = *(registers + rs) + signExtend(immediate); + + // TODO: check for overflow + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + println(); + } +} - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - } - println(); - } +void fct_jr() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 16, 0, 0)); + } + } + + if (interpret) + pc = *(registers + rs); + + if (debug) { + if (interpret) { + print((int*) " -> $pc="); + print(itoa(pc, string_buffer, 16, 0, 0)); + } + println(); + } } -void op_lw() { - int vaddr; - - if (debug) { - printOpcode(opcode); - print((int*) " "); - printRegister(rt); - print((int*) ","); - print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); - print((int*) "("); - printRegister(rs); - print((int*) ")"); - if (interpret) { - print((int*) ": "); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); - } - } +void fct_mfhi() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + *(registers + rd) = reg_hi; + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + } + println(); + } +} - if (interpret) { - vaddr = *(registers+rs) + signExtend(immediate); +void fct_mflo() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + *(registers + rd) = reg_lo; + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + } + println(); + } +} - *(registers+rt) = loadMemory(vaddr); +void fct_multu() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + // TODO: 64-bit resolution currently not supported + reg_lo = *(registers + rs) * *(registers + rt); + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> $lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + } + println(); + } +} - // keep track of number of loads - loads = loads + 1; +void fct_divu() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) ",$lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + reg_lo = *(registers + rs) / *(registers + rt); + reg_hi = *(registers + rs) % *(registers + rt); + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> $lo="); + print(itoa(reg_lo, string_buffer, 10, 0, 0)); + print((int*) ",$hi="); + print(itoa(reg_hi, string_buffer, 10, 0, 0)); + } + println(); + } +} - *(loadsPerAddress + pc / 4) = *(loadsPerAddress + pc / 4) + 1; +void fct_addu() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + *(registers + rd) = *(registers + rs) + *(registers + rt); + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + } + println(); + } +} - pc = pc + 4; - } +void fct_subu() { + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + *(registers + rd) = *(registers + rs) - *(registers + rt); + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + } + println(); + } +} - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) "=memory[vaddr="); - print(itoa(vaddr, string_buffer, 16, 0, 0)); - print((int*) "]"); - } - println(); - } +void op_lw() { + int vaddr; + int mem; + + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "("); + printRegister(rs); + print((int*) ")"); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 16, 0, 0)); + } + } + + if (interpret) { + + vaddr = *(registers + rs) + signExtend(immediate); + + // Pre-warm TLB with the required page tables + if (tlb(vaddr) != -1) { + + // only if != -1 + *(registers + rt) = loadMemory(vaddr); + + // keep track of number of loads + loads = loads + 1; + + *(loadsPerAddress + pc / 4) = *(loadsPerAddress + pc / 4) + 1; + + pc = pc + 4; + + } + + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) "=memory[vaddr="); + print(itoa(vaddr, string_buffer, 16, 0, 0)); + print((int*) "]"); + } + println(); + } } void fct_slt() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rd); - print((int*) ","); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } - - if (interpret) { - if (*(registers+rs) < *(registers+rt)) - *(registers+rd) = 1; - else - *(registers+rd) = 0; - - pc = pc + 4; - } - - if (debug) { - if (interpret) { - print((int*) " -> "); - printRegister(rd); - print((int*) "="); - print(itoa(*(registers+rd), string_buffer, 10, 0, 0)); - } - println(); - } + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rd); + print((int*) ","); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + if (*(registers + rs) < *(registers + rt)) + *(registers + rd) = 1; + else + *(registers + rd) = 0; + + pc = pc + 4; + } + + if (debug) { + if (interpret) { + print((int*) " -> "); + printRegister(rd); + print((int*) "="); + print(itoa(*(registers + rd), string_buffer, 10, 0, 0)); + } + println(); + } } void op_sw() { - int vaddr; - - if (debug) { - printOpcode(opcode); - print((int*) " "); - printRegister(rt); - print((int*) ","); - print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); - print((int*) "("); - printRegister(rs); - print((int*) ")"); - if (interpret) { - print((int*) ": "); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 16, 0, 0)); - } - } - - if (interpret) { - vaddr = *(registers+rs) + signExtend(immediate); - - storeMemory(vaddr, *(registers+rt)); - - // keep track of number of stores - stores = stores + 1; - - *(storesPerAddress + pc / 4) = *(storesPerAddress + pc / 4) + 1; - - pc = pc + 4; - } - - if (debug) { - if (interpret) { - print((int*) " -> memory[vaddr="); - print(itoa(vaddr, string_buffer, 16, 0, 0)); - print((int*) "]="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - print((int*) "="); - printRegister(rt); - } - println(); - } + int vaddr; + + if (debug) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + print((int*) ","); + print(itoa(signExtend(immediate), string_buffer, 10, 0, 0)); + print((int*) "("); + printRegister(rs); + print((int*) ")"); + if (interpret) { + print((int*) ": "); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 16, 0, 0)); + } + } + + if (interpret) { + vaddr = *(registers + rs) + signExtend(immediate); + + // Pre-warm TLB with the required page tables + if (tlb(vaddr) != -1) { + + // only if != -1 + storeMemory(vaddr, *(registers + rt)); + + // keep track of number of stores + stores = stores + 1; + + *(storesPerAddress + pc / 4) = *(storesPerAddress + pc / 4) + 1; + + pc = pc + 4; + + } + + } + + if (debug) { + if (interpret) { + print((int*) " -> memory[vaddr="); + print(itoa(vaddr, string_buffer, 16, 0, 0)); + print((int*) "]="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + print((int*) "="); + printRegister(rt); + } + println(); + } } void fct_teq() { - if (debug) { - printFunction(function); - print((int*) " "); - printRegister(rs); - print((int*) ","); - printRegister(rt); - if (interpret) { - print((int*) ": "); - printRegister(rs); - print((int*) "="); - print(itoa(*(registers+rs), string_buffer, 10, 0, 0)); - print((int*) ","); - printRegister(rt); - print((int*) "="); - print(itoa(*(registers+rt), string_buffer, 10, 0, 0)); - } - } - - if (interpret) { - if (*(registers+rs) == *(registers+rt)) - exception_handler(EXCEPTION_SIGNAL); - - pc = pc + 4; - } - - if (debug) - println(); + if (debug) { + printFunction(function); + print((int*) " "); + printRegister(rs); + print((int*) ","); + printRegister(rt); + if (interpret) { + print((int*) ": "); + printRegister(rs); + print((int*) "="); + print(itoa(*(registers + rs), string_buffer, 10, 0, 0)); + print((int*) ","); + printRegister(rt); + print((int*) "="); + print(itoa(*(registers + rt), string_buffer, 10, 0, 0)); + } + } + + if (interpret) { + if (*(registers + rs) == *(registers + rt)) + exception_handler(EXCEPTION_SIGNAL); + + pc = pc + 4; + } + + if (debug) + println(); } // ----------------------------------------------------------------- @@ -4681,358 +6044,888 @@ void fct_teq() { // ----------------------------------------------------------------- void printException(int enumber) { - print((int*) *(EXCEPTIONS + enumber)); + print((int*) *(EXCEPTIONS + enumber)); } void exception_handler(int enumber) { - print(binaryName); - print((int*) ": exception: "); - printException(enumber); - println(); + print(binaryName); + print((int*) ": exception: "); + printException(enumber); + println(); - exit(enumber); + exit(enumber); } void fetch() { - ir = loadMemory(pc); + ir = loadMemory(pc); } void execute() { - if (debug) - if (sourceLineNumber != (int*) 0) { - print(binaryName); - print((int*) ": "); - } - - if (interpret) - if (debug) - print((int*) "$pc="); - - if (debug) { - print(itoa(pc, string_buffer, 16, 8, 0)); - if (sourceLineNumber != (int*) 0) { - print((int*) "(~"); - print(itoa(*(sourceLineNumber + pc / 4), string_buffer, 10, 0, 0)); - print((int*) ")"); - } - print((int*) ": "); - } - - 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); - } - - if (interpret == 0) { - if (pc == codeLength - 4) - halt = 1; - else - pc = pc + 4; - } + if (debug) + if (sourceLineNumber != (int*) 0) { + print(binaryName); + print((int*) ": "); + } + + if (interpret) + if (debug) + print((int*) "$pc="); + + if (debug) { + print(itoa(pc, string_buffer, 10, 0, 0)); + if (sourceLineNumber != (int*) 0) { + print((int*) "(~"); + print(itoa(*(sourceLineNumber + pc / 4), string_buffer, 10, 0, 0)); + print((int*) ")"); + } + print((int*) ": "); + } + + 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); + } + + if (interpret == 0) { + if (pc == codeLength - 4) + halt = 1; + else + pc = pc + 4; + } } void run() { - halt = 0; - while (halt == 0) { - fetch(); - decode(); - execute(); - } + int instrCount; + + halt = 0; + instrCount = 0; + + while (halt == 0) { - halt = 0; + fetch(); + decode(); + execute(); - interpret = 0; - debug = 0; + if (nextContextId != -1) { + saveContext(); + restoreContext(nextContextId); + nextContextId = -1; + } + + if (kernel_mode == 0) + instrCount = instrCount + 1; + + if (instrCount == 10) { + trap(HYPERCALL_SWITCH_CONTEXT, -1); + instrCount = 0; + } + + } + + halt = 0; + + interpret = 0; + debug = 1; } void up_push(int value) { - int vaddr; + int vaddr; - // allocate space for one value on the stack - *(registers+REG_SP) = *(registers+REG_SP) - 4; + // allocate space for one value on the stack + *(registers + REG_SP) = *(registers + REG_SP) - 4; - // compute address - vaddr = *(registers+REG_SP); + // compute address + vaddr = *(registers + REG_SP); - // store value - storeMemory(vaddr, value); + // store value + storeMemory(vaddr, value); } int up_malloc(int size) { - *(registers+REG_A0) = size; + *(registers + REG_A0) = size; - syscall_malloc(); + syscall_malloc(); - return *(registers+REG_V0); + return *(registers + REG_V0); } int up_copyString(int *s) { - int l; - int a; - int w; - int t; + int l; + int a; + int w; + int t; - l = stringLength(s) + 1; + l = stringLength(s) + 1; - a = up_malloc(l); + a = up_malloc(l); - w = a + l; + w = a + l; - if (l % 4 != 0) - // making sure w is a multiple of 4 bytes - w = w + 4 - l % 4; + if (l % 4 != 0) + // making sure w is a multiple of 4 bytes + w = w + 4 - l % 4; - t = a; + t = a; - while (a < w) { - storeMemory(a, *s); + while (a < w) { + storeMemory(a, *s); - s = s + 1; - a = a + 4; - } + s = s + 1; + a = a + 4; + } - return t; + return t; } void up_copyArguments(int argc, int *argv) { - int vaddr; + int vaddr; + + up_push(argc); - up_push(argc); + vaddr = up_malloc(argc * 4); - vaddr = up_malloc(argc * 4); + up_push(vaddr); - up_push(vaddr); + while (argc > 0) { + storeMemory(vaddr, up_copyString((int*) *argv)); - while (argc > 0) { - storeMemory(vaddr, up_copyString((int*) *argv)); + vaddr = vaddr + 4; - vaddr = vaddr + 4; + argv = argv + 1; + argc = argc - 1; + } - argv = argv + 1; - argc = argc - 1; - } } void copyBinaryToMemory() { - int a; + int a; + int* page; + int offset; + int index; + int* pageTable; + + a = 0; + + pageTable = (int*) *(processFindByPID(1) + 1); - a = 0; + while (a < binaryLength) { - while (a < binaryLength) { - storeMemory(a, loadBinary(a)); + offset = a % PAGE_FRAME_SIZE; + index = a / PAGE_FRAME_SIZE; + + if (offset == 0) { + page = palloc(); + map_page_in_context(1, index, page); + pagetable_setAddrAtIndex(pageTable, index, page); + } + + *(page + offset / 4) = loadBinary(a); + + a = a + 4; + } + +} + +void copyKernelBinaryToMemory() { // Note: Make sure that we are running in KERNEL MODE + + int a; + + a = 0; + + while (a < kernelBinaryLength) { + storeMemory(a, loadKernelBinary(a)); + a = a + 4; + } - a = a + 4; - } } int addressWithMaxCounter(int *counters, int max) { - int a; - int n; - int i; - int c; + int a; + int n; + int i; + int c; - a = -1; + a = -1; - n = 0; + n = 0; - i = 0; + i = 0; - while (i < maxBinaryLength / 4) { - c = *(counters + i); + while (i < maxBinaryLength / 4) { + c = *(counters + i); - if (n < c) - if (c < max) { - n = c; - a = i * 4; - } + if (n < c) + if (c < max) { + n = c; + a = i * 4; + } - i = i + 1; - } + i = i + 1; + } - return a; + return a; } int fixedPointRatio(int a, int b) { - // assert: a >= b - int r; - - // compute fixed point ratio r with 2 fractional digits - - r = 0; - - // multiply a/b with 100 but avoid overflow - - if (a <= INT_MAX / 100) { - if (b != 0) - r = a * 100 / b; - } else if (a <= INT_MAX / 10) { - if (b / 10 != 0) - r = a * 10 / (b / 10); - } else { - if (b / 100 != 0) - r = a / (b / 100); - } - - // compute a/b in percent - // 1000000 = 10000 (for 100.00%) * 100 (for 2 fractional digits of r) - - if (r != 0) - return 1000000 / r; - else - return 0; + // assert: a >= b + int r; + + // compute fixed point ratio r with 2 fractional digits + + r = 0; + + // multiply a/b with 100 but avoid overflow + + if (a <= INT_MAX / 100) { + if (b != 0) + r = a * 100 / b; + } else if (a <= INT_MAX / 10) { + if (b / 10 != 0) + r = a * 10 / (b / 10); + } else { + if (b / 100 != 0) + r = a / (b / 100); + } + + // compute a/b in percent + // 1000000 = 10000 (for 100.00%) * 100 (for 2 fractional digits of r) + + if (r != 0) + return 1000000 / r; + else + return 0; } int printCounters(int total, int *counters, int max) { - int a; - - a = addressWithMaxCounter(counters, max); - - print(itoa(*(counters + a / 4), string_buffer, 10, 0, 0)); - - print((int*) "("); - print(itoa(fixedPointRatio(total, *(counters + a / 4)), string_buffer, 10, 0, 2)); - print((int*) "%)"); - - if (*(counters + a / 4) != 0) { - print((int*) "@"); - print(itoa(a, string_buffer, 16, 8, 0)); - if (sourceLineNumber != (int*) 0) { - print((int*) "(~"); - print(itoa(*(sourceLineNumber + a / 4), string_buffer, 10, 0, 0)); - print((int*) ")"); - } - } + int a; - return a; + a = addressWithMaxCounter(counters, max); + + print(itoa(*(counters + a / 4), string_buffer, 10, 0, 0)); + + print((int*) "("); + print(itoa(fixedPointRatio(total, *(counters + a / 4)), string_buffer, 10, 0, 2)); + print((int*) "%)"); + + if (*(counters + a / 4) != 0) { + print((int*) "@"); + print(itoa(a, string_buffer, 16, 8, 0)); + if (sourceLineNumber != (int*) 0) { + print((int*) "(~"); + print(itoa(*(sourceLineNumber + a / 4), string_buffer, 10, 0, 0)); + print((int*) ")"); + } + } + + return a; } void printProfile(int *message, int total, int *counters) { - int a; - - if (total > 0) { - print(selfieName); - print(message); - print(itoa(total, string_buffer, 10, 0, 0)); - print((int*) ","); - a = printCounters(total, counters, INT_MAX); // max counter - print((int*) ","); - a = printCounters(total, counters, *(counters + a / 4)); // 2nd max - print((int*) ","); - a = printCounters(total, counters, *(counters + a / 4)); // 3rd max - println(); - } + int a; + + if (total > 0) { + print(selfieName); + print(message); + print(itoa(total, string_buffer, 10, 0, 0)); + print((int*) ","); + a = printCounters(total, counters, INT_MAX); // max counter + print((int*) ","); + a = printCounters(total, counters, *(counters + a / 4)); // 2nd max + print((int*) ","); + a = printCounters(total, counters, *(counters + a / 4)); // 3rd max + println(); + } } void disassemble() { - assemblyFD = open(assemblyName, O_CREAT_WRONLY_TRUNC, S_IRUSR_IWUSR_IRGRP_IROTH); + assemblyFD = open(assemblyName, O_CREAT_WRONLY_TRUNC, + S_IRUSR_IWUSR_IRGRP_IROTH); - if (assemblyFD < 0) { - print(selfieName); - print((int*) ": could not create assembly output file "); - print(assemblyName); - println(); + if (assemblyFD < 0) { + print(selfieName); + print((int*) ": could not create assembly output file "); + print(assemblyName); + println(); - exit(-1); - } + exit(-1); + } - print(selfieName); - print((int*) ": writing assembly into output file "); - print(assemblyName); - println(); + print(selfieName); + print((int*) ": writing assembly into output file "); + print(assemblyName); + println(); - outputName = assemblyName; - outputFD = assemblyFD; + outputName = assemblyName; + outputFD = assemblyFD; - interpret = 0; - debug = 1; + interpret = 0; + debug = 1; - copyBinaryToMemory(); - - resetInterpreter(); + copyBinaryToMemory(); - run(); + resetInterpreter(); - outputName = (int*) 0; - outputFD = 1; + run(); + + outputName = (int*) 0; + outputFD = 1; } void emulate(int argc, int *argv) { - print(selfieName); - print((int*) ": this is selfie's mipster executing "); - print(binaryName); - print((int*) " with "); - print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0, 0)); - print((int*) "MB of memory"); - println(); - interpret = 1; + int pid; + + print(selfieName); + print((int*) ": this is selfie's kernel lauching the user prog "); + print(binaryName); + print((int*) " with "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0, 0)); + print((int*) "MB of memory"); + println(); + + interpret = 1; + + free_list = memory; + + // Create a new context for the user process + pid = (int) create_context(4 * 1024 * 1024, binaryLength); + osProcessList = osCreateProcess(pid, (int*) 0, osProcessList); + + osCurrentProcess = osProcessList; + + copyBinaryToMemory(); + + // Switch to the user process + switch_context(pid); + + // Handles syscalls and other events + kernel_event_loop(); + + print(selfieName); + print((int*) ": this is selfie's mipster terminating "); + print(binaryName); + println(); + + print(selfieName); + print((int*) ": profile: total,max(ratio%)@addr(line#),2max(ratio%)@addr(line#),3max(ratio%)@addr(line#)"); + println(); + printProfile((int*) ": calls: ", calls, callsPerAddress); + printProfile((int*) ": loops: ", loops, loopsPerAddress); + printProfile((int*) ": loads: ", loads, loadsPerAddress); + printProfile((int*) ": stores: ", stores, storesPerAddress); +} + +// ----------------------------------------------------------------- +// --------------------------- KERNEL ------------------------------ +// ----------------------------------------------------------------- + +void kernel(int argc, int* argv) { + + int pid; + int* cursor; + + kernel_mode = 1; + + print(selfieName); + print((int*) ": starting kernel with "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0, 0)); + print((int*) " MB of memory... "); + println(); + + cursor = memory; + while ((int) cursor < (int) memory + memorySize) { + *cursor = 0; + cursor = cursor + 1; + } + + // Load the kernel + copyKernelBinaryToMemory(); + + // Create a context for the kernel process + pid = createKernelContext(); + + osCurrentProcess = contextFindContextByPID(kernelProcessList, pid); + + *(registers + REG_SP) = memorySize - 4; // initialize stack pointer + + *(registers + REG_GP) = kernelBinaryLength; // initialize global pointer + + *(registers + REG_K1) = *(registers + REG_GP); // initialize bump pointer + + resetInterpreter(); + + up_copyArguments(argc, argv); + + // Run the OS kernel + run(); + +} + +int continueInSearch(int a, int *b) { + int c; + int d; + + if (a == LOCK_BLOCK) { + c = 0; + } else { + c = 1; + } + + if ((int) b == 0) { + d = 0; + return 0; + } else { + d = 1; + } + + return c; +} + +void mapPages(int callerPid, int idx, int* paddr) { + int* cursor; + int* pageTable; + int* prevPage; + int* prevPageTable; + int* callerProcess; + + cursor = osProcessList; + callerProcess = osFindProcess(callerPid, osProcessList); + prevPageTable = (int*) *(callerProcess + 1); + prevPage = pagetable_getAddrAtIndex(prevPageTable, idx); + + while ((int) cursor != 0) { + pageTable = (int*) *(cursor + 1); + + if (pagetable_getAddrAtIndex(pageTable, idx) == prevPage) { + map_page_in_context(*cursor, idx, paddr); + } + + cursor = (int*)*(cursor + 3); + } +} + +void kernel_event_loop() { + int* sharedMemory; + int eventType; + int arg; + int callerPid; + int* page; + + int* threadList; - copyBinaryToMemory(); + int* parentProcess; + int* childProcess; - resetInterpreter(); + int* pageTable; + int* childProcessPageTable; - *(registers+REG_SP) = memorySize - 4; // initialize stack pointer + int* cursor; + int count; - *(registers+REG_GP) = binaryLength; // initialize global pointer + int* process; - *(registers+REG_K1) = *(registers+REG_GP); // initialize bump pointer + int stop; - up_copyArguments(argc, argv); + int* unblockedProcess; - run(); + int* nextProcess; - print(selfieName); - print((int*) ": this is selfie's mipster terminating "); - print(binaryName); - println(); + int waitForPID; + int* waitForProcess; + int* waitingProcess; - print(selfieName); - print((int*) ": profile: total,max(ratio%)@addr(line#),2max(ratio%)@addr(line#),3max(ratio%)@addr(line#)"); - println(); - printProfile((int*) ": calls: ", calls, callsPerAddress); - printProfile((int*) ": loops: ", loops, loopsPerAddress); - printProfile((int*) ": loads: ", loads, loadsPerAddress); - printProfile((int*) ": stores: ", stores, storesPerAddress); + sharedMemory = -SHARED_MEMORY_SIZE; + stop = 0; + + while (stop == 0) { + eventType = *sharedMemory; + arg = *(sharedMemory + 1); + callerPid = *(sharedMemory + 2); + + count = 0; + + if (eventType == PAGE_FAULT) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + + print((int*) "OS: Handle Page Fault"); + println(); + + page = palloc(); + + mapPages(callerPid, arg / PAGE_FRAME_SIZE, page); + + pageTable = (int*) *(processFindByPID(callerPid) + 1); + + pagetable_setAddrAtIndex(pageTable, arg/PAGE_FRAME_SIZE, page); + + osCurrentProcess = osFindProcess(callerPid, osProcessList); + + switch_context(callerPid); + + print((int*) "-------------------------"); + println(); + } else if (eventType == HYPERCALL_SWITCH_CONTEXT) { + process = osFindProcess(callerPid, osProcessList); + process = (int*) *(process + 3); + + if ((int) process == 0) { + process = osProcessList; + } + + osCurrentProcess = process; + + switch_context(*process); + } else if (eventType == SYSCALL_LOCK) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Lock"); + println(); + + if ((int) lockOwner == 0) { + print((int*) "... taking the lock!"); + println(); + + lockOwner = osCurrentProcess; + + osCurrentProcess = osFindProcess(callerPid, osProcessList); + + switch_context(callerPid); + } else { + print((int*) "... being blocked after requesting a lock!"); + println(); + + osBlockedQueue = osBlockProcess(osCurrentProcess, LOCK_BLOCK, -1); + osProcessList = osDeleteProcess(osCurrentProcess, osProcessList); + + process = (int*) *(osCurrentProcess + 3); + + if ((int) process == 0) { + process = osProcessList; + } + + osCurrentProcess = process; + + switch_context(*process); + } + + print((int*) "-------------------------"); + println(); + } else if (eventType == SYSCALL_UNLOCK) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Unlock"); + println(); + + print((int*) " ... unlocking!"); + println(); + + lockOwner = (int*) 0; + unblockedProcess = osBlockedQueue; + + if ((int) osBlockedQueue != 0) { + if (*(osBlockedQueue + 4) != LOCK_BLOCK) { + unblockedProcess = (int*)*(unblockedProcess + 3); + + while (continueInSearch(*(unblockedProcess + 4), unblockedProcess)) { + unblockedProcess = (int*)*(unblockedProcess + 3); + } + } + } + + if ((int) unblockedProcess != 0) { + osBlockedQueue = osUnBlockProcess(*unblockedProcess); + osProcessList = osProcessReady(unblockedProcess); + } + + process = (int*)*(osCurrentProcess + 3); + + if ((int) process == 0) { + process = osProcessList; + } + + osCurrentProcess = process; + + print((int*) "Next up - Process#"); + printNumber(*process); + + switch_context(*process); + + print((int*) "-------------------------"); + println(); + } else if (eventType == SYSCALL_WAIT) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Wait"); + println(); + + waitForPID = arg; + waitForProcess = osFindProcess(waitForPID, osProcessList); + + print((int*) " ... and I have to wait for: "); + printNumber(waitForPID); + + if ((int) waitForProcess == 0) { + print((int*) "No such process in the ready queue..."); + + waitForProcess = osBlockedQFindProcess(waitForPID); + + if ((int) waitForProcess != 0) { + print((int*) " but in the blocking queue"); + } else { + print((int*) ", nor in the blocking queue..."); + } + + println(); + } + + if ((int) waitForProcess != 0) { + print((int*) "Block process #"); + printNumber(*osCurrentProcess); + + process = (int*)*(osCurrentProcess + 3); + + if ((int) process != 0) { + process = osProcessList; + } + + osBlockedQueue = osBlockProcess(osCurrentProcess, WAIT_FOR_CHILD_BLOCK, waitForPID); + osProcessList = osDeleteProcess(osFindProcess(*osCurrentProcess, osProcessList), osProcessList); + + } else { + waitForProcess = osFindProcess(waitForPID, osZombieQueue); + + print((int*) "Process to wait for could be a zombie!"); + println(); + + if ((int) waitForProcess != 0) { + print((int*) "Indeed!"); + println(); + + osZombieQueue = osUnzombifyProcess(waitForProcess); + + } else { + print((int*) "No..."); + println(); + } + + process = (int*) *(osCurrentProcess + 3); + + if ((int) process == 0) { + process = osProcessList; + } + } + + osCurrentProcess = waitForProcess; + + switch_context(*waitForProcess); + + print((int*) "-------------------------"); + println(); + } else if (eventType == HYPERCALL_CREATE_CONTEXT) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Fork (Create Context)"); + println(); + + osProcessList = osCreateProcess(arg, (int*) 0, osProcessList); + + parentProcess = processFindByPID(callerPid); + pageTable = (int*) *(parentProcess + 1); + + cursor = pageTable; + + childProcess = processFindByPID(arg); + childProcessPageTable = (int*) *(childProcess + 1); + + while (count < PAGE_TABLE_SIZE) { + if (*cursor != -1) { + page = palloc(); + copyPageFrame(*cursor, page); + pagetable_setAddrAtIndex(childProcessPageTable, count, page); + map_page_in_context(arg, count, page); + } + + count = count + 1; + cursor = cursor + 1; + } + + osCurrentProcess = osFindProcess(arg, osProcessList); + + switch_context(arg); + + print((int*) "-------------------------"); + println(); + } else if (eventType == SYSCALL_FORK_THREAD) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Thread Fork"); + println(); + + osProcessList = osProcessForkThread(osCurrentProcess, arg); + + osCurrentProcess = osProcessList; + + switch_context(arg); + + print((int*) "-------------------------"); + println(); + } else if (eventType == SYSCALL_EXIT) { + shout(); + + println(); + print((int*) "-------------------------"); + println(); + print((int*) "OS: Exit"); + println(); + + println(); + print((int*) "exiting with error code "); + printNumber(arg); + + process = osFindProcess(callerPid, osProcessList); + + osProcessList = osDeleteProcess(osFindProcess(callerPid, osProcessList), osProcessList); + + delete_context(callerPid); + + if (*osCurrentProcess > 1) { + waitingProcess = osBlockedQFindProcessByReason(*osCurrentProcess, WAIT_FOR_CHILD_BLOCK); + + if ((int) waitingProcess != 0) { + print((int*) "Process "); + print(itoa(*waitingProcess, string_buffer, 10, 0, 0)); + print((int*) " is waiting for me..."); + println(); + + osProcessList = osProcessReady(waitingProcess); + osBlockedQueue = osUnBlockProcess(*waitingProcess); + } else { + print((int*) "Noone is waiting for me... I'm a zombie now."); + println(); + + osZombieQueue = osZombifyProcess(*osCurrentProcess); + } + } + + freePageTable(*(process + 1), *osCurrentProcess); + + if ((int) osProcessList == 0) { + stop = 1; + } else { + process = (int*) *(osCurrentProcess + 3); + + if ((int) process == 0) { + process = osProcessList; + } + + osCurrentProcess = process; + switch_context(*process); + } + + print((int*) "-------------------------"); + println(); + } else { + print("Unknown event type"); + println(); + + osCurrentProcess = osFindProcess(callerPid, osProcessList); + + switch_context(callerPid); + } + } +} + +void copyPageFrame(int* parentFrame, int* childFrame) { + int* cursor; + + cursor = parentFrame; + + while ((int) cursor != (int) parentFrame + PAGE_FRAME_SIZE) { + *childFrame = *cursor; + childFrame = childFrame + 1; + cursor = cursor + 1; + } +} + +int srvSchedule() { + int* next; + int next_pid; + + next = context_getNext(kernelCurrentContext); + + if ((int) next == 0) { + next = kernelProcessList; + next = context_getNext(kernelProcessList); + } + + kernelCurrentContext = next; + + if ((int) next == 0) { + next_pid = 0; + } else { + next_pid = context_getPID(next); + } + + return next_pid; } // ----------------------------------------------------------------- @@ -5040,131 +6933,148 @@ void emulate(int argc, int *argv) { // ----------------------------------------------------------------- int selfie(int argc, int* argv) { - if (argc < 2) - return -1; - else { - while (argc >= 2) { - if (stringCompare((int*) *argv, (int*) "-c")) { - sourceName = (int*) *(argv+1); - binaryName = sourceName; - - argc = argc - 2; - argv = argv + 2; - - compile(); - } else if (stringCompare((int*) *argv, (int*) "-o")) { - binaryName = (int*) *(argv+1); - - argc = argc - 2; - argv = argv + 2; - - if (binaryLength > 0) - emit(); - else { - print(selfieName); - print((int*) ": nothing to emit to output file "); - print(binaryName); - println(); - } - } else if (stringCompare((int*) *argv, (int*) "-s")) { - assemblyName = (int*) *(argv+1); - argc = argc - 2; - argv = argv + 2; + if (argc == 0) + if (kernel_mode == 1) + halt = 1; - if (binaryLength > 0) { - initMemory(binaryLength); + if (argc <= 1) { + return -1; + } else { + while (argc >= 2) { + if (stringCompare((int*) *argv, (int*) "-c")) { + sourceName = (int*) *(argv + 1); + binaryName = sourceName; - disassemble(); - } else { - print(selfieName); - print((int*) ": nothing to disassemble to output file "); - print(assemblyName); - println(); - } - } else if (stringCompare((int*) *argv, (int*) "-l")) { - binaryName = (int*) *(argv+1); + argc = argc - 2; + argv = argv + 2; - argc = argc - 2; - argv = argv + 2; + compile(); + } else if (stringCompare((int*) *argv, (int*) "-o")) { + binaryName = (int*) *(argv + 1); - load(); - } else if (stringCompare((int*) *argv, (int*) "-m")) { - initMemory(atoi((int*) *(argv+1)) * MEGABYTE); + argc = argc - 2; + argv = argv + 2; - argc = argc - 1; - argv = argv + 1; + if (binaryLength > 0) + emit(); + else { + print(selfieName); + print((int*) ": nothing to emit to output file "); + print(binaryName); + println(); + } + } else if (stringCompare((int*) *argv, (int*) "-s")) { + assemblyName = (int*) *(argv + 1); - // pass binaryName as first argument replacing size - *argv = (int) binaryName; + argc = argc - 2; + argv = argv + 2; - if (binaryLength > 0) { - debug = 0; + if (binaryLength > 0) { + initMemory(binaryLength); - emulate(argc, argv); - } else { - print(selfieName); - print((int*) ": nothing to emulate"); - println(); + disassemble(); + } else { + print(selfieName); + print((int*) ": nothing to disassemble to output file "); + print(assemblyName); + println(); + } + } else if (stringCompare((int*) *argv, (int*) "-l")) { + binaryName = (int*) *(argv + 1); - exit(-1); - } + argc = argc - 2; + argv = argv + 2; - return 0; - } else if (stringCompare((int*) *argv, (int*) "-d")) { - initMemory(atoi((int*) *(argv+1)) * MEGABYTE); + load(); - argc = argc - 1; - argv = argv + 1; + } else if (stringCompare((int*) *argv, (int*) "-m")) { - // pass binaryName as first argument replacing size - *argv = (int) binaryName; + initMemory(atoi((int*) *(argv + 1)) * MEGABYTE); - if (binaryLength > 0) { - debug = 1; + argc = argc - 1; + argv = argv + 1; - emulate(argc, argv); - } else { - print(selfieName); - print((int*) ": nothing to debug"); - println(); + // pass binaryName as first argument replacing size + *argv = (int) binaryName; - exit(-1); - } + if (binaryLength > 0) { + debug = 0; + emulate(argc, argv); + } else { + print(selfieName); + print((int*) ": nothing to emulate"); + println(); - return 0; - } else if (stringCompare((int*) *argv, (int*) "-k")) { - print(selfieName); - print((int*) ": selfie -k size ... not yet implemented"); - println(); + exit(-1); + } - return 0; - } else - return -1; - } - } + return 0; + + } else if (stringCompare((int*) *argv, (int*) "-d")) { + initMemory(atoi((int*) *(argv + 1)) * MEGABYTE); + + argc = argc - 1; + argv = argv + 1; + + // pass binaryName as first argument replacing size + *argv = (int) binaryName; + + if (binaryLength > 0) { + debug = 1; + + emulate(argc, argv); + } else { + print(selfieName); + print((int*) ": nothing to debug"); + println(); - return 0; + exit(-1); + } + + return 0; + } else if (stringCompare((int*) *argv, (int*) "-k")) { + kernelBinaryName = (int*) *(argv + 2); + initMemory(128 * *(argv + 1)); + + argc = argc - 2; + argv = argv + 2; + + interpret = 1; + + loadKernel(); + + kernel(argc, argv); + + argc = 0; + } else + return -1; + } + } + + return 0; } int main(int argc, int *argv) { - initLibrary(); - - initScanner(); - - initRegister(); - initDecoder(); - - initInterpreter(); - - selfieName = (int*) *argv; - - argc = argc - 1; - argv = argv + 1; - - if (selfie(argc, (int*) argv) != 0) { - print(selfieName); - print((int*) ": usage: selfie { -c source | -o binary | -s assembly | -l binary } [ -m size ... | -d size ... | -k size ... ] "); - println(); - } -} \ No newline at end of file + + initLibrary(); + + initScanner(); + + initRegister(); + initDecoder(); + + initInterpreter(); + + selfieName = (int*) *argv; + + argc = argc - 1; + argv = argv + 1; + + if (selfie(argc, (int*) argv) != 0) { + print(selfieName); + print((int*) ": usage: selfie { -c source | -o binary | -s assembly | -l binary } [ -m size ... | -d size ... | -k size ... ] "); + println(); + } + +} diff --git a/test.c b/test.c new file mode 100644 index 0000000..11b4cd6 --- /dev/null +++ b/test.c @@ -0,0 +1,74 @@ +int main() { + + int* a; + int pid; + + a = malloc(4096); + + *(a+1000) = 1; + + *(a+2000) = 1; + + putchar('h'); + putchar('e'); + putchar('l'); + putchar('l'); + putchar('o'); + putchar(' '); + + pid = fork(); + + lock(); + + putchar('l'); + putchar('o'); + putchar('c'); + putchar('k'); + + unlock(); + + putchar('t'); + putchar('e'); + putchar('s'); + putchar('t'); + + if (pid > 0) { + wait(pid); + + putchar('z'); + + pid = fork(); + + if (pid > 0) { + wait(pid); + exit(24); + } + + putchar('i'); + putchar('i'); + putchar('i'); + putchar('i'); + putchar('i'); + + exit(7); + } else { + putchar('k'); + putchar('k'); + putchar('k'); + putchar('k'); + putchar('k'); + + lock(); + + putchar('k'); + + unlock(); + + putchar('k'); + putchar('k'); + putchar('k'); + putchar('k'); + + exit(5); + } +} diff --git a/treiber.c b/treiber.c new file mode 100644 index 0000000..28eae9a --- /dev/null +++ b/treiber.c @@ -0,0 +1,70 @@ +int* treiberStack = (int*) 0; +int* treiberStackTop = (int*) 0; + +void treiberPush(int* treiberStack, int value) { + int* node; + int* top; + + int casSucceed; + + casSucceed = 0; + + node = malloc(2*4); + + *node = value; + *(node + 1) = (int) 0; + + while (casSucceed == 0) { + top = treiberStackTop; + *(node + 1) = (int) top; + + casSucceed = (int) cas(treiberStackTop, top, node); + } +} + +int treiberPop(int* treiberStack, int* poppedValue) { + int* top; + int casSucceed; + + casSucceed = 0; + + while (casSucceed == 0) { + top = treiberStackTop; + + if ((int) top == 0) { + return 0; + } + + casSucceed = (int) cas(treiberStackTop, top, *(top + 1)); + } + + *poppedValue = *top; + + return 1; +} + +void testTreiberStack() { + int* pop; + + pop = malloc(4); + + treiberPush(treiberStack, 23); + + treiberPush(treiberStack, 66); + + treiberPop(treiberStack, pop); + + treiberPush(treiberStack, 42); +} + +int main() { + int pid; + + pid = tfork(); + pid = tfork(); + pid = tfork(); + + testTreiberStack(); + + exit(0); +}