From 3592da79bbf0a39d0e57371a15de833a67c7ded4 Mon Sep 17 00:00:00 2001 From: Christoph Kirsch Date: Mon, 7 Jul 2014 15:20:25 +0200 Subject: [PATCH 01/26] Initial commit --- LICENSE | 23 +++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 27 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..50113bb --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2014, Christoph Kirsch +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5b2682a --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +AOS-Winter-2014 +=============== + +Advanced Operating Systems 2014 From 86b740a4a79d8a29b9888813d7ead98513f1f148 Mon Sep 17 00:00:00 2001 From: Christoph Kirsch Date: Thu, 25 Jun 2015 14:29:47 +0200 Subject: [PATCH 02/26] Updated to 2015 --- LICENSE | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index 50113bb..bc3f908 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014, Christoph Kirsch +Copyright (c) 2015, Christoph Kirsch All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/README.md b/README.md index 5b2682a..4f90635 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -AOS-Winter-2014 +AOS-Winter-2015 =============== -Advanced Operating Systems 2014 +Advanced Operating Systems 2015 From 0061b458bae2f4945e0a1271a01e388125711e2e Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Tue, 6 Oct 2015 16:02:30 +0200 Subject: [PATCH 03/26] added assignment 0 --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 4f90635..3d4a461 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,28 @@ AOS-Winter-2015 =============== Advanced Operating Systems 2015 + + +Home work flow +============== + +* Step 1: get a github account +* Step 2: fork the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) +* Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015. +* Step 4: Implement the first assignment (see below) +* Step 5: Send a pull request containing your solution via github.com to __cksystemsteaching/AOS-Winter-2015__ + + +Assignment 0 +------------ + +Review [linked lists](https://en.wikipedia.org/wiki/Linked_list) and implement a simple program using a singly linked list in C*. The minimal requirements are as follows: + +* must be implemented in C* +* must compile with selfie +* must run on selfie +* the list must be dynamically allocated +* every node must be dynamically allocated +* inserting nodes to the list and removing nodes from the list +* list iteration +* Bonus: sort the list. Any way you like From 6af3c90f57767270b2fc6a99bbcfa3439ee8f6a2 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Tue, 6 Oct 2015 16:07:34 +0200 Subject: [PATCH 04/26] added link to branch --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d4a461..1a91518 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ Home work flow * Step 1: get a github account * Step 2: fork the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) -* Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015. +* Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015 * Step 4: Implement the first assignment (see below) -* Step 5: Send a pull request containing your solution via github.com to __cksystemsteaching/AOS-Winter-2015__ +* Step 5: Send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) Assignment 0 From 5cb5835dcaa7ebc9546e092b2dda569b3e495646 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Tue, 6 Oct 2015 16:19:12 +0200 Subject: [PATCH 05/26] added note on building teams --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1a91518..ade8ae3 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ Advanced Operating Systems 2015 Home work flow ============== -* Step 1: get a github account -* Step 2: fork the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) +* Step 0: form a team of 2-3 members +* Step 1: get a github account (for each member) +* Step 2: one person per group forks the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) and adds the other team members as collaborators * Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015 * Step 4: Implement the first assignment (see below) * Step 5: Send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) From dad152f7df4f1ed3753e1066e7a428d3e87a35a7 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Tue, 6 Oct 2015 16:20:38 +0200 Subject: [PATCH 06/26] added step on authors --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ade8ae3..bc928e4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ Home work flow * Step 2: one person per group forks the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) and adds the other team members as collaborators * Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015 * Step 4: Implement the first assignment (see below) -* Step 5: Send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) +* Step 5: Add your names to the AUTHORS file +* Step 6: Send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) Assignment 0 From 8807eaa93e5edfa1d156a6cab86f1de7e25da433 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Tue, 6 Oct 2015 16:21:02 +0200 Subject: [PATCH 07/26] typos --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc928e4..82cad52 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Home work flow * Step 1: get a github account (for each member) * Step 2: one person per group forks the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) and adds the other team members as collaborators * Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015 -* Step 4: Implement the first assignment (see below) -* Step 5: Add your names to the AUTHORS file -* Step 6: Send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) +* Step 4: implement the first assignment (see below) +* Step 5: add your names to the AUTHORS file +* Step 6: send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) Assignment 0 From b2b73c1e9b14386f8d086ad282d1c1d52e82f04f Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Wed, 7 Oct 2015 11:54:10 +0200 Subject: [PATCH 08/26] draft of assignment 1 --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 82cad52..f9899d5 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,21 @@ Review [linked lists](https://en.wikipedia.org/wiki/Linked_list) and implement a * inserting nodes to the list and removing nodes from the list * list iteration * Bonus: sort the list. Any way you like +* Deadline: Oct 15, end of day + + +Assignment 1: Loading, scheduling, switching, execution +------------------------------------------------------- + +Implement basic concurrent executio of _n_ processes in mipster. _n >= 2_ + +* understand how mipster [interprets and executes binary instructions](https://github.com/cksystemsteaching/AOS-Winter-2015/blob/selfie-master/selfie.c#L3933). Tipp: Add your own comments to the code +* mipster maintains a local state for a process (running executable), e.g., pc, registers, memory +* understand the purpose of each variable and data structure +* duplicate the process state n times +* running mipster like: _./selfie -m 32 yourbinary_ should generate _n_ instances of _yourbinary_ in a single instance of mipster +* implement [preemptive multitasking](https://en.wikipedia.org/wiki/Preemption_(computing)), i.e., switching between the _n_ instances of _yourbinary_ is determined by mipster +* switch processes every m instructions. _1 <= m <= number of instructions in yourbinary_ +* implement [round-robin scheduling](https://en.wikipedia.org/wiki/Round-robin_scheduling) +* add some output in _yourbinary_ to demonstrate context switching +* Deadline: Oct 22, end of day From a7ee2f70ddc49ee35c7a7038c6dfee2e1bfb8089 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Wed, 7 Oct 2015 11:55:08 +0200 Subject: [PATCH 09/26] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9899d5..456e7f2 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Assignment 1: Loading, scheduling, switching, execution Implement basic concurrent executio of _n_ processes in mipster. _n >= 2_ -* understand how mipster [interprets and executes binary instructions](https://github.com/cksystemsteaching/AOS-Winter-2015/blob/selfie-master/selfie.c#L3933). Tipp: Add your own comments to the code +* understand how mipster [interprets and executes binary instructions](https://github.com/cksystemsteaching/AOS-Winter-2015/blob/selfie-master/selfie.c#L3933). Tipp: add your own comments to the code * mipster maintains a local state for a process (running executable), e.g., pc, registers, memory * understand the purpose of each variable and data structure * duplicate the process state n times From b1344e0183a461a56e8609ca6787fef62b6ac4c9 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Wed, 7 Oct 2015 12:01:46 +0200 Subject: [PATCH 10/26] nother typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 456e7f2..9ac1d36 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Review [linked lists](https://en.wikipedia.org/wiki/Linked_list) and implement a Assignment 1: Loading, scheduling, switching, execution ------------------------------------------------------- -Implement basic concurrent executio of _n_ processes in mipster. _n >= 2_ +Implement basic concurrent execution of _n_ processes in mipster. _n >= 2_ * understand how mipster [interprets and executes binary instructions](https://github.com/cksystemsteaching/AOS-Winter-2015/blob/selfie-master/selfie.c#L3933). Tipp: add your own comments to the code * mipster maintains a local state for a process (running executable), e.g., pc, registers, memory From b215e50bd0b06587b520653a35cd4f5772fd25e1 Mon Sep 17 00:00:00 2001 From: Christoph Kirsch Date: Tue, 13 Oct 2015 16:18:00 +0200 Subject: [PATCH 11/26] Polished README --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9ac1d36..d9ed20e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,4 @@ -AOS-Winter-2015 -=============== - -Advanced Operating Systems 2015 - - -Home work flow +Home Work Flow ============== * Step 0: form a team of 2-3 members @@ -16,8 +10,8 @@ Home work flow * Step 6: send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) -Assignment 0 ------------- +Assignment 0: Basic data structures +----------------------------------- Review [linked lists](https://en.wikipedia.org/wiki/Linked_list) and implement a simple program using a singly linked list in C*. The minimal requirements are as follows: @@ -46,4 +40,4 @@ Implement basic concurrent execution of _n_ processes in mipster. _n >= 2_ * switch processes every m instructions. _1 <= m <= number of instructions in yourbinary_ * implement [round-robin scheduling](https://en.wikipedia.org/wiki/Round-robin_scheduling) * add some output in _yourbinary_ to demonstrate context switching -* Deadline: Oct 22, end of day +* Deadline: Oct 22, end of day \ No newline at end of file From d59eedb453fca7fa76fefc25599d40eb13730f77 Mon Sep 17 00:00:00 2001 From: Christoph Kirsch Date: Tue, 13 Oct 2015 16:19:14 +0200 Subject: [PATCH 12/26] Polished README further --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9ed20e..ea203a1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ Home Work Flow -============== +-------------- * Step 0: form a team of 2-3 members * Step 1: get a github account (for each member) From a0ef6e7b5980b24694f3b664ee63e65589811578 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 15 Oct 2015 13:13:03 +0200 Subject: [PATCH 13/26] Assignment 0 --- list.c | 345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 15 +++ 2 files changed, 360 insertions(+) create mode 100644 list.c create mode 100644 makefile diff --git a/list.c b/list.c new file mode 100644 index 0000000..74f8efd --- /dev/null +++ b/list.c @@ -0,0 +1,345 @@ +int main(); +int *string_buffer; +int CHAR_LF; +int CHAR_TAB; +int CHAR_CR; +int INT_MIN; +int INT_MAX; +int result; +int *power_of_two_table; + + + +void printString(int c0, int c1, int c2, int c3, int c4, + int c5, int c6, int c7, int c8, int c9, + int c10, int c11, int c12, int c13, int c14, + int c15, int c16, int c17, int c18, int c19); +void assignString(int *s, int c0, int c1, int c2, int c3, int c4, + int c5, int c6, int c7, int c8, int c9, + int c10, int c11, int c12, int c13, int c14, + int c15, int c16, int c17, int c18, int c19); +void print(int *s); + + +void assignString(int *s, int c0, int c1, int c2, int c3, int c4, + int c5, int c6, int c7, int c8, int c9, + int c10, int c11, int c12, int c13, int c14, + int c15, int c16, int c17, int c18, int c19) { + + *(s+0) = c0; *(s+1) = c1; *(s+2) = c2; *(s+3) = c3; *(s+4) = c4; + *(s+5) = c5; *(s+6) = c6; *(s+7) = c7; *(s+8) = c8; *(s+9) = c9; + *(s+10) = c10; *(s+11) = c11; *(s+12) = c12; *(s+13) = c13; *(s+14) = c14; + *(s+15) = c15; *(s+16) = c16; *(s+17) = c17; *(s+18) = c18; *(s+19) = c19; + *(s+20) = 0; +} + +void printString(int c0, int c1, int c2, int c3, int c4, + int c5, int c6, int c7, int c8, int c9, + int c10, int c11, int c12, int c13, int c14, + int c15, int c16, int c17, int c18, int c19) { + + assignString(string_buffer, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + + print(string_buffer); +} + +void print(int *s) { + while (*s != 0) { + putchar(*s); + s = s + 1; + } +} + +int stringLength(int *s) { + int i; + + i = 0; + + while (*(s+i) != 0) + i = i + 1; + + return i; +} + +void reverseString(int *s) { + int tmp; + int i; + int j; + + i = 0; + j = stringLength(s) - 1; + + while (i < j) { + tmp = *(s+i); + *(s+i) = *(s+j); + *(s+j) = tmp; + i = i + 1; + j = j - 1; + } +} + +int* itoa(int n, int *s, int b, int a) { + // assert: b in {2,4,8,10,16} + + int i; + int sign; + + i = 0; + + sign = 0; + + if (n == 0) { + *s = '0'; + + i = 1; + } else if (n < 0) { + sign = 1; + + if (b == 10) { + if (n == INT_MIN) { + *s = '8'; // rightmost decimal digit of 32-bit INT_MIN + + n = -(n / 10); + i = i + 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + *s = '0'; // rightmost non-decimal digit of INT_MIN + + n = (rightShift(INT_MIN, 1) / b) * 2; + i = i + 1; + } else + n = rightShift(leftShift(n, 1), 1); + } + } + + while (n != 0) { + *(s+i) = n % b; + + if (*(s+i) > 9) + *(s+i) = *(s+i) - 10 + 'A'; + else + *(s+i) = *(s+i) + '0'; + + n = n / b; + i = i + 1; + + if (i == 1) { + if (sign) { + if (b != 10) + n = n + (rightShift(INT_MIN, 1) / b) * 2; + } + } + } + + if (b != 10) { + while (i < a) { + *(s+i) = '0'; // align with zeros + + i = i + 1; + } + } else if (sign) { + *(s+i) = '-'; + + i = i + 1; + } + + *(s+i) = 0; // null terminated string + + reverseString(s); + + return s; +} + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + + +void init (){ + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; + INT_MIN = -INT_MAX - 1; + + CHAR_TAB = 9; // ASCII code 9 = tabulator + CHAR_LF = 10; // ASCII code 10 = linefeed + CHAR_CR = 13; // ASCII code 13 = carriage return + + string_buffer = malloc(33*4); + + +} + + +int * insert(int data, int * head){ + int * adr; + + adr = (int*)malloc (2*4); + *adr = data; + *(adr+1) = head; + + return adr; + +} + +void printList(int*head){ + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + while ((int)(head) != 0){ + print(itoa(*(head),number_buffer,10,0)); + putchar(CHAR_LF); + head = *(head+1); + } +} + +void sortList(int *head){ + int i; + int j; + int help; + int* temp; + + i = 0; + j = 0; + + while(*(head+1) != 0){ + + temp = *(head+1); + + while((int)(temp) != 0){ + + if(*(head) < *(temp)){ + help = *(temp); + *temp = *head; + *head = help; + } + + temp = *(temp+1); + } + + head = *(head+1); + } +} + +void remove(int data, int * head){ + int* current; + int* previous; + int* help; + + current = head; + previous = 0; + + if(*(current) == data){ + help = *(current+1); + *current = *help; + *(current+1) = *(help+1); + } + else{ + while((int)current != 0){ + if(*(current) == data){ + *(previous+1) =(int*)(*(current+1)); + current = 0; + } + else{ + previous = current; + current = *(current+1); + } + } + } +} + + + +int main(){ + int* head; + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + init(); + + //inserting + head = insert(7,head); + head = insert(8,head); + head = insert(3,head); + head = insert(6,head); + head = insert(9,head); + head = insert(16,head); + head = insert(18,head); + head = insert(50,head); + head = insert(42,head); + head = insert(31,head); + head = insert(39,head); + head = insert(29,head); + head = insert(13,head); + head = insert(0,head); + head = insert(72,head); + head = insert(51,head); + + //printing + putchar(CHAR_LF); + printString('O','r','i','g','i','n','a','l',' ','L','i','s','t',' ',0,0,0,0,0,0); + putchar(CHAR_LF); + printList(head); + putchar(CHAR_LF); + + //removing 9, inserting 4 + remove(9,head); + head = insert(4,head); + + //printing + printString('R','e','m','o','v','e','d',' ','9',' ','I','n','s','e','r','t','e','d',' ','4'); + putchar(CHAR_LF); + printList(head); + + //sorting + sortList(head); + + + //printing + putchar(CHAR_LF); + printString('S','o','r','t','e','d',' ','L','i','s','t',' ',0,0,0,0,0,0,0,0); + putchar(CHAR_LF); + printList(head); + + exit(0); +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..7a49208 --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +CFLAGS=-O3 -Wall + +PROGRAMS=selfie + + +default: compile run + +compile: + -rm -r $ list.mips + -touch out + ./selfie < list.c + -mv out list.mips + +run: + ./selfie -m 32 list.mips From b01c56d004ff5521904439a9cee772ea1922710f Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 15 Oct 2015 13:15:30 +0200 Subject: [PATCH 14/26] Assignment 0 --- AUTHORS.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 AUTHORS.txt diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..a284922 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,3 @@ +HASIC DALMIR 1121497 +Git username: dhasic +E-mail: dhasic@cs.uni-salzburg.at \ No newline at end of file From 1645fd08cf21fb24b90edceb28952e176cff28fe Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 22 Oct 2015 21:12:06 +0200 Subject: [PATCH 15/26] Assignment1 --- selfie.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++- test.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 test.c diff --git a/selfie.c b/selfie.c index c2b5d87..32c2383 100755 --- a/selfie.c +++ b/selfie.c @@ -857,6 +857,40 @@ int ir; // instruction record int reg_hi; // hi register for multiplication/division int reg_lo; // lo register for multiplication/division + +// -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- + +void push(int *mem, int *reg, int *reg_hi, int *reg_lo, int pc, int *head); + +void setPrcosessNext(int *process, int *next); +void setProcessPc(int * process, int pc); +void setProcessMemory(int *process, int *memory); +void setProcessRegisters(int *process, int *registers); +void setProcessRegHi(int *process, int reg_hi); +void setProcessRegLo(int *process, int reg_lo); + +int* getProcessNext(int *process); +int getProcessPc(int *process); +int* getProcessMemory(int *process); +int* getProcessRegisters(int *process); +int getProcessRegHi(int *process); +int getProcessRegLo(int *process); + +void createProcessList(int numberoOfProcesses); +void createProcess(int *head); +void memCopy(int *oldMemory, int *newMemory, int length); + + +int* pop(int *head); +void scheduler(); + +// ------------------ADDITIONAL GLOBAL VARIABLES A1 -------------- + +int* readyqueue; +int memSize; +int numberofInstructions; + + // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { @@ -938,6 +972,9 @@ void initInterpreter() { reg_hi = 0; reg_lo = 0; + + readyqueue = 0;//ADDED A1 + numberofInstructions = 0; //ADDED A1 } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -3930,15 +3967,24 @@ void execute() { } } +//A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH void run() { - + pop(readyqueue); while (1) { fetch(); decode(); pre_debug(); execute(); post_debug(); + + numberofInstructions = numberofInstructions + 1; + if(numberofInstructions > 10){ + scheduler(); + } + } + + } void debug_boot(int memorySize) { @@ -3956,7 +4002,8 @@ int* parse_args(int argc, int *argv, int *cstar_argv) { memorySize = atoi((int*)*(cstar_argv+2)) * 1024 * 1024 / 4; allocateMachineMemory(memorySize*4); - + memSize = memorySize; //ADDED A1 + // initialize stack pointer *(registers+REG_SP) = (memorySize - 1) * 4; @@ -4052,11 +4099,188 @@ int main_emulator(int argc, int *argv, int *cstar_argv) { *(registers+REG_K1) = *(registers+REG_GP); up_copyArguments(argc-3, argv+3); + + createProcessList(3); //ADDED CREATES LIST WITH 3 PROCESSES run(); exit(0); } +// ---------------------------------------------------------------- +// ---------------------ASSIGNMENT 1 ------------------------------ +// ---------------------------------------------------------------- + + +void memCopy(int *oldMemory, int *newMemory, int length) { + int i; + + i = 0; + + while (i < length) { + *(newMemory+i) = *(oldMemory+i); + i = i + 1; + } +} + +void createProcessList (int numberoOfProcesses){ + int i; + i = 0; + + while(i 9) + *(s+i) = *(s+i) - 10 + 'A'; + else + *(s+i) = *(s+i) + '0'; + + n = n / b; + i = i + 1; + + if (i == 1) { + if (sign) { + if (b != 10) + n = n + (rightShift(INT_MIN, 1) / b) * 2; + } + } + } + + if (b != 10) { + while (i < a) { + *(s+i) = '0'; // align with zeros + + i = i + 1; + } + } else if (sign) { + *(s+i) = '-'; + + i = i + 1; + } + + *(s+i) = 0; // null terminated string + + reverseString(s); + + return s; +} + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + + +void init (){ + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; + INT_MIN = -INT_MAX - 1; + + CHAR_TAB = 9; // ASCII code 9 = tabulator + CHAR_LF = 10; // ASCII code 10 = linefeed + CHAR_CR = 13; // ASCII code 13 = carriage return + + string_buffer = malloc(33*4); + + +} + + + + + +int main(){ + int* head; + int* number_buffer; + + number_buffer = (int*) malloc (10 * 4); + + init(); + + print(itoa(1, string_buffer, 10, 0)); + + + print(itoa(2, string_buffer, 10, 0)); + print(itoa(3, string_buffer, 10, 0)); + print(itoa(4, string_buffer, 10, 0)); + print(itoa(5, string_buffer, 10, 0)); + + print(itoa(6, string_buffer, 10, 0)); + print(itoa(7, string_buffer, 10, 0)); + print(itoa(8, string_buffer, 10, 0)); + print(itoa(9, string_buffer, 10, 0)); + putchar(CHAR_LF); + + + + exit(0); +} \ No newline at end of file From 3801a78d3821739457d88d480b841091ee14ee2d Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 29 Oct 2015 19:30:32 +0100 Subject: [PATCH 16/26] removed authors file --- AUTHORS.txt | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 AUTHORS.txt diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index a284922..0000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,3 +0,0 @@ -HASIC DALMIR 1121497 -Git username: dhasic -E-mail: dhasic@cs.uni-salzburg.at \ No newline at end of file From d0ae3844dd3a1dfecd2eb45cec5fbd6847c76c81 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 29 Oct 2015 19:32:02 +0100 Subject: [PATCH 17/26] Assignment 2 --- AUTHORS | 3 +- selfie.c | 3780 +++++++++++++++++++++++++++++------------------------- test.c | 5 +- 3 files changed, 2007 insertions(+), 1781 deletions(-) diff --git a/AUTHORS b/AUTHORS index f8c27e6..8629a2f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,4 +2,5 @@ Martin Aigner Christian Barthel Christoph Kirsch Michael Lippautz -Simone Oblasser \ No newline at end of file +Simone Oblasser +Dalmir Hasic \ No newline at end of file diff --git a/selfie.c b/selfie.c index 32c2383..d56674a 100755 --- a/selfie.c +++ b/selfie.c @@ -80,39 +80,53 @@ int leftShift(int n, int b); int rightShift(int n, int b); int stringLength(int *s); -void reverseString(int *s); +void stringReverse(int *s); int stringCompare(int *s, int *t); + int atoi(int *s); int* itoa(int n, int *s, int b, int a); + void print(int *s); -void assignString(int *s, int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -int* createString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -void printString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19); -void memset(int *a, int size, int v); +void println(); + +void printCharacter(int character); +void printString(int *s); void exit(int code); int* malloc(int size); // ------------------------ GLOBAL CONSTANTS ----------------------- +int CHAR_EOF = -1; // end of file +int CHAR_TAB = 9; // ASCII code 9 = tabulator +int CHAR_LF = 10; // ASCII code 10 = line feed +int CHAR_CR = 13; // ASCII code 13 = carriage return +int CHAR_SPACE = ' '; +int CHAR_SEMICOLON = ';'; +int CHAR_PLUS = '+'; +int CHAR_DASH = '-'; +int CHAR_ASTERISK = '*'; +int CHAR_HASH = '#'; +int CHAR_SLASH = '/'; +int CHAR_UNDERSCORE = '_'; +int CHAR_EQUAL = '='; +int CHAR_LPARENTHESIS = '('; +int CHAR_RPARENTHESIS = ')'; +int CHAR_LBRACE = '{'; +int CHAR_RBRACE = '}'; +int CHAR_COMMA = ','; +int CHAR_LT = '<'; +int CHAR_GT = '>'; +int CHAR_EXCLAMATION = '!'; +int CHAR_PERCENTAGE = '%'; +int CHAR_SINGLEQUOTE = 39; // ASCII code 39 = ' +int CHAR_DOUBLEQUOTE = '"'; + int *power_of_two_table; int INT_MAX; // maximum numerical value of an integer int INT_MIN; // minimum numerical value of an integer -int CHAR_TAB; -int CHAR_LF; -int CHAR_CR; - int *string_buffer; // ------------------------- INITIALIZATION ------------------------ @@ -136,11 +150,8 @@ void initLibrary() { INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; INT_MIN = -INT_MAX - 1; - CHAR_TAB = 9; // ASCII code 9 = tabulator - CHAR_LF = 10; // ASCII code 10 = linefeed - CHAR_CR = 13; // ASCII code 13 = carriage return - - string_buffer = malloc(33*4); + // accommodate 32-bit numbers for itoa + string_buffer = malloc(33); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -155,342 +166,160 @@ void initLibrary() { void initScanner(); -int findNextCharacter(); +void printSymbol(int symbol); +void printLineNumber(int* message); + +void syntaxErrorMessage(int *message); +void syntaxErrorCharacter(int character); + int isCharacterWhitespace(); -int isCharacterLetterOrDigitOrUnderscore(); -int isCharacterDigit(); +int findNextCharacter(); int isCharacterLetter(); +int isCharacterDigit(); +int isCharacterLetterOrDigitOrUnderscore(); +int isNotDoubleQuoteOrEOF(); int identifierStringMatch(int stringIndex); int identifierOrKeyword(); int getSymbol(); -void syntaxWarn(int errCode); -void syntaxError(int errCode); - // ------------------------ GLOBAL CONSTANTS ----------------------- -int SYM_EOF; // end of file -int SYM_IDENTIFIER; // identifier -int SYM_INTEGER; // a number -int SYM_VOID; // VOID -int SYM_INT; // INT -int SYM_SEMICOLON; // ; -int SYM_IF; // IF -int SYM_ELSE; // ELSE -int SYM_PLUS; // + -int SYM_MINUS; // - -int SYM_ASTERISK; // * -int SYM_DIV; // / -int SYM_EQUAL; // == -int SYM_ASSIGN; // = -int SYM_LPARENTHESIS; // ( -int SYM_RPARENTHESIS; // ) -int SYM_LBRACE; // { -int SYM_RBRACE; // } -int SYM_WHILE; // WHILE -int SYM_RETURN; // RETURN -int SYM_COMMA; // , -int SYM_LT; // < -int SYM_LEQ; // <= -int SYM_GT; // > -int SYM_GEQ; // >= -int SYM_NOTEQ; // != -int SYM_MOD; // % -int SYM_CHARACTER; // char value - -int maxIdentifierLength; // maximum number of characters in an identifier -int maxIntegerLength; // maximum number of characters in an integer - -// Error-Token declaration -int ERR_EOF; -int ERR_UNKNOWN; -int ERR_EXPRESSION; -int ERR_TYPE; -int ERR_IDENTIFIER_OR_LPARENTHESIS; -int ERR_IDENTIFIER; -int ERR_ASSIGN; -int ERR_IDENTIFIER_OR_ASSIGN; -int ERR_IDENT_OR_CONST_OR_EXP; -int ERR_LBRACE_OR_SEMICOLON; -int ERR_PROCEDURE_OR_VARIABLE; -int ERR_UNDECLARED_VARIABLE; -int ERR_TYPE_MISMATCH; -int ERR_WRONG_RETURNTYPE; -int ERR_MAXCODELENGTH; -int ERR_MAXIDENTIFIERLENGTH; -int ERR_WRAPAROUND; -int ERR_STATEMENT; -int ERR_FILE_NOT_FOUND; -int ERR_ILLEGAL_DEREF; -int ERR_IDENTIFIER_OR_INTEGER; - -// strings for better error messages -int *error; -int *warning; -int *errNewline; -int *errLine; -int *errSymbol; -int *stringArray; +int SYM_EOF = -1; // end of file +int SYM_IDENTIFIER = 0; // identifier +int SYM_INTEGER = 1; // integer +int SYM_VOID = 2; // VOID +int SYM_INT = 3; // INT +int SYM_SEMICOLON = 4; // ; +int SYM_IF = 5; // IF +int SYM_ELSE = 6; // ELSE +int SYM_PLUS = 7; // + +int SYM_MINUS = 8; // - +int SYM_ASTERISK = 9; // * +int SYM_DIV = 10; // / +int SYM_EQUALITY = 11; // == +int SYM_ASSIGN = 12; // = +int SYM_LPARENTHESIS = 13; // ( +int SYM_RPARENTHESIS = 14; // ) +int SYM_LBRACE = 15; // { +int SYM_RBRACE = 16; // } +int SYM_WHILE = 17; // WHILE +int SYM_RETURN = 18; // RETURN +int SYM_COMMA = 19; // , +int SYM_LT = 20; // < +int SYM_LEQ = 21; // <= +int SYM_GT = 22; // > +int SYM_GEQ = 23; // >= +int SYM_NOTEQ = 24; // != +int SYM_MOD = 25; // % +int SYM_CHARACTER = 26; // character +int SYM_STRING = 27; // string + +int *SYMBOLS; // array of strings representing symbols + +int maxIdentifierLength = 64; // maximum number of characters in an identifier +int maxIntegerLength = 10; // maximum number of characters in an integer +int maxStringLength = 64; // maximum number of characters in a string // ------------------------ GLOBAL VARIABLES ----------------------- -int lineNumber; // Current Line Number for error reporting -int character; // most recently read character -int symbol; // most recently recognized symbol - -int *identifier; // stores scanned identifier -int *integer; // stores scanned integer as string - -int ivalue; // stores numerical value of scanned integer string - -int mayBeINTMINConstant; // support INT_MIN constant - -// ------------------------- INITIALIZATION ------------------------ - -void initScanner () { - SYM_EOF = -1; // end of file - SYM_IDENTIFIER = 0; // identifier - SYM_INTEGER = 1; // a number - SYM_VOID = 2; // VOID - SYM_INT = 3; // INT - SYM_SEMICOLON = 4; // ; - SYM_IF = 5; // IF - SYM_ELSE = 6; // ELSE - SYM_PLUS = 7; // + - SYM_MINUS = 8; // - - SYM_ASTERISK = 9; // * - SYM_DIV = 10; // / - SYM_EQUAL = 11; // == - SYM_ASSIGN = 12; // = - SYM_LPARENTHESIS = 13; // ( - SYM_RPARENTHESIS = 14; // ) - SYM_LBRACE = 15; // { - SYM_RBRACE = 16; // } - SYM_WHILE = 17; // WHILE - SYM_RETURN = 18; // RETURN - SYM_COMMA = 19; // , - SYM_LT = 20; // < - SYM_LEQ = 21; // <= - SYM_GT = 22; // > - SYM_GEQ = 23; // >= - SYM_NOTEQ = 24; // != - SYM_MOD = 25; // % - SYM_CHARACTER = 26; // character value - - maxIdentifierLength = 64; - maxIntegerLength = 10; - - ERR_EOF = 40; //keep this b/c -1 is no valid array index - ERR_UNKNOWN = 41; - ERR_EXPRESSION = 42; - ERR_TYPE = 43; - ERR_IDENTIFIER_OR_LPARENTHESIS = 44; - ERR_IDENTIFIER = 45; - ERR_ASSIGN = 46; - ERR_IDENTIFIER_OR_ASSIGN = 47; - ERR_IDENT_OR_CONST_OR_EXP = 48; - ERR_LBRACE_OR_SEMICOLON = 49; - ERR_PROCEDURE_OR_VARIABLE = 50; - ERR_UNDECLARED_VARIABLE = 51; - ERR_TYPE_MISMATCH = 52; - ERR_WRONG_RETURNTYPE = 53; - ERR_MAXCODELENGTH = 54; - ERR_MAXIDENTIFIERLENGTH = 55; - ERR_WRAPAROUND = 56; - ERR_STATEMENT = 57; - ERR_FILE_NOT_FOUND = 58; - ERR_ILLEGAL_DEREF = 59; - ERR_IDENTIFIER_OR_INTEGER = 60; - - // ------------ "ERROR: " ------------ - error = createString('E','R','R','O','R',':',' ',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "WARNING: " ------------ - warning = createString('W','A','R','N','I','N','G',':',' ',0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "/n" ------------ - errNewline = createString(10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ", line " ------------ - errLine = createString(',',' ','l','i','n','e',' ',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ", current symbol: " ------------ - errSymbol = createString(',',' ','c','u','r','r','e','n','t',' ','s','y','m','b','o','l',':',' ',0,0); - - // -------------------- ERROR TOKENS -------------------- - - stringArray = (int*)malloc(4*70); - - // ------------ "unknown" ------------ - *(stringArray + ERR_UNKNOWN) = (int)createString('u','n','k','n','o','w','n',0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "expression" ------------ - *(stringArray + ERR_EXPRESSION) = (int)createString('e','x','p','r','e','s','s','i','o','n',0,0,0,0,0,0,0,0,0,0); - - // ------------ "while" ------------ - *(stringArray + SYM_WHILE) = (int)createString('w','h','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "if" ------------ - *(stringArray + SYM_IF) = (int)createString('i','f',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "return" ------------ - *(stringArray + SYM_RETURN) = (int)createString('r','e','t','u','r','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "type" ------------ - *(stringArray + ERR_TYPE) = (int)createString('t','y','p','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "(" ------------ - *(stringArray + SYM_LPARENTHESIS) = (int)createString('(',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ")" ------------ - *(stringArray + SYM_RPARENTHESIS) = (int)createString(')',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "{" ------------ - *(stringArray + SYM_LBRACE) = (int)createString('{',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "}" ------------ - *(stringArray + SYM_RBRACE) = (int)createString('}',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ ";" ------------ - *(stringArray + SYM_SEMICOLON) = (int)createString(';',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "ident or (" ------------ - *(stringArray + ERR_IDENTIFIER_OR_LPARENTHESIS) = (int)createString('i','d','e','n','t',' ','o','r',' ','(',0,0,0,0,0,0,0,0,0,0); - - // ------------ "identifier" ------------ - *(stringArray + ERR_IDENTIFIER) = (int)createString('i','d','e','n','t','i','f','i','e','r',0,0,0,0,0,0,0,0,0,0); - - // ------------ "assign" ------------ - *(stringArray + ERR_ASSIGN) = (int)createString('a','s','s','i','g','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "ident or assign" ------------ - *(stringArray + ERR_IDENTIFIER_OR_ASSIGN) = (int)createString('i','d','e','n','t',' ','o','r',' ','a','s','s','i','g','n',0,0,0,0,0); - - // ------------ "ident, const or exp" ------------ - *(stringArray + ERR_IDENT_OR_CONST_OR_EXP) = (int)createString('i','d','e','n','t',',',' ','c','o','n','s','t',' ','o','r',' ','e','x','p',0); - - // ------------ "( or ;" ------------ - *(stringArray + ERR_LBRACE_OR_SEMICOLON) = (int)createString('(',' ','o','r',' ',';',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "procedure or var"------------ - *(stringArray + ERR_PROCEDURE_OR_VARIABLE) = (int)createString('p','r','o','c','e','d','u','r','e',' ','o','r',' ','v','a','r',0,0,0,0); - - // ------------ "eof" ------------ - *(stringArray + ERR_EOF) = (int)createString('e','o','f',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +int lineNumber = 1; // current Line Number for error reporting - // ------------ "undeclared var"------------ - *(stringArray + ERR_UNDECLARED_VARIABLE) = (int)createString('u','n','d','e','c','l','a','r','e','d',' ','v','a','r',0,0,0,0,0,0); +int *identifier = (int*) 0; // stores scanned identifier as string +int *integer = (int*) 0; // stores scanned integer as string +int *string = (int*) 0; // stores scanned string - // ------------ "type mismatch" ------------ - *(stringArray + ERR_TYPE_MISMATCH) = (int)createString('t','y','p','e',' ','m','i','s','m','a','t','c','h',0,0,0,0,0,0,0); +int constant = 0; // stores numerical value of scanned integer or character - // ------------ "wrong return type" ------------ - *(stringArray + ERR_WRONG_RETURNTYPE) = (int)createString('w','r','o','n','g',' ','r','e','t','u','r','n',' ','t','y','p','e',0,0,0); +int initialValue = 0; // stores initial value of variable definitions - // ------------ "statement" ------------ - *(stringArray + ERR_STATEMENT) = (int)createString('s','t','a','t','e','m','e','n','t',0,0,0,0,0,0,0,0,0,0,0); +int mayBeINTMINConstant = 0; // support INT_MIN constant +int isINTMINConstant = 0; - // ------------ "wraparound" ------------ - *(stringArray + ERR_WRAPAROUND) = (int)createString('w','r','a','p','a','r','o','u','n','d',0,0,0,0,0,0,0,0,0,0); +int character; // most recently read character +int symbol; // most recently recognized symbol - // ------------ "maxcodelength" ------------ - *(stringArray + ERR_MAXCODELENGTH) = (int)createString('m','a','x','c','o','d','e','l','e','n','g','t','h',0,0,0,0,0,0,0); - - // ------------ "maxidentlength" ------------ - *(stringArray + ERR_MAXIDENTIFIERLENGTH) = (int)createString('m','a','x','i','d','e','n','t','l','e','n','g','t','h',0,0,0,0,0,0); - - // ------------ "file not found" ------------ - *(stringArray + ERR_FILE_NOT_FOUND) = (int)createString('f','i','l','e',' ','n','o','t',' ','f','o','u','n','d',0,0,0,0,0,0); - - // ------------ "else" ------------ - *(stringArray + SYM_ELSE) = (int)createString('e','l','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - // ------------ "void" ------------ - *(stringArray + SYM_VOID) = (int)createString('v','o','i','d',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +// ------------------------- INITIALIZATION ------------------------ - // ------------ "int" ------------ - *(stringArray + SYM_INT) = (int)createString('i','n','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +void initScanner () { + SYMBOLS = malloc(28*4); + + *(SYMBOLS + SYM_IDENTIFIER) = (int) "identifier"; + *(SYMBOLS + SYM_INTEGER) = (int) "integer"; + *(SYMBOLS + SYM_VOID) = (int) "void"; + *(SYMBOLS + SYM_INT) = (int) "int"; + *(SYMBOLS + SYM_SEMICOLON) = (int) ";"; + *(SYMBOLS + SYM_IF) = (int) "if"; + *(SYMBOLS + SYM_ELSE) = (int) "else"; + *(SYMBOLS + SYM_PLUS) = (int) "+"; + *(SYMBOLS + SYM_MINUS) = (int) "-"; + *(SYMBOLS + SYM_ASTERISK) = (int) "*"; + *(SYMBOLS + SYM_DIV) = (int) "/"; + *(SYMBOLS + SYM_EQUALITY) = (int) "=="; + *(SYMBOLS + SYM_ASSIGN) = (int) "="; + *(SYMBOLS + SYM_LPARENTHESIS) = (int) "("; + *(SYMBOLS + SYM_RPARENTHESIS) = (int) ")"; + *(SYMBOLS + SYM_LBRACE) = (int) "{"; + *(SYMBOLS + SYM_RBRACE) = (int) "}"; + *(SYMBOLS + SYM_WHILE) = (int) "while"; + *(SYMBOLS + SYM_RETURN) = (int) "return"; + *(SYMBOLS + SYM_COMMA) = (int) ","; + *(SYMBOLS + SYM_LT) = (int) "<"; + *(SYMBOLS + SYM_LEQ) = (int) "<="; + *(SYMBOLS + SYM_GT) = (int) ">"; + *(SYMBOLS + SYM_GEQ) = (int) ">="; + *(SYMBOLS + SYM_NOTEQ) = (int) "!="; + *(SYMBOLS + SYM_MOD) = (int) "%"; + *(SYMBOLS + SYM_CHARACTER) = (int) "character"; + *(SYMBOLS + SYM_STRING) = (int) "string"; - lineNumber = 1; character = getchar(); - symbol = -1; - - identifier = 0; - integer = 0; - - ivalue = 0; - - mayBeINTMINConstant = 0; + symbol = SYM_EOF; } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void initSymbolTable(); - -void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int class, int type); -int *getSymbolTableEntry(int *ident, int *symbol_table); +void createSymbolTableEntry(int which, int *string, int data, int class, int type, int value); +int* getSymbolTableEntry(int *string, int class, int *symbol_table); -int *getNext(int *entry); -int *getIdentifier(int *entry); +int* getNext(int *entry); +int* getString(int *entry); int getData(int *entry); int getClass(int *entry); int getType(int *entry); +int getValue(int *entry); int getRegister(int *entry); void setNext(int *entry, int *next); -void setIdentifier(int *entry, int *identifier); +void setString(int *entry, int *identifier); void setData(int *entry, int data); void setClass(int *entry, int class); void setType(int *entry, int type); +void setValue(int *entry, int value); void setRegister(int *entry, int reg); // ------------------------ GLOBAL CONSTANTS ----------------------- // classes -int UNKNOWN; // 0 -int CONSTANT; // 1 -int VARIABLE; // 2 -int FUNCTION; // 3 +int VARIABLE = 1; +int FUNCTION = 2; +int STRING = 3; // types -int INT_T; // 1 -int INTSTAR_T; // 2 -int VOID_T; // 3 +int INT_T = 1; +int INTSTAR_T = 2; +int VOID_T = 3; // symbol tables -int GLOBAL_TABLE; -int LOCAL_TABLE; +int GLOBAL_TABLE = 1; +int LOCAL_TABLE = 2; // ------------------------ GLOBAL VARIABLES ----------------------- -// table pointer -int *global_symbol_table; -int *local_symbol_table; - -// ------------------------- INITIALIZATION ------------------------ - -void initSymbolTable() { - // classes - UNKNOWN = 0; - CONSTANT = 1; - VARIABLE = 2; - FUNCTION = 3; - - // types - INT_T = 1; - INTSTAR_T = 2; - VOID_T = 3; - - // symbol tables - GLOBAL_TABLE = 1; - LOCAL_TABLE = 2; - - // table pointer - global_symbol_table = 0; - local_symbol_table = 0; -} +// table pointers +int *global_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; // ----------------------------------------------------------------- // ---------------------------- PARSER ----------------------------- @@ -499,25 +328,31 @@ void initSymbolTable() { void initParser(); int isNotRbraceOrEOF(); -int isVariableOrProcedure(); int isExpression(); -int isPlusOrMinus(); int isStarOrDivOrModulo(); +int isPlusOrMinus(); +int isComparison(); + +int lookForFactor(); +int lookForStatement(); +int lookForType(); -int waitForStatement(); -int waitForVariable(); -int waitForFactor(); +void save_temporaries(); +void restore_temporaries(int numberOfTemporaries); -void save_registers(); -void restore_registers(int numberOfRegisters); +void syntaxErrorSymbol(int expected); +void syntaxErrorUnexpected(); +int* putType(int type); +void typeWarning(int expected, int found); int* getVariable(int *variable); int load_variable(int *variable); void load_integer(); +void load_string(); int help_call_codegen(int *entry, int *procedure); void help_procedure_prologue(int localVariables); -void help_procedure_epilogue(int parameters, int functionStart, int functionType); +void help_procedure_epilogue(int parameters); int gr_call(int *procedure); int gr_factor(); @@ -528,36 +363,33 @@ void gr_while(); void gr_if(); void gr_return(int returnType); void gr_statement(); -int gr_variable(); +int gr_type(); +void gr_variable(int offset); +void gr_initialization(int *name, int offset, int type); void gr_procedure(int *procedure, int returnType); void gr_cstar(); // ------------------------ GLOBAL CONSTANTS ----------------------- -int maxCodeLength; +int maxBinaryLength; // ------------------------ GLOBAL VARIABLES ----------------------- -int allocatedRegisters; // number of allocated registers -int allocatedGlobalVariables; // number of global variables +int allocatedTemporaries = 0; // number of allocated temporaries -int codeLength; -int returnBranches; -int *currentFuncName; // holds the name of currently parsed function +int allocatedMemory = 0; // number of bytes for global variables and strings + +int mainJumpAddress = 0; // address of main function +int returnBranches = 0; // fixup chain for return statements + +int *currentProcedureName = (int*) 0; // name of currently parsed procedure // ------------------------- INITIALIZATION ------------------------ void initParser() { - // set maximum code length for emitting code - maxCodeLength = 32000; - - allocatedRegisters = 0; - allocatedGlobalVariables = 0; - - codeLength = 0; - returnBranches = 0; - currentFuncName = 0; + // set maximum code length in bytes for emitting code + maxBinaryLength = twoToThePowerOf(17); } // ----------------------------------------------------------------- @@ -577,36 +409,84 @@ void emitMainEntry(); // ---------------------------- REGISTER --------------------------- // ----------------------------------------------------------------- +void initRegister(); + +void printRegister(int reg); + // ------------------------ GLOBAL CONSTANTS ----------------------- -int REG_ZR; -int REG_V0; -int REG_A0; -int REG_A1; -int REG_A2; -int REG_A3; -int REG_RR; -int REG_K1; -int REG_GP; -int REG_SP; -int REG_FP; -int REG_LINK; +int REG_ZR = 0; +int REG_AT = 1; +int REG_V0 = 2; +int REG_V1 = 3; +int REG_A0 = 4; +int REG_A1 = 5; +int REG_A2 = 6; +int REG_A3 = 7; +int REG_T0 = 8; +int REG_T1 = 9; +int REG_T2 = 10; +int REG_T3 = 11; +int REG_T4 = 12; +int REG_T5 = 13; +int REG_T6 = 14; +int REG_T7 = 15; +int REG_S0 = 16; +int REG_S1 = 17; +int REG_S2 = 18; +int REG_S3 = 19; +int REG_S4 = 20; +int REG_S5 = 21; +int REG_S6 = 22; +int REG_S7 = 23; +int REG_T8 = 24; +int REG_T9 = 25; +int REG_K0 = 26; +int REG_K1 = 27; +int REG_GP = 28; +int REG_SP = 29; +int REG_FP = 30; +int REG_RA = 31; + +int *REGISTERS; // array of strings representing registers // ------------------------- INITIALIZATION ------------------------ void initRegister() { - REG_ZR = 0; - REG_V0 = 2; - REG_A0 = 4; - REG_A1 = 5; - REG_A2 = 6; - REG_A3 = 7; - REG_RR = 26; - REG_K1 = 27; - REG_GP = 28; - REG_SP = 29; - REG_FP = 30; - REG_LINK = 31; + REGISTERS = malloc(32*4); + + *(REGISTERS + REG_ZR) = (int) "$zero"; + *(REGISTERS + REG_AT) = (int) "$at"; + *(REGISTERS + REG_V0) = (int) "$v0"; + *(REGISTERS + REG_V1) = (int) "$v1"; + *(REGISTERS + REG_A0) = (int) "$a0"; + *(REGISTERS + REG_A1) = (int) "$a1"; + *(REGISTERS + REG_A2) = (int) "$a2"; + *(REGISTERS + REG_A3) = (int) "$a3"; + *(REGISTERS + REG_T0) = (int) "$t0"; + *(REGISTERS + REG_T1) = (int) "$t1"; + *(REGISTERS + REG_T2) = (int) "$t2"; + *(REGISTERS + REG_T3) = (int) "$t3"; + *(REGISTERS + REG_T4) = (int) "$t4"; + *(REGISTERS + REG_T5) = (int) "$t5"; + *(REGISTERS + REG_T6) = (int) "$t6"; + *(REGISTERS + REG_T7) = (int) "$t7"; + *(REGISTERS + REG_S0) = (int) "$s0"; + *(REGISTERS + REG_S1) = (int) "$s1"; + *(REGISTERS + REG_S2) = (int) "$s2"; + *(REGISTERS + REG_S3) = (int) "$s3"; + *(REGISTERS + REG_S4) = (int) "$s4"; + *(REGISTERS + REG_S5) = (int) "$s5"; + *(REGISTERS + REG_S6) = (int) "$s6"; + *(REGISTERS + REG_S7) = (int) "$s7"; + *(REGISTERS + REG_T8) = (int) "$t8"; + *(REGISTERS + REG_T9) = (int) "$t9"; + *(REGISTERS + REG_K0) = (int) "$k0"; + *(REGISTERS + REG_K1) = (int) "$k1"; + *(REGISTERS + REG_GP) = (int) "$gp"; + *(REGISTERS + REG_SP) = (int) "$sp"; + *(REGISTERS + REG_FP) = (int) "$fp"; + *(REGISTERS + REG_RA) = (int) "$ra"; } // ----------------------------------------------------------------- @@ -632,6 +512,9 @@ int signExtend(int immediate); void initDecoder(); +void printOpcode(int opcode); +void printFunction(int function); + void decode(); void decodeRFormat(); void decodeIFormat(); @@ -639,77 +522,98 @@ void decodeJFormat(); // ------------------------ GLOBAL CONSTANTS ----------------------- -int OP_SPECIAL; -int FCT_SYSCALL; -int FCT_MFHI; -int FCT_MFLO; -int FCT_MULTU; -int FCT_DIVU; -int OP_ADDIU; -int FCT_ADDU; -int FCT_SUBU; -int OP_LW; -int OP_SW; -int OP_BEQ; -int OP_BNE; -int FCT_SLT; -int FCT_NOP; -int FCT_JR; -int OP_JAL; -int OP_J; -int FCT_TEQ; +int OP_SPECIAL = 0; +int OP_J = 2; +int OP_JAL = 3; +int OP_BEQ = 4; +int OP_BNE = 5; +int OP_ADDIU = 9; +int OP_LW = 35; +int OP_SW = 43; + +int *OPCODES; // array of strings representing MIPS opcodes + +int FCT_NOP = 0; +int FCT_JR = 8; +int FCT_SYSCALL = 12; +int FCT_MFHI = 16; +int FCT_MFLO = 18; +int FCT_MULTU = 25; +int FCT_DIVU = 27; +int FCT_ADDU = 33; +int FCT_SUBU = 35; +int FCT_SLT = 42; +int FCT_TEQ = 52; + +int *FUNCTIONS; // array of strings representing MIPS functions // ------------------------ GLOBAL VARIABLES ----------------------- -int opcode; -int rs; -int rt; -int rd; -int immediate; -int function; -int instr_index; +int opcode = 0; +int rs = 0; +int rt = 0; +int rd = 0; +int immediate = 0; +int function = 0; +int instr_index = 0; // ------------------------- INITIALIZATION ------------------------ void initDecoder() { - OP_SPECIAL = 0; - FCT_NOP = 0; - OP_JAL = 3; - OP_J = 2; - OP_BEQ = 4; - OP_BNE = 5; - OP_ADDIU = 9; - FCT_JR = 8; - FCT_SYSCALL = 12; - FCT_MFHI = 16; - FCT_MFLO = 18; - FCT_MULTU = 25; - FCT_DIVU = 27; - FCT_ADDU = 33; - FCT_SUBU = 35; - OP_LW = 35; - FCT_SLT = 42; - OP_SW = 43; - FCT_TEQ = 52; - - opcode = 0; - rs = 0; - rt = 0; - rd = 0; - immediate = 0; - function = 0; - instr_index = 0; + OPCODES = malloc(44*4); + + *(OPCODES + OP_SPECIAL) = (int) "nop"; + *(OPCODES + OP_J) = (int) "j"; + *(OPCODES + OP_JAL) = (int) "jal"; + *(OPCODES + OP_BEQ) = (int) "beq"; + *(OPCODES + OP_BNE) = (int) "bne"; + *(OPCODES + OP_ADDIU) = (int) "addiu"; + *(OPCODES + OP_LW) = (int) "lw"; + *(OPCODES + OP_SW) = (int) "sw"; + + FUNCTIONS = malloc(53*4); + + *(FUNCTIONS + FCT_NOP) = (int) "nop"; + *(FUNCTIONS + FCT_JR) = (int) "jr"; + *(FUNCTIONS + FCT_SYSCALL) = (int) "syscall"; + *(FUNCTIONS + FCT_MFHI) = (int) "mfhi"; + *(FUNCTIONS + FCT_MFLO) = (int) "mflo"; + *(FUNCTIONS + FCT_MULTU) = (int) "multu"; + *(FUNCTIONS + FCT_DIVU) = (int) "divu"; + *(FUNCTIONS + FCT_ADDU) = (int) "addu"; + *(FUNCTIONS + FCT_SUBU) = (int) "subu"; + *(FUNCTIONS + FCT_SLT) = (int) "slt"; + *(FUNCTIONS + FCT_TEQ) = (int) "teq"; } // ----------------------------------------------------------------- // ---------------------------- MEMORY ----------------------------- // ----------------------------------------------------------------- -void allocateMachineMemory(int size); +void initMemory(int size, int* name); + +int tlb(int vaddr); + +int loadMemory(int vaddr); +void storeMemory(int vaddr, int data); // ------------------------ GLOBAL VARIABLES ----------------------- -int *memory; // machine memory +int *memory; +int memorySize; + +int *binaryName; +int binaryLength; + +// ------------------------- INITIALIZATION ------------------------ + +void initMemory(int size, int *name) { + memory = malloc(size); + memorySize = size; + + binaryName = name; + binaryLength = 0; +} // ----------------------------------------------------------------- // ---------------------------- BINARY ----------------------------- @@ -724,15 +628,15 @@ void fixup_relative(int fromAddress); void fixup_absolute(int fromAddress, int toAddress); void fixlink_absolute(int fromAddress, int toAddress); +int copyStringToMemory(int *s, int a); + void emitBinary(); -int loadBinary(int *filename); +void loadBinary(); // ----------------------------------------------------------------- // --------------------------- SYSCALLS ---------------------------- // ----------------------------------------------------------------- -void initSyscalls(); - void emitExit(); void syscall_exit(); @@ -753,25 +657,18 @@ void syscall_getchar(); void emitPutchar(); -// ------------------------ GLOBAL CONSTANTS ----------------------- - -int SYSCALL_EXIT; -int SYSCALL_READ; -int SYSCALL_WRITE; -int SYSCALL_OPEN; -int SYSCALL_MALLOC; -int SYSCALL_GETCHAR; +void emitYield(); +void syscall_yield(); -// ------------------------- INITIALIZATION ------------------------ +// ------------------------ GLOBAL CONSTANTS ----------------------- -void initSyscalls() { - SYSCALL_EXIT = 4001; - SYSCALL_READ = 4003; - SYSCALL_WRITE = 4004; - SYSCALL_OPEN = 4005; - SYSCALL_MALLOC = 5001; - SYSCALL_GETCHAR = 5002; -} +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; +int SYSCALL_MALLOC = 5001; +int SYSCALL_GETCHAR = 5002; +int SYSCALL_YIELD = 5003; // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -809,9 +706,9 @@ void op_teq(); void initInterpreter(); -void exception_handler(int enumber); +void printException(int enumber); -int addressTranslation(int vaddr); +void exception_handler(int enumber); void pre_debug(); void post_debug(); @@ -820,47 +717,50 @@ void fetch(); void execute(); void run(); -void debug_boot(int memorySize); -int* parse_args(int argc, int *argv, int *cstar_argv); +void parse_args(int argc, int *argv); + void up_push(int value); int up_malloc(int size); -int up_copyCString(int *s); void up_copyArguments(int argc, int *argv); -int main_emulator(int argc, int *argv, int *cstar_argv); +int main_emulator(int argc, int *argv); // ------------------------ GLOBAL CONSTANTS ----------------------- -int *register_strings; // static strings for register names -int *op_strings; // static strings for debug_disassemble -int *fct_strings; +int debug_load = 0; -int debug_registers; -int debug_syscalls; -int debug_load; -int debug_disassemble; +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; +int debug_getchar = 0; -int EXCEPTION_SIGNAL; -int EXCEPTION_ADDRESSERROR; -int EXCEPTION_UNKNOWNINSTRUCTION; -int EXCEPTION_HEAPOVERFLOW; -int EXCEPTION_UNKNOWNSYSCALL; -int EXCEPTION_UNKNOWNFUNCTION; +int debug_registers = 0; +int debug_disassemble = 0; + +int EXCEPTION_SIGNAL = 1; +int EXCEPTION_ADDRESSERROR = 2; +int EXCEPTION_UNKNOWNINSTRUCTION = 3; +int EXCEPTION_HEAPOVERFLOW = 4; +int EXCEPTION_UNKNOWNSYSCALL = 5; +int EXCEPTION_UNKNOWNFUNCTION = 6; + +int *EXCEPTIONS; // array of strings representing exceptions // ------------------------ GLOBAL VARIABLES ----------------------- int *registers; // general purpose registers -int pc; // program counter -int ir; // instruction record +int pc = 0; // program counter +int ir = 0; // instruction record -int reg_hi; // hi register for multiplication/division -int reg_lo; // lo register for multiplication/division +int reg_hi = 0; // hi register for multiplication/division +int reg_lo = 0; // lo register for multiplication/division // -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- -void push(int *mem, int *reg, int *reg_hi, int *reg_lo, int pc, int *head); +void push(int *mem, int *reg, int *reg_hi, int *reg_lo, int pc,int pId,int *segment, int *head); void setPrcosessNext(int *process, int *next); void setProcessPc(int * process, int pc); @@ -868,6 +768,8 @@ void setProcessMemory(int *process, int *memory); void setProcessRegisters(int *process, int *registers); void setProcessRegHi(int *process, int reg_hi); void setProcessRegLo(int *process, int reg_lo); +void setProcessId (int *process, int pId); +void setProcessSegPointer(int *process, int *segment); int* getProcessNext(int *process); int getProcessPc(int *process); @@ -875,106 +777,57 @@ int* getProcessMemory(int *process); int* getProcessRegisters(int *process); int getProcessRegHi(int *process); int getProcessRegLo(int *process); +int getProcessId(int *process); +int* getProcessSegPointer(int *process); + void createProcessList(int numberoOfProcesses); -void createProcess(int *head); +void createProcess(int *head, int pId); void memCopy(int *oldMemory, int *newMemory, int length); +int * insertSegment(int pId, int start, int size, int *head); + +void setSegmentId(int *segment, int pId); +void setSegmentNext(int *segment, int *next); +void setSegmentStart(int *segment, int start); +void setSegmentSize(int *segment, int size); + +int* getSegmentNext(int *segment); +int getSegmentId(int *segment); +int getSegmentStart(int *segment); +int getSegmentSize(int *segment); int* pop(int *head); void scheduler(); // ------------------ADDITIONAL GLOBAL VARIABLES A1 -------------- -int* readyqueue; +int *readyqueue = 0; int memSize; -int numberofInstructions; +int numberofInstructions = 0; +// ------------------ADDITIONAL GLOBAL VARIABLES A2--------------- +int *process = 0; +int *segmentTable = 0; +int segPointer = 0; +int segSize = 2 * 1024 * 1024; +int segmentStart = 0; //this variable is initalized when scheduler is called + // so that it doesn't have to be computed every time + // tlb is called // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { - register_strings = (int*)malloc(4*32); - op_strings = (int*)malloc(4*64); - fct_strings = (int*)malloc(4*64); - - *(register_strings + 0) = (int)createString('z','e','r','o',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 1) = (int)createString('a','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 2) = (int)createString('v','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 3) = (int)createString('v','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 4) = (int)createString('a','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 5) = (int)createString('a','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 6) = (int)createString('a','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 7) = (int)createString('a','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 8) = (int)createString('t','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 9) = (int)createString('t','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 10) = (int)createString('t','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 11) = (int)createString('t','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 12) = (int)createString('t','4',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 13) = (int)createString('t','5',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 14) = (int)createString('t','6',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 15) = (int)createString('t','7',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 16) = (int)createString('s','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 17) = (int)createString('s','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 18) = (int)createString('s','2',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 19) = (int)createString('s','3',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 20) = (int)createString('s','4',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 21) = (int)createString('s','5',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 22) = (int)createString('s','6',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 23) = (int)createString('s','7',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 24) = (int)createString('t','8',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 25) = (int)createString('t','9',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 26) = (int)createString('k','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 27) = (int)createString('k','1',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 28) = (int)createString('g','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 29) = (int)createString('s','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 30) = (int)createString('f','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(register_strings + 31) = (int)createString('r','a',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - *(fct_strings + 0) = (int)createString('n','o','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 8) = (int)createString('j','r',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 12) = (int)createString('s','y','s','c','a','l','l',0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 16) = (int)createString('m','f','h','i',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 18) = (int)createString('m','f','l','o',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 25) = (int)createString('m','u','l','t','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 27) = (int)createString('d','i','v','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 33) = (int)createString('a','d','d','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 35) = (int)createString('s','u','b','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 42) = (int)createString('s','l','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(fct_strings + 52) = (int)createString('t','e','q',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - *(op_strings + 0) = (int)createString('n','o','p',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 3) = (int)createString('j','a','l',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 2) = (int)createString('j',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 4) = (int)createString('b','e','q',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 5) = (int)createString('b','n','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 9) = (int)createString('a','d','d','i','u',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 15) = (int)createString('l','u','i',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 35) = (int)createString('l','w',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - *(op_strings + 43) = (int)createString('s','w',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - debug_registers = 0; - debug_syscalls = 0; - debug_load = 0; - debug_disassemble = 0; - - EXCEPTION_SIGNAL = 1; - EXCEPTION_ADDRESSERROR = 2; - EXCEPTION_UNKNOWNINSTRUCTION = 3; - EXCEPTION_HEAPOVERFLOW = 4; - EXCEPTION_UNKNOWNSYSCALL = 5; - EXCEPTION_UNKNOWNFUNCTION = 6; - - registers = (int*)malloc(32*4); - - pc = 0; - ir = 0; - - reg_hi = 0; - reg_lo = 0; - - readyqueue = 0;//ADDED A1 - numberofInstructions = 0; //ADDED A1 + EXCEPTIONS = malloc(7*4); + + *(EXCEPTIONS + EXCEPTION_SIGNAL) = (int) "signal"; + *(EXCEPTIONS + EXCEPTION_ADDRESSERROR) = (int) "address error"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNINSTRUCTION) = (int) "unknown instruction"; + *(EXCEPTIONS + EXCEPTION_HEAPOVERFLOW) = (int) "heap overflow"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNSYSCALL) = (int) "unknown syscall"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNFUNCTION) = (int) "unknown function"; + + registers = malloc(32*4); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -1014,56 +867,85 @@ int rightShift(int n, int b) { (INT_MAX / twoToThePowerOf(b) + 1); } +int getCharacter(int *s, int i) { + // assert: i >= 0 + int a; + + a = i / 4; + + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); +} + +int* putCharacter(int *s, int i, int c) { + // assert: i >= 0, all characters are 7-bit + int a; + + a = i / 4; + + *(s + a) = (*(s + a) - leftShift(getCharacter(s, i), (i % 4) * 8)) + leftShift(c, (i % 4) * 8); + + return s; +} + int stringLength(int *s) { int i; i = 0; - while (*(s+i) != 0) + while (getCharacter(s, i) != 0) i = i + 1; return i; } -void reverseString(int *s) { - int tmp; +void stringReverse(int *s) { int i; int j; + int tmp; i = 0; j = stringLength(s) - 1; while (i < j) { - tmp = *(s+i); - *(s+i) = *(s+j); - *(s+j) = tmp; + tmp = getCharacter(s, i); + + putCharacter(s, i, getCharacter(s, j)); + putCharacter(s, j, tmp); + i = i + 1; j = j - 1; } } -int stringCompare(int* s, int* t) { +int stringCompare(int *s, int *t) { + int i; + + i = 0; + while (1) - if (*s == 0) - if (*t == 0) + if (getCharacter(s, i) == 0) + if (getCharacter(t, i) == 0) return 1; else return 0; - else if (*s == *t) { - s = s + 1; - t = t + 1; - } else + else if (getCharacter(s, i) == getCharacter(t, i)) + i = i + 1; + else return 0; } -int atoi(int* s) { +int atoi(int *s) { + int i; int n; + i = 0; + n = 0; - while (*s != 0) { - n = n * 10 + *s - '0'; - s = s + 1; + while (getCharacter(s, i) != 0) { + n = n * 10 + getCharacter(s, i) - '0'; + + i = i + 1; } return n; @@ -1080,7 +962,7 @@ int* itoa(int n, int *s, int b, int a) { sign = 0; if (n == 0) { - *s = '0'; + putCharacter(s, 0, '0'); i = 1; } else if (n < 0) { @@ -1088,7 +970,8 @@ int* itoa(int n, int *s, int b, int a) { if (b == 10) { if (n == INT_MIN) { - *s = '8'; // rightmost decimal digit of 32-bit INT_MIN + // rightmost decimal digit of 32-bit INT_MIN + putCharacter(s, 0, '8'); n = -(n / 10); i = i + 1; @@ -1096,7 +979,8 @@ int* itoa(int n, int *s, int b, int a) { n = -n; } else { if (n == INT_MIN) { - *s = '0'; // rightmost non-decimal digit of INT_MIN + // rightmost non-decimal digit of INT_MIN + putCharacter(s, 0, '0'); n = (rightShift(INT_MIN, 1) / b) * 2; i = i + 1; @@ -1106,12 +990,10 @@ int* itoa(int n, int *s, int b, int a) { } while (n != 0) { - *(s+i) = n % b; - - if (*(s+i) > 9) - *(s+i) = *(s+i) - 10 + 'A'; + if (n % b > 9) + putCharacter(s, i, n % b - 10 + 'A'); else - *(s+i) = *(s+i) + '0'; + putCharacter(s, i, n % b + '0'); n = n / b; i = i + 1; @@ -1126,70 +1008,69 @@ int* itoa(int n, int *s, int b, int a) { if (b != 10) { while (i < a) { - *(s+i) = '0'; // align with zeros + putCharacter(s, i, '0'); // align with zeros i = i + 1; } + + if (b == 16) { + putCharacter(s, i, 'x'); + putCharacter(s, i + 1, '0'); + + i = i + 2; + } } else if (sign) { - *(s+i) = '-'; + putCharacter(s, i, '-'); i = i + 1; } - *(s+i) = 0; // null terminated string + putCharacter(s, i, 0); // null terminated string - reverseString(s); + stringReverse(s); return s; } void print(int *s) { - while (*s != 0) { - putchar(*s); - s = s + 1; - } -} + int i; -void assignString(int *s, int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { + i = 0; - *(s+0) = c0; *(s+1) = c1; *(s+2) = c2; *(s+3) = c3; *(s+4) = c4; - *(s+5) = c5; *(s+6) = c6; *(s+7) = c7; *(s+8) = c8; *(s+9) = c9; - *(s+10) = c10; *(s+11) = c11; *(s+12) = c12; *(s+13) = c13; *(s+14) = c14; - *(s+15) = c15; *(s+16) = c16; *(s+17) = c17; *(s+18) = c18; *(s+19) = c19; - *(s+20) = 0; -} + while (getCharacter(s, i) != 0) { + putchar(getCharacter(s, i)); -int* createString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { - int* s; + i = i + 1; + } +} - s = (int*)malloc(21*4); - assignString(s, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, - c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); - return s; +void println() { + putchar(CHAR_LF); } -void printString(int c0, int c1, int c2, int c3, int c4, - int c5, int c6, int c7, int c8, int c9, - int c10, int c11, int c12, int c13, int c14, - int c15, int c16, int c17, int c18, int c19) { +void printCharacter(int character) { + putchar(CHAR_SINGLEQUOTE); - assignString(string_buffer, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, - c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + if (character == CHAR_EOF) + print((int*) "end of file"); + else if (character == CHAR_TAB) + print((int*) "tabulator"); + else if (character == CHAR_LF) + print((int*) "line feed"); + else if (character == CHAR_CR) + print((int*) "carriage return"); + else + putchar(character); - print(string_buffer); + putchar(CHAR_SINGLEQUOTE); } -void memset(int *a, int size, int v) { - while (size > 0) { - size = size - 1; - *(a+size) = v; - } +void printString(int *s) { + putchar(CHAR_DOUBLEQUOTE); + + print(s); + + putchar(CHAR_DOUBLEQUOTE); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -1202,6 +1083,58 @@ void memset(int *a, int size, int v) { // ---------------------------- SCANNER ---------------------------- // ----------------------------------------------------------------- +void printSymbol(int symbol) { + putchar(CHAR_DOUBLEQUOTE); + + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); + + putchar(CHAR_DOUBLEQUOTE); +} + +void printLineNumber(int* message) { + print((int*) "cstarc: "); + print(message); + print((int*) " in line "); + print(itoa(lineNumber, string_buffer, 10, 0)); + print((int*) ": "); +} + +void syntaxErrorMessage(int *message) { + printLineNumber((int*) "error"); + + print(message); + + println(); +} + +void syntaxErrorCharacter(int expected) { + printLineNumber((int*) "error"); + + printCharacter(expected); + print((int*) " expected but "); + + printCharacter(character); + print((int*) " found"); + + println(); +} + +int isCharacterWhitespace() { + if (character == CHAR_SPACE) + return 1; + else if (character == CHAR_TAB) + return 1; + else if (character == CHAR_LF) + return 1; + else if (character == CHAR_CR) + return 1; + else + return 0; +} + int findNextCharacter() { int inComment; @@ -1215,7 +1148,7 @@ int findNextCharacter() { inComment = 0; else if (character == CHAR_CR) inComment = 0; - else if (character == SYM_EOF) + else if (character == CHAR_EOF) return character; } else if (isCharacterWhitespace()) { @@ -1226,13 +1159,13 @@ int findNextCharacter() { character = getchar(); - } else if (character == '#') { + } else if (character == CHAR_HASH) { character = getchar(); inComment = 1; - } else if (character == '/') { + } else if (character == CHAR_SLASH) { character = getchar(); - if (character == '/') + if (character == CHAR_SLASH) inComment = 1; else { symbol = SYM_DIV; @@ -1244,26 +1177,17 @@ int findNextCharacter() { } } -int isCharacterWhitespace() { - if (character == ' ') - return 1; - else if (character == CHAR_TAB) - return 1; - else if (character == CHAR_LF) - return 1; - else if (character == CHAR_CR) - return 1; - else - return 0; -} - -int isCharacterLetterOrDigitOrUnderscore() { - if (isCharacterLetter()) - return 1; - else if(isCharacterDigit()) - return 1; - else if(character == '_') - return 1; +int isCharacterLetter() { + if (character >= 'a') + if (character <= 'z') + return 1; + else + return 0; + else if (character >= 'A') + if (character <= 'Z') + return 1; + else + return 0; else return 0; } @@ -1278,23 +1202,28 @@ int isCharacterDigit() { return 0; } -int isCharacterLetter() { - if (character >= 'a') - if (character <= 'z') - return 1; - else - return 0; - else if (character >= 'A') - if (character <= 'Z') - return 1; - else - return 0; +int isCharacterLetterOrDigitOrUnderscore() { + if (isCharacterLetter()) + return 1; + else if (isCharacterDigit()) + return 1; + else if (character == CHAR_UNDERSCORE) + return 1; else return 0; } -int identifierStringMatch(int stringIndex) { - return stringCompare(identifier, (int*)(*(stringArray + stringIndex))); +int isNotDoubleQuoteOrEOF() { + if (character == CHAR_DOUBLEQUOTE) + return 0; + else if (character == CHAR_EOF) + return 0; + else + return 1; +} + +int identifierStringMatch(int keyword) { + return stringCompare(identifier, (int*) *(SYMBOLS + keyword)); } int identifierOrKeyword() { @@ -1319,216 +1248,243 @@ int getSymbol() { symbol = SYM_EOF; - if (findNextCharacter() == SYM_EOF) + if (findNextCharacter() == CHAR_EOF) return SYM_EOF; else if (symbol == SYM_DIV) // check here because / was recognized instead of // return SYM_DIV; if (isCharacterLetter()) { - identifier = (int*)malloc((maxIdentifierLength+1) * 4); + identifier = malloc(maxIdentifierLength + 1); + i = 0; while (isCharacterLetterOrDigitOrUnderscore()) { - if (i+1 > maxIdentifierLength) { - syntaxError(ERR_MAXIDENTIFIERLENGTH); // identifier too long + if (i >= maxIdentifierLength) { + syntaxErrorMessage((int*) "identifier too long"); exit(-1); } - *(identifier+i) = character; + + putCharacter(identifier, i, character); + i = i + 1; + character = getchar(); } - *(identifier+i) = 0; // null terminated string + putCharacter(identifier, i, 0); // null terminated string + symbol = identifierOrKeyword(); } else if (isCharacterDigit()) { - integer = (int*)malloc((maxIntegerLength+1) * 4); + integer = malloc(maxIntegerLength + 1); + i = 0; while (isCharacterDigit()) { - if (i+1 > maxIntegerLength) { - syntaxError(ERR_WRAPAROUND); // integer too long + if (i >= maxIntegerLength) { + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } - *(integer+i) = character; + + putCharacter(integer, i, character); + i = i + 1; + character = getchar(); } - *(integer+i) = 0; // null terminated string - ivalue = atoi(integer); + putCharacter(integer, i, 0); // null terminated string - if (ivalue < 0) { - if (ivalue == INT_MIN) { - if (mayBeINTMINConstant == 0) { - syntaxError(ERR_WRAPAROUND); + constant = atoi(integer); + + if (constant < 0) { + if (constant == INT_MIN) { + if (mayBeINTMINConstant) + isINTMINConstant = 1; + else { + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } } else { - syntaxError(ERR_WRAPAROUND); + syntaxErrorMessage((int*) "integer out of bound"); exit(-1); } } symbol = SYM_INTEGER; - } else if (character == ';') { + } else if (character == CHAR_SINGLEQUOTE) { character = getchar(); - symbol = SYM_SEMICOLON; - } else if (character == '+') { - character = getchar(); - symbol = SYM_PLUS; + constant = 0; - } else if (character == '-') { - character = getchar(); - symbol = SYM_MINUS; + if (character == CHAR_EOF) { + syntaxErrorMessage((int*) "reached end of file looking for a character constant"); - } else if (character == '*') { - character = getchar(); - symbol = SYM_ASTERISK; + exit(-1); + } else + constant = character; - } else if (character == '=') { character = getchar(); - if (character == '=') { + + if (character == CHAR_SINGLEQUOTE) character = getchar(); - symbol = SYM_EQUAL; + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + exit(-1); } else - symbol = SYM_ASSIGN; + syntaxErrorCharacter(CHAR_SINGLEQUOTE); - } else if (character == '(') { - character = getchar(); - symbol = SYM_LPARENTHESIS; + symbol = SYM_CHARACTER; - } else if (character == ')') { + } else if (character == CHAR_DOUBLEQUOTE) { character = getchar(); - symbol = SYM_RPARENTHESIS; - } else if (character == '{') { - character = getchar(); - symbol = SYM_LBRACE; + string = malloc(maxStringLength + 1); - } else if (character == '}') { - character = getchar(); - symbol = SYM_RBRACE; + i = 0; - } else if (character == ',') { - character = getchar(); - symbol = SYM_COMMA; + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } - } else if (character == '<') { - character = getchar(); - if (character == '=') { + putCharacter(string, i, character); + + i = i + 1; + character = getchar(); - symbol = SYM_LEQ; - } else - symbol = SYM_LT; + } - } else if (character == '>') { - character = getchar(); - if (character == '=') { + if (character == CHAR_DOUBLEQUOTE) character = getchar(); - symbol = SYM_GEQ; - } else - symbol = SYM_GT; + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); + + exit(-1); + } - } else if (character == '!') { + putCharacter(string, i, 0); // null terminated string + + symbol = SYM_STRING; + + } else if (character == CHAR_SEMICOLON) { character = getchar(); - if (character == '=') { - character = getchar(); - symbol = SYM_NOTEQ; - } else - syntaxError(ERR_UNKNOWN); + symbol = SYM_SEMICOLON; - } else if (character == '%') { + } else if (character == CHAR_PLUS) { character = getchar(); - symbol = SYM_MOD; + symbol = SYM_PLUS; - } else if (character == 39) { // ' + } else if (character == CHAR_DASH) { character = getchar(); - ivalue = character; // any ascii character + symbol = SYM_MINUS; + + } else if (character == CHAR_ASTERISK) { character = getchar(); - if (character == 39) { // ' + symbol = SYM_ASTERISK; + + } else if (character == CHAR_EQUAL) { + character = getchar(); + if (character == CHAR_EQUAL) { character = getchar(); - symbol = SYM_CHARACTER; + symbol = SYM_EQUALITY; } else - syntaxError(ERR_UNKNOWN); - } else { - syntaxError(ERR_UNKNOWN); - exit(-1); // unknown character - } - - return symbol; -} - -void syntaxWarn(int errCode) { - int *numberBuffer; - - numberBuffer = (int*)malloc(4*10); + symbol = SYM_ASSIGN; - print(warning); + } else if (character == CHAR_LPARENTHESIS) { + character = getchar(); + symbol = SYM_LPARENTHESIS; - print((int*)(*(stringArray+errCode))); + } else if (character == CHAR_RPARENTHESIS) { + character = getchar(); + symbol = SYM_RPARENTHESIS; - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); + } else if (character == CHAR_LBRACE) { + character = getchar(); + symbol = SYM_LBRACE; - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + } else if (character == CHAR_RBRACE) { + character = getchar(); + symbol = SYM_RBRACE; - print(errNewline); -} + } else if (character == CHAR_COMMA) { + character = getchar(); + symbol = SYM_COMMA; -void syntaxError(int errCode) { - int *numberBuffer; + } else if (character == CHAR_LT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_LEQ; + } else + symbol = SYM_LT; - numberBuffer = (int*)malloc(4*10); + } else if (character == CHAR_GT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_GEQ; + } else + symbol = SYM_GT; - print(error); + } else if (character == CHAR_EXCLAMATION) { + character = getchar(); + if (character == CHAR_EQUAL) + character = getchar(); + else + syntaxErrorCharacter(CHAR_EQUAL); - print((int*)(*(stringArray+errCode))); + symbol = SYM_NOTEQ; - print(errLine); - print(itoa(lineNumber, numberBuffer, 10, 0)); + } else if (character == CHAR_PERCENTAGE) { + character = getchar(); + symbol = SYM_MOD; - print(errSymbol); - print(itoa(symbol, numberBuffer, 10, 0)); + } else { + printLineNumber((int*) "error"); + print((int*) "found unknown character "); + printCharacter(character); + + println(); - print(errNewline); + exit(-1); + } - getSymbol(); + return symbol; } // ----------------------------------------------------------------- // ------------------------- SYMBOL TABLE -------------------------- // ----------------------------------------------------------------- -void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int class, int type) { - int* newEntry; +void createSymbolTableEntry(int whichTable, int *string, int data, int class, int type, int value) { + int *newEntry; - // symbolTable: - // +----+------------+ - // | 0 | ptr to next| - // | 1 | identifier | - // | 2 | data | VARIABLE: offset/FUNCTION: code address - // | 3 | class | - // | 4 | type | - // | 5 | register | - // +----+------------+ + // symbol table entry: + // +----+----------+ + // | 0 | next | pointer to next entry + // | 1 | string | identifier string, string constant + // | 2 | data | VARIABLE: offset, FUNCTION: address, STRING: offset + // | 3 | class | VARIABLE, FUNCTION, STRING + // | 4 | type | INT_T, INTSTAR_T, VOID_T + // | 5 | value | VARIABLE: constant value + // | 6 | register | REG_GP, REG_FP + // +----+----------+ - newEntry = (int*)malloc(6 * 4); + newEntry = malloc(7 * 4); - // store pointer to identifier - // cast only works if size of int and int* is equivalent - setIdentifier(newEntry, ident); + setString(newEntry, string); setData(newEntry, data); setClass(newEntry, class); setType(newEntry, type); + setValue(newEntry, value); // create entry at head of symbol table - // cast only works if size of int and int* is equivalent - if (which_symbol_table == GLOBAL_TABLE) { + if (whichTable == GLOBAL_TABLE) { setRegister(newEntry, REG_GP); setNext(newEntry, global_symbol_table); global_symbol_table = newEntry; @@ -1539,24 +1495,26 @@ void createSymbolTableEntry(int which_symbol_table, int *ident, int data, int cl } } -int* getSymbolTableEntry(int *ident, int *symbol_table) { - while ((int)symbol_table != 0) { - if (stringCompare(ident, getIdentifier(symbol_table))) - return symbol_table; - else - // keep looking - // cast only works if size of int and int* is equivalent - symbol_table = getNext(symbol_table); +int* getSymbolTableEntry(int *string, int class, int *symbol_table) { + while ((int) symbol_table != 0) { + if (stringCompare(string, getString(symbol_table))) + if (class == getClass(symbol_table)) + return symbol_table; + + // keep looking + symbol_table = getNext(symbol_table); } - return 0; + return (int*) 0; } int* getNext(int *entry) { + // cast only works if size of int and int* is equivalent return (int*) *entry; } -int* getIdentifier(int *entry) { +int* getString(int *entry) { + // cast only works if size of int and int* is equivalent return (int*) *(entry + 1); } @@ -1572,15 +1530,21 @@ int getType(int *entry) { return *(entry + 4); } -int getRegister(int *entry) { +int getValue(int *entry) { return *(entry + 5); } +int getRegister(int *entry) { + return *(entry + 6); +} + void setNext(int *entry, int *next) { + // cast only works if size of int and int* is equivalent *entry = (int) next; } -void setIdentifier(int *entry, int *identifier) { +void setString(int *entry, int *identifier) { + // cast only works if size of int and int* is equivalent *(entry + 1) = (int) identifier; } @@ -1596,8 +1560,12 @@ void setType(int *entry, int type) { *(entry + 4) = type; } +void setValue(int *entry, int value) { + *(entry + 5) = value; +} + void setRegister(int *entry, int reg) { - *(entry + 5) = reg; + *(entry + 6) = reg; } // ----------------------------------------------------------------- @@ -1605,23 +1573,14 @@ void setRegister(int *entry, int reg) { // ----------------------------------------------------------------- int isNotRbraceOrEOF() { - if (symbol == SYM_EOF) + if (symbol == SYM_RBRACE) return 0; - else if(symbol == SYM_RBRACE) + else if(symbol == SYM_EOF) return 0; else return 1; } -int isVariableOrProcedure() { - if (symbol == SYM_INT) - return 1; - else if (symbol == SYM_VOID) - return 1; - else - return 0; -} - int isExpression() { if (symbol == SYM_MINUS) return 1; @@ -1633,16 +1592,18 @@ int isExpression() { return 1; else if (symbol == SYM_ASTERISK) return 1; + else if (symbol == SYM_STRING) + return 1; else if (symbol == SYM_CHARACTER) return 1; else return 0; } -int isPlusOrMinus() { - if (symbol == SYM_MINUS) +int isConstant() { + if (symbol == SYM_INTEGER) return 1; - else if (symbol == SYM_PLUS) + else if (symbol == SYM_CHARACTER) return 1; else return 0; @@ -1659,16 +1620,44 @@ int isStarOrDivOrModulo() { return 0; } -int waitForStatement() { - if (symbol == SYM_ASTERISK) +int isPlusOrMinus() { + if (symbol == SYM_MINUS) + return 1; + else if (symbol == SYM_PLUS) + return 1; + else + return 0; +} + +int isComparison() { + if (symbol == SYM_EQUALITY) + return 1; + else if (symbol == SYM_NOTEQ) + return 1; + else if (symbol == SYM_LT) + return 1; + else if (symbol == SYM_GT) + return 1; + else if (symbol == SYM_LEQ) + return 1; + else if (symbol == SYM_GEQ) + return 1; + else + return 0; +} + +int lookForFactor() { + if (symbol == SYM_LPARENTHESIS) + return 0; + else if (symbol == SYM_ASTERISK) return 0; else if (symbol == SYM_IDENTIFIER) return 0; - else if (symbol == SYM_WHILE) + else if (symbol == SYM_INTEGER) return 0; - else if (symbol == SYM_IF) + else if (symbol == SYM_CHARACTER) return 0; - else if (symbol == SYM_RETURN) + else if (symbol == SYM_STRING) return 0; else if (symbol == SYM_EOF) return 0; @@ -1676,8 +1665,16 @@ int waitForStatement() { return 1; } -int waitForVariable() { - if (symbol == SYM_INT) +int lookForStatement() { + if (symbol == SYM_ASTERISK) + return 0; + else if (symbol == SYM_IDENTIFIER) + return 0; + else if (symbol == SYM_WHILE) + return 0; + else if (symbol == SYM_IF) + return 0; + else if (symbol == SYM_RETURN) return 0; else if (symbol == SYM_EOF) return 0; @@ -1685,16 +1682,10 @@ int waitForVariable() { return 1; } -int waitForFactor() { - if (symbol == SYM_LPARENTHESIS) - return 0; - else if (symbol == SYM_ASTERISK) - return 0; - else if (symbol == SYM_IDENTIFIER) - return 0; - else if (symbol == SYM_INTEGER) +int lookForType() { + if (symbol == SYM_INT) return 0; - else if (symbol == SYM_CHARACTER) + else if (symbol == SYM_VOID) return 0; else if (symbol == SYM_EOF) return 0; @@ -1702,35 +1693,142 @@ int waitForFactor() { return 1; } -void save_registers() { - while (allocatedRegisters > 0) { - emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); +void talloc() { + // we use registers REG_T0-REG_T9 and REG_S0-REG_S7 for temporaries + if (allocatedTemporaries < REG_T9 - REG_A3) + allocatedTemporaries = allocatedTemporaries + 1; + else { + syntaxErrorMessage((int*) "out of registers"); + + exit(-1); + } +} + +int currentTemporary() { + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); - allocatedRegisters = allocatedRegisters - 1; + exit(-1); } } -void restore_registers(int numberOfRegisters) { +int previousTemporary() { + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); - while (allocatedRegisters < numberOfRegisters) { - allocatedRegisters = allocatedRegisters + 1; + exit(-1); + } +} + +int nextTemporary() { + if (allocatedTemporaries < REG_T9 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); - emitIFormat(OP_LW, REG_SP, allocatedRegisters, 0); + exit(-1); + } +} + +void tfree(int numberOfTemporaries) { + allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; + + if (allocatedTemporaries < 0) { + syntaxErrorMessage((int*) "illegal register deallocation"); + + exit(-1); + } +} + +void save_temporaries() { + while (allocatedTemporaries > 0) { + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } +} + +void restore_temporaries(int numberOfTemporaries) { + while (allocatedTemporaries < numberOfTemporaries) { + talloc(); + + emitIFormat(OP_LW, REG_SP, currentTemporary(), 0); emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); } } +void syntaxErrorSymbol(int expected) { + printLineNumber((int*) "error"); + + printSymbol(expected); + print((int*) " expected but "); + + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +void syntaxErrorUnexpected() { + printLineNumber((int*) "error"); + + print((int*) "unexpected symbol "); + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +int* putType(int type) { + if (type == INT_T) + return (int*) "int"; + else if (type == INTSTAR_T) + return (int*) "int*"; + else if (type == VOID_T) + return (int*) "void"; + else + return (int*) "unknown"; +} + +void typeWarning(int expected, int found) { + printLineNumber((int*) "warning"); + + print((int*) "type mismatch, "); + + print(putType(expected)); + + print((int*) " expected but "); + + print(putType(found)); + + print((int*) " found"); + + println(); +} + int* getVariable(int *variable) { - int* entry; + int *entry; - entry = getSymbolTableEntry(variable, local_symbol_table); + entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); - if ((int)entry == 0) { - entry = getSymbolTableEntry(variable, global_symbol_table); + if (entry == (int*) 0) { + entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); - if ((int)entry == 0) - syntaxError(ERR_UNDECLARED_VARIABLE); + if (entry == (int*) 0) { + printLineNumber((int*) "error"); + + print(variable); + + print((int*) " undeclared"); + println(); + + exit(-1); + } } return entry; @@ -1741,68 +1839,81 @@ int load_variable(int *variable) { entry = getVariable(variable); - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_LW, getRegister(entry), allocatedRegisters, getData(entry)); + emitIFormat(OP_LW, getRegister(entry), currentTemporary(), getData(entry)); return getType(entry); } void load_integer() { - // assert: ivalue >= 0 or ivalue == INT_MIN + // assert: constant >= 0 or constant == INT_MIN - allocatedRegisters = allocatedRegisters + 1; + talloc(); - if (ivalue >= 0) { - mayBeINTMINConstant = 0; - - if (ivalue < twoToThePowerOf(15)) + if (constant >= 0) { + if (constant < twoToThePowerOf(15)) // ADDIU can only load numbers < 2^15 without sign extension - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, ivalue); - else if (ivalue < twoToThePowerOf(28)) { + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); + else if (constant < twoToThePowerOf(28)) { // load 14 msbs of a 28-bit number first - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, rightShift(ivalue, 14)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 14)); // shift left by 14 bits emitLeftShiftBy(14); // and finally add 14 lsbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 18), 18)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 18), 18)); } else { // load 14 msbs of a 31-bit number first - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, rightShift(ivalue, 17)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 17)); emitLeftShiftBy(14); // then add the next 14 msbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 15), 18)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 15), 18)); emitLeftShiftBy(3); // and finally add the remaining 3 lsbs - emitIFormat(OP_ADDIU, allocatedRegisters, allocatedRegisters, rightShift(leftShift(ivalue, 29), 29)); + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 29), 29)); } } else { // load largest positive 16-bit number with a single bit set: 2^14 - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, twoToThePowerOf(14)); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), twoToThePowerOf(14)); // and then multiply 2^14 by 2^14*2^3 to get to 2^31 == INT_MIN emitLeftShiftBy(14); emitLeftShiftBy(3); } +} - getSymbol(); +void load_string() { + int l; + + l = stringLength(string) + 1; + + allocatedMemory = allocatedMemory + l; + + if (l % 4 != 0) + allocatedMemory = allocatedMemory + 4 - l % 4; + + createSymbolTableEntry(GLOBAL_TABLE, string, -allocatedMemory, STRING, INTSTAR_T, 0); + + talloc(); + + emitIFormat(OP_ADDIU, REG_GP, currentTemporary(), -allocatedMemory); } int help_call_codegen(int *entry, int *procedure) { int type; - type = UNKNOWN; - - if ((int)entry == 0) { + if (entry == (int*) 0) { // CASE 1: function call, no definition, no declaration. - createSymbolTableEntry(GLOBAL_TABLE, procedure, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, procedure, binaryLength, FUNCTION, INT_T, 0); + emitJFormat(OP_JAL, 0); + type = INT_T; //assume default return type 'int' } else { @@ -1810,156 +1921,174 @@ int help_call_codegen(int *entry, int *procedure) { if (getData(entry) == 0) { // CASE 2: function call, no definition, but declared. - setData(entry, codeLength); + setData(entry, binaryLength); + emitJFormat(OP_JAL, 0); - } else if (getOpcode(*(memory + getData(entry))) == OP_JAL) { + } else if (getOpcode(loadMemory(getData(entry))) == OP_JAL) { // CASE 3: function call, no declaration - emitJFormat(OP_JAL, getData(entry)); - setData(entry, codeLength - 2); + emitJFormat(OP_JAL, getData(entry) / 4); + + setData(entry, binaryLength - 8); } else // CASE 4: function defined, use the address - emitJFormat(OP_JAL, getData(entry)); + emitJFormat(OP_JAL, getData(entry) / 4); } return type; } void help_procedure_prologue(int localVariables) { - // save return address + // allocate space for return address emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, REG_LINK, 0); - // save caller's frame + // save return address + emitIFormat(OP_SW, REG_SP, REG_RA, 0); + + // allocate space for caller's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + + // save caller's frame pointer emitIFormat(OP_SW, REG_SP, REG_FP, 0); - // allocate callee's frame + // set callee's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_FP, 0); - // allocate callee's local variables - if (localVariables != 0) { - emitIFormat(OP_ADDIU, REG_SP, REG_SP, localVariables * (-4)); - } + // allocate space for callee's local variables + if (localVariables != 0) + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4 * localVariables); } -void help_procedure_epilogue(int parameters, int functionStart, int functionType) { - // deallocate callee's frame and local variables +void help_procedure_epilogue(int parameters) { + // deallocate space for callee's frame pointer and local variables emitIFormat(OP_ADDIU, REG_FP, REG_SP, 0); - // restore caller's frame + // restore caller's frame pointer emitIFormat(OP_LW, REG_SP, REG_FP, 0); + + // deallocate space for caller's frame pointer emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); - // restore return address and deallocate parameters - emitIFormat(OP_LW, REG_SP, REG_LINK, 0); - emitIFormat(OP_ADDIU, REG_SP, REG_SP, ((parameters+1)*4)); + // restore return address + emitIFormat(OP_LW, REG_SP, REG_RA, 0); + + // deallocate space for return address and parameters + emitIFormat(OP_ADDIU, REG_SP, REG_SP, (parameters + 1) * 4); // return - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } int gr_call(int *procedure) { int *entry; - int numberOfRegisters; + int numberOfTemporaries; int type; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries - entry = getSymbolTableEntry(procedure, global_symbol_table); + entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); - numberOfRegisters = allocatedRegisters; + numberOfTemporaries = allocatedTemporaries; - save_registers(); + save_temporaries(); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 if (isExpression()) { gr_expression(); - // TODO: check if types/number of params is correct. - // PSH first parameter onto stack + // TODO: check if types/number of parameters is correct + // push first parameter onto stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); while (symbol == SYM_COMMA) { getSymbol(); + gr_expression(); - // PSH more parameters onto stack + // push more parameters onto stack emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); - emitIFormat(OP_SW, REG_SP, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); } + if (symbol == SYM_RPARENTHESIS) { getSymbol(); + type = help_call_codegen(entry, procedure); } else { - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); + type = INT_T; } } else if (symbol == SYM_RPARENTHESIS) { getSymbol(); + type = help_call_codegen(entry, procedure); } else { - syntaxWarn(ERR_EXPRESSION); + syntaxErrorSymbol(SYM_RPARENTHESIS); + type = INT_T; } - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 - restore_registers(numberOfRegisters); + restore_temporaries(numberOfTemporaries); - // assert: allocatedRegisters == n + // assert: allocatedTemporaries == n return type; } int gr_factor() { + int hasCast; int cast; int type; + int *variableOrProcedureName; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries + + hasCast = 0; - cast = 0; // turn off cast by default + type = INT_T; - while (waitForFactor()) - syntaxError(ERR_IDENT_OR_CONST_OR_EXP); + while (lookForFactor()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } // optional cast: [ cast ] if (symbol == SYM_LPARENTHESIS) { getSymbol(); - mayBeINTMINConstant = 0; - - // (int) + // cast: "(" "int" [ "*" ] ")" if (symbol == SYM_INT) { - getSymbol(); - - cast = INT_T; - - // (int*) - if (symbol == SYM_ASTERISK) { - getSymbol(); + hasCast = 1; - cast = INTSTAR_T; - } + cast = gr_type(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); - // Not a cast: "(" expression ")" + // not a cast: "(" expression ")" } else { type = gr_expression(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return type; } @@ -1969,15 +2098,13 @@ int gr_factor() { if (symbol == SYM_ASTERISK) { getSymbol(); - mayBeINTMINConstant = 0; - // ["*"] identifier if (symbol == SYM_IDENTIFIER) { type = load_variable(identifier); getSymbol(); - // * "(" simpleExpression ")" + // * "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { getSymbol(); @@ -1986,19 +2113,17 @@ int gr_factor() { if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(ERR_IDENTIFIER_OR_LPARENTHESIS); + syntaxErrorUnexpected(); - // dereference - emitIFormat(OP_LW, allocatedRegisters, allocatedRegisters, 0); + if (type != INTSTAR_T) + typeWarning(INTSTAR_T, type); - if (cast == 0) { - if (type != INTSTAR_T) - syntaxWarn(ERR_ILLEGAL_DEREF); + // dereference + emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); - type = INT_T; - } + type = INT_T; // identifier? } else if (symbol == SYM_IDENTIFIER) { @@ -2006,111 +2131,107 @@ int gr_factor() { getSymbol(); - mayBeINTMINConstant = 0; - if (symbol == SYM_LPARENTHESIS) { getSymbol(); - // function call: identifier "(" ... ")" ... + // function call: identifier "(" ... ")" type = gr_call(variableOrProcedureName); - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_ADDIU, REG_RR, allocatedRegisters, 0); + emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); } else - // else.. it is just an 'identifier' + // variable access: identifier type = load_variable(variableOrProcedureName); // integer? } else if (symbol == SYM_INTEGER) { load_integer(); + + getSymbol(); + type = INT_T; // character? } else if (symbol == SYM_CHARACTER) { - mayBeINTMINConstant = 0; - - allocatedRegisters = allocatedRegisters + 1; + talloc(); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, ivalue); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); getSymbol(); + type = INT_T; + + // string? + } else if (symbol == SYM_STRING) { + load_string(); + + getSymbol(); + + type = INTSTAR_T; // "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { - mayBeINTMINConstant = 0; getSymbol(); + type = gr_expression(); if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); - } + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 - if (cast == 0) - return type; - else + if (hasCast) return cast; + else + return type; } int gr_term() { int ltype; + int operatorSymbol; int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries ltype = gr_factor(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 - // * / or % ? - while (isStarOrDivOrModulo()) { - if (symbol == SYM_ASTERISK) { - // assert: allocatedRegisters == n + 2 - getSymbol(); - rtype = gr_factor(); - - - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_MULTU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFLO); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); - - } else if (symbol == SYM_DIV) { - getSymbol(); - rtype = gr_factor(); + // * / or % ? + while (isStarOrDivOrModulo()) { + operatorSymbol = symbol; + getSymbol(); - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFLO); + rtype = gr_factor(); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + // assert: allocatedTemporaries == n + 2 + + if (ltype != rtype) + typeWarning(ltype, rtype); - } else if (symbol == SYM_MOD) { - getSymbol(); - rtype = gr_factor(); + if (operatorSymbol == SYM_ASTERISK) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); - if (ltype == rtype) { - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, 0, FCT_DIVU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters-1, FCT_MFHI); + } else if (operatorSymbol == SYM_DIV) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + } else if (operatorSymbol == SYM_MOD) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFHI); } + + tfree(1); } - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return ltype; } @@ -2118,192 +2239,164 @@ int gr_term() { int gr_simpleExpression() { int sign; int ltype; - int rtype; int operatorSymbol; + int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries // optional: - if (symbol == SYM_MINUS) { sign = 1; + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } } else sign = 0; ltype = gr_term(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 if (sign == 1) { - if (mayBeINTMINConstant) - // avoids 0-INT_MIN overflow when bootstrapping - // even though 0-INT_MIN == INT_MIN - mayBeINTMINConstant = 0; - else - emitRFormat(OP_SPECIAL, REG_ZR, allocatedRegisters, allocatedRegisters, FCT_SUBU); + if (ltype != INT_T) { + typeWarning(INT_T, ltype); + + ltype = INT_T; + } + + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), currentTemporary(), FCT_SUBU); } // + or -? while (isPlusOrMinus()) { operatorSymbol = symbol; + getSymbol(); rtype = gr_term(); - // assert: allocatedRegisters == n + 2 + // assert: allocatedTemporaries == n + 2 if (operatorSymbol == SYM_PLUS) { - if (ltype == rtype) { // base case, normal arithmetic - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else if (ltype == INTSTAR_T) { - if (rtype == INT_T) { - // pointer arithmetic requires factor of 2^2 - emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else { - syntaxError(ERR_TYPE_MISMATCH); - } - } else if (rtype == INTSTAR_T) { - if (ltype == INT_T) { - // pointer arithmetic requires factor of 2^2 + if (ltype == INTSTAR_T) { + if (rtype == INT_T) + // pointer arithmetic: factor of 2^2 of integer operand emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); - } else - syntaxError(ERR_TYPE_MISMATCH); - } - } else { - if (ltype == rtype) - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); - else - syntaxError(ERR_TYPE_MISMATCH); + } else if (rtype == INTSTAR_T) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_ADDU); + + } else if (operatorSymbol == SYM_MINUS) { + if (ltype != rtype) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); } - allocatedRegisters = allocatedRegisters - 1; + tfree(1); } - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 return ltype; } int gr_expression() { int ltype; + int operatorSymbol; int rtype; - // assert: n = allocatedRegisters + // assert: n = allocatedTemporaries - ltype = gr_simpleExpression(); // type of left element + ltype = gr_simpleExpression(); - // assert: allocatedRegisters == n + 1 + // assert: allocatedTemporaries == n + 1 //optional: ==, !=, <, >, <=, >= simpleExpression - if (symbol == SYM_EQUAL) { + if (isComparison()) { + operatorSymbol = symbol; + getSymbol(); - rtype = gr_simpleExpression(); - // assert: allocatedRegisters == n + 2 + rtype = gr_simpleExpression(); - if (ltype == rtype) { - // subtract, if result = 0 then 1, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); + // assert: allocatedTemporaries == n + 2 - allocatedRegisters = allocatedRegisters - 1; + if (ltype != rtype) + typeWarning(ltype, rtype); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); - } else - syntaxError(ERR_TYPE_MISMATCH); + if (operatorSymbol == SYM_EQUALITY) { + // subtract, if result = 0 then 1, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); - } else if (symbol == SYM_NOTEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_NOTEQ) { // subtract, if result = 0 then 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SUBU); - - allocatedRegisters = allocatedRegisters - 1; - - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); - } else - syntaxError(ERR_TYPE_MISMATCH); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); - } else if (symbol == SYM_LT) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_LT) { // set to 1 if a < b, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SLT); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); - } else if (symbol == SYM_GT) { - getSymbol(); - rtype = gr_simpleExpression(); + tfree(1); - // assert: allocatedRegisters == n + 2 - - if (ltype == rtype) { + } else if (operatorSymbol == SYM_GT) { // set to 1 if b < a, else 0 - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters-1, allocatedRegisters-1, FCT_SLT); - - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_TYPE_MISMATCH); - - } else if (symbol == SYM_LEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); - // assert: allocatedRegisters == n + 2 + tfree(1); - if (ltype == rtype) { + } else if (operatorSymbol == SYM_LEQ) { // if b < a set 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters-1, allocatedRegisters-1, FCT_SLT); + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); - allocatedRegisters = allocatedRegisters - 1; + tfree(1); - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - } else - syntaxError(ERR_TYPE_MISMATCH); - - } else if (symbol == SYM_GEQ) { - getSymbol(); - rtype = gr_simpleExpression(); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); - // assert: allocatedRegisters == n + 2 - - if (ltype == rtype) { + } else if (operatorSymbol == SYM_GEQ) { // if a < b set 0, else 1 - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_SLT); + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); - allocatedRegisters = allocatedRegisters - 1; + tfree(1); - emitIFormat(OP_BNE, REG_ZR, allocatedRegisters, 4); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 1); + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters, 0); - } else - syntaxError(ERR_TYPE_MISMATCH); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + } } - - // assert: allocatedRegisters == n + 1 + + // assert: allocatedTemporaries == n + 1 return ltype; } @@ -2312,75 +2405,92 @@ void gr_while() { int brBackToWhile; int brForwardToEnd; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 + + brBackToWhile = binaryLength; - brBackToWhile = codeLength; + brForwardToEnd = 0; // while ( expression ) if (symbol == SYM_WHILE) { getSymbol(); + if (symbol == SYM_LPARENTHESIS) { getSymbol(); + gr_expression(); - //don't know where to branch, fixup later - brForwardToEnd = codeLength; - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + // do not know where to branch, fixup later + brForwardToEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); if (symbol == SYM_RPARENTHESIS) { getSymbol(); + // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); + while (isNotRbraceOrEOF()) gr_statement(); if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } } // only one statement without {} else gr_statement(); } else - syntaxError(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } else - syntaxError(SYM_WHILE); + syntaxErrorSymbol(SYM_WHILE); // unconditional branch to beginning of while - emitIFormat(OP_BEQ, 0, 0, brBackToWhile - codeLength - 1); + emitIFormat(OP_BEQ, 0, 0, (brBackToWhile - binaryLength - 4) / 4); - // first instr after loop comes here, now we have - // our address for the conditional jump from above - fixup_relative(brForwardToEnd); + if (brForwardToEnd != 0) + // first instruction after loop comes here + // now we have our address for the conditional jump from above + fixup_relative(brForwardToEnd); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_if() { int brForwardToElseOrEnd; int brForwardToEnd; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 // if ( expression ) if (symbol == SYM_IF) { getSymbol(); + if (symbol == SYM_LPARENTHESIS) { getSymbol(); + gr_expression(); // if the "if" case is not true, we jump to "else" (if provided) - brForwardToElseOrEnd = codeLength; - emitIFormat(OP_BEQ, REG_ZR, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 1; + brForwardToElseOrEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); if (symbol == SYM_RPARENTHESIS) { getSymbol(); + // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); @@ -2390,8 +2500,11 @@ void gr_if() { if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } } // only one statement without {} else @@ -2402,7 +2515,7 @@ void gr_if() { getSymbol(); // if the "if" case was true, we jump to the end - brForwardToEnd = codeLength; + brForwardToEnd = binaryLength; emitIFormat(OP_BEQ, 0, 0, 0); // if the "if" case was not true, we jump here @@ -2411,13 +2524,18 @@ void gr_if() { // zero or more statements: { statement } if (symbol == SYM_LBRACE) { getSymbol(); + while (isNotRbraceOrEOF()) gr_statement(); if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + // only one statement without {} } else gr_statement(); @@ -2428,142 +2546,144 @@ void gr_if() { // if the "if" case was not true, we jump here fixup_relative(brForwardToElseOrEnd); } else - syntaxError(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } else - syntaxError(SYM_IF); + syntaxErrorSymbol(SYM_IF); - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_return(int returnType) { - // assert: allocatedRegisters == 0 + int type; + + // assert: allocatedTemporaries == 0 - // keyword return if (symbol == SYM_RETURN) getSymbol(); else - syntaxError(SYM_RETURN); + syntaxErrorSymbol(SYM_RETURN); // optional: expression if (symbol != SYM_SEMICOLON) { - if (returnType != VOID_T) { - // TODO check for other wrong types, too - gr_expression(); + type = gr_expression(); - // save value of expression in return register - emitRFormat(OP_SPECIAL, REG_ZR, allocatedRegisters, REG_RR, FCT_ADDU); - allocatedRegisters = allocatedRegisters - 1; - } else - syntaxError(ERR_WRONG_RETURNTYPE); + if (returnType == VOID_T) + typeWarning(type, returnType); + else if (type != returnType) + typeWarning(returnType, type); + + // save value of expression in return register + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), REG_V0, FCT_ADDU); + + tfree(1); } // unconditional branch to procedure epilogue // maintain fixup chain for later fixup - emitJFormat(OP_J, returnBranches); + emitJFormat(OP_J, returnBranches / 4); // new head of fixup chain - returnBranches = codeLength-2; + // offest is 8 rather than 4 bytes because of delay slot NOP + returnBranches = binaryLength - 8; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_statement() { + int ltype; + int rtype; int *variableOrProcedureName; int *entry; - // assert: allocatedRegisters == 0; + // assert: allocatedTemporaries == 0; + + while (lookForStatement()) { + syntaxErrorUnexpected(); - while (waitForStatement()) - syntaxError(ERR_STATEMENT); + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } // ["*"] if (symbol == SYM_ASTERISK) { getSymbol(); - // ["*"] identifier + + // "*" identifier if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); + ltype = load_variable(identifier); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + getSymbol(); - // ["*"] identifier "=" + // "*" identifier "=" if (symbol == SYM_ASSIGN) { getSymbol(); - gr_expression(); + rtype = gr_expression(); - emitIFormat(OP_SW, allocatedRegisters-1, allocatedRegisters, 0); - allocatedRegisters = allocatedRegisters - 2; + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + tfree(2); } else - syntaxError(ERR_ASSIGN); + syntaxErrorSymbol(SYM_ASSIGN); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); - // "*" "(" identifier [ "+" integer ] + // "*" "(" expression ")" } else if (symbol == SYM_LPARENTHESIS) { getSymbol(); - if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); - - getSymbol(); - - if (symbol == SYM_PLUS) { - getSymbol(); - if (symbol == SYM_IDENTIFIER) { - load_variable(identifier); - getSymbol(); - } else if (symbol == SYM_INTEGER) - load_integer(); - else - syntaxError(ERR_IDENTIFIER_OR_INTEGER); + ltype = gr_expression(); - // pointer arithmetic requires factor of 2^2 - emitLeftShiftBy(2); - emitRFormat(OP_SPECIAL, allocatedRegisters-1, allocatedRegisters, allocatedRegisters-1, FCT_ADDU); + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); - allocatedRegisters = allocatedRegisters - 1; - } + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); - if (symbol == SYM_RPARENTHESIS) { + // "*" "(" expression ")" "=" + if (symbol == SYM_ASSIGN) { getSymbol(); - // "*" "(" identifier ["+" integer] ")" =" - if (symbol == SYM_ASSIGN) { - getSymbol(); - - gr_expression(); + rtype = gr_expression(); - emitIFormat(OP_SW, allocatedRegisters-1, allocatedRegisters, 0); + if (rtype != INT_T) + typeWarning(INT_T, rtype); - allocatedRegisters = allocatedRegisters - 2; - } else - syntaxError(ERR_ASSIGN); + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); - if (symbol == SYM_SEMICOLON) - getSymbol(); - else - syntaxWarn(SYM_SEMICOLON); + tfree(2); } else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); } else - syntaxError(ERR_IDENTIFIER); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); } - - // identifier = [ "*" ] identifier "=" expression ";" | - // identifier = call ";" - // call; + // identifier "=" expression | call else if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - // call ";" + // call if (symbol == SYM_LPARENTHESIS) { getSymbol(); @@ -2572,24 +2692,31 @@ void gr_statement() { if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); - // identifier = expression ";" + // identifier = expression } else if (symbol == SYM_ASSIGN) { entry = getVariable(variableOrProcedureName); + + ltype = getType(entry); + getSymbol(); - gr_expression(); - emitIFormat(OP_SW, getRegister(entry), allocatedRegisters, getData(entry)); + rtype = gr_expression(); + + if (ltype != rtype) + typeWarning(ltype, rtype); - allocatedRegisters = allocatedRegisters - 1; + emitIFormat(OP_SW, getRegister(entry), currentTemporary(), getData(entry)); + + tfree(1); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxError(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } else - syntaxError(ERR_IDENTIFIER_OR_ASSIGN); + syntaxErrorUnexpected(); } // while statement? else if (symbol == SYM_WHILE) { @@ -2601,28 +2728,23 @@ void gr_statement() { } // return statement? else if (symbol == SYM_RETURN) { - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); gr_return(getType(entry)); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } } -int gr_variable() { +int gr_type() { int type; - while (waitForVariable()) - syntaxError(ERR_TYPE); - - type = UNKNOWN; - + type = INT_T; + if (symbol == SYM_INT) { - type = INT_T; - getSymbol(); if (symbol == SYM_ASTERISK) { @@ -2630,117 +2752,204 @@ int gr_variable() { getSymbol(); } - - if (symbol != SYM_IDENTIFIER) - syntaxError(ERR_IDENTIFIER); } else - syntaxError(ERR_EOF); + syntaxErrorSymbol(SYM_INT); return type; } +void gr_variable(int offset) { + int type; + + type = gr_type(); + + if (symbol == SYM_IDENTIFIER) { + createSymbolTableEntry(LOCAL_TABLE, identifier, offset, VARIABLE, type, 0); + + getSymbol(); + } else { + syntaxErrorSymbol(SYM_IDENTIFIER); + + createSymbolTableEntry(LOCAL_TABLE, (int*) "missing variable name", offset, VARIABLE, type, 0); + } +} + +void gr_initialization(int *name, int offset, int type) { + int hasCast; + int cast; + int sign; + + initialValue = 0; + + hasCast = 0; + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else if (symbol == SYM_ASSIGN) { + getSymbol(); + + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + hasCast = 1; + + getSymbol(); + + cast = gr_type(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } + + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; + + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; + + if (isConstant()) { + initialValue = constant; + + getSymbol(); + + if (sign == 1) + initialValue = -initialValue; + } else + syntaxErrorUnexpected(); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorUnexpected(); + + if (hasCast) { + if (type != cast) + typeWarning(type, cast); + } else if (type != INT_T) + typeWarning(type, INT_T); + + createSymbolTableEntry(GLOBAL_TABLE, name, offset, VARIABLE, type, initialValue); +} + void gr_procedure(int *procedure, int returnType) { + int numberOfParameters; int parameters; - int oparam; - int offset; int localVariables; - int type; int functionStart; int *entry; - currentFuncName = procedure; + currentProcedureName = procedure; - oparam = 0; + numberOfParameters = 0; // ( variable , variable ) ; if (symbol == SYM_LPARENTHESIS) { getSymbol(); - parameters = 0; - if (symbol != SYM_RPARENTHESIS) { - type = gr_variable(); - - createSymbolTableEntry(LOCAL_TABLE, identifier, 0, VARIABLE, type); + gr_variable(0); - getSymbol(); - - parameters = 1; + numberOfParameters = 1; while (symbol == SYM_COMMA) { getSymbol(); - type = gr_variable(); - - createSymbolTableEntry(LOCAL_TABLE, identifier, 0, VARIABLE, type); - - getSymbol(); + gr_variable(0); - parameters = parameters + 1; + numberOfParameters = numberOfParameters + 1; } - oparam = parameters; entry = local_symbol_table; - offset = 8; // skip fp and link - while (parameters > 0) { - setData(entry, offset); - parameters = parameters - 1; - offset = offset + 4; + + parameters = 0; + + while (parameters < numberOfParameters) { + // 8 bytes offset to skip frame pointer and link + setData(entry, parameters * 4 + 8); + + parameters = parameters + 1; entry = getNext(entry); } if (symbol == SYM_RPARENTHESIS) getSymbol(); else - syntaxWarn(SYM_RPARENTHESIS); + syntaxErrorSymbol(SYM_RPARENTHESIS); } else getSymbol(); } else - syntaxError(SYM_LPARENTHESIS); + syntaxErrorSymbol(SYM_LPARENTHESIS); if (symbol == SYM_SEMICOLON) { - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); - if ((int)entry == 0) - createSymbolTableEntry(GLOBAL_TABLE, currentFuncName, 0, FUNCTION, returnType); + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, 0, FUNCTION, returnType, 0); getSymbol(); // ( variable, variable ) { variable; variable; statement } } else if (symbol == SYM_LBRACE) { - functionStart = codeLength; + functionStart = binaryLength; + getSymbol(); - localVariables = 0; - entry = getSymbolTableEntry(currentFuncName, global_symbol_table); + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); - if ((int)entry == 0) { - createSymbolTableEntry(GLOBAL_TABLE, currentFuncName, codeLength, FUNCTION, returnType); - } else { - if (getData(entry) != 0) - if (getOpcode(*(memory + getData(entry))) == OP_JAL) + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, binaryLength, FUNCTION, returnType, 0); + else { + if (getData(entry) != 0) { + if (getOpcode(loadMemory(getData(entry))) == OP_JAL) fixlink_absolute(getData(entry), functionStart); + else { + printLineNumber((int*) "error"); + + print((int*) "multiple definitions of "); + + print(currentProcedureName); + + println(); + } + } - // TODO: overwrites previous definitions setData(entry, functionStart); - // TODO: check type of declaration and definition + if (getType(entry) != returnType) + typeWarning(getType(entry), returnType); + setType(entry, returnType); } - while (symbol == SYM_INT) { - type = gr_variable(); + localVariables = 0; + while (symbol == SYM_INT) { localVariables = localVariables + 1; - createSymbolTableEntry(LOCAL_TABLE, identifier, -4 * localVariables, VARIABLE, type); - - getSymbol(); + gr_variable(-4 * localVariables); if (symbol == SYM_SEMICOLON) getSymbol(); else - syntaxWarn(SYM_SEMICOLON); + syntaxErrorSymbol(SYM_SEMICOLON); } help_procedure_prologue(localVariables); @@ -2753,84 +2962,81 @@ void gr_procedure(int *procedure, int returnType) { if (symbol == SYM_RBRACE) getSymbol(); - else - syntaxWarn(SYM_RBRACE); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } - fixlink_absolute(returnBranches, codeLength); + fixlink_absolute(returnBranches, binaryLength); returnBranches = 0; - help_procedure_epilogue(oparam, functionStart, returnType); + help_procedure_epilogue(numberOfParameters); } else - syntaxError(ERR_LBRACE_OR_SEMICOLON); + syntaxErrorUnexpected(); - local_symbol_table = 0; + local_symbol_table = (int*) 0; - // assert: allocatedRegisters == 0 + // assert: allocatedTemporaries == 0 } void gr_cstar() { - int offset; int type; int *variableOrProcedureName; - type = UNKNOWN; + while (symbol != SYM_EOF) { + while (lookForType()) { + syntaxErrorUnexpected(); - while (isVariableOrProcedure()) { - // type identifier - if (symbol == SYM_INT) { - type = INT_T; + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } - getSymbol(); + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; - if (symbol == SYM_ASTERISK) { - type = INTSTAR_T; - getSymbol(); - } + getSymbol(); if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - // type identifier, this means it is a global variable - if (symbol == SYM_SEMICOLON) { - getSymbol(); - - offset = allocatedGlobalVariables * (-4); - - createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, offset, VARIABLE, type); - - allocatedGlobalVariables = allocatedGlobalVariables + 1; - } - // type identifier procedure - else - gr_procedure(variableOrProcedureName, type); + gr_procedure(variableOrProcedureName, type); } else - syntaxError(ERR_IDENTIFIER); - - // void identifier procedure - } else if (symbol == SYM_VOID) { - type = VOID_T; - getSymbol(); + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); if (symbol == SYM_IDENTIFIER) { variableOrProcedureName = identifier; getSymbol(); - gr_procedure(variableOrProcedureName, type); - } - } else - syntaxError(ERR_PROCEDURE_OR_VARIABLE); - } + // type identifier "(" procedure declaration or definition + if (symbol == SYM_LPARENTHESIS) + gr_procedure(variableOrProcedureName, type); + else { + allocatedMemory = allocatedMemory + 4; - // when we leave while, we don't expect any more - // code to come, but if it does, it's a syntax error - if (symbol != SYM_EOF) { - syntaxError(ERR_EOF); - exit(-1); + // type identifier ";" global variable declaration + if (symbol == SYM_SEMICOLON) { + getSymbol(); + + createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, -allocatedMemory, VARIABLE, type, 0); + + // type identifier "=" global variable definition + } else + gr_initialization(variableOrProcedureName, -allocatedMemory, type); + } + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } } } @@ -2842,20 +3048,18 @@ void emitLeftShiftBy(int b) { // assert: 0 <= b < 15 // load multiplication factor less than 2^15 to avoid sign extension - emitIFormat(OP_ADDIU, REG_ZR, allocatedRegisters+1, twoToThePowerOf(b)); - emitRFormat(OP_SPECIAL, allocatedRegisters, allocatedRegisters+1, 0, FCT_MULTU); - emitRFormat(OP_SPECIAL, 0, 0, allocatedRegisters, FCT_MFLO); + emitIFormat(OP_ADDIU, REG_ZR, nextTemporary(), twoToThePowerOf(b)); + emitRFormat(OP_SPECIAL, currentTemporary(), nextTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, currentTemporary(), FCT_MFLO); } void emitMainEntry() { - int *label; + // instruction at address zero cannot be fixed up + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); - emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // null page + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", binaryLength, FUNCTION, INT_T, 0); - // "main": entry point - label = (int*)createString('m','a','i','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + mainJumpAddress = binaryLength; emitJFormat(OP_JAL, 0); } @@ -2866,28 +3070,37 @@ void emitMainEntry() { int main_compiler() { initScanner(); - initSymbolTable(); initParser(); - allocateMachineMemory(maxCodeLength*4); + // memory in bytes and executable file name "out" + initMemory(maxBinaryLength, (int*) "out"); getSymbol(); + // jump to main emitMainEntry(); - // Library functions: - emitExit(); // first library function because this marks - // also 'default'-exit when programmer hasn't - // inserted exit() call in main + // library: + // exit must be first to exit main + // if exit call in main is missing + emitExit(); emitRead(); emitWrite(); emitOpen(); emitMalloc(); emitGetchar(); emitPutchar(); + emitYield(); + + // parser + gr_cstar(); - gr_cstar(); // invoke compiler - emitBinary(); + if (getInstrIndex(loadMemory(mainJumpAddress)) != 0) + emitBinary(); + else { + print((int*) "cstarc: main function missing"); + println(); + } exit(0); } @@ -2898,6 +3111,14 @@ int main_compiler() { // ----------------------------------------------------------------- // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void printRegister(int reg) { + print((int*) *(REGISTERS + reg)); +} + // ----------------------------------------------------------------- // ---------------------------- ENCODER ---------------------------- // ----------------------------------------------------------------- @@ -2990,6 +3211,14 @@ int signExtend(int immediate) { // ---------------------------- DECODER ---------------------------- // ----------------------------------------------------------------- +void printOpcode(int opcode) { + print((int*) *(OPCODES + opcode)); +} + +void printFunction(int function) { + print((int*) *(FUNCTIONS + function)); +} + void decode() { opcode = getOpcode(ir); @@ -3055,8 +3284,26 @@ void decodeJFormat() { // ---------------------------- MEMORY ----------------------------- // ----------------------------------------------------------------- -void allocateMachineMemory(int size) { - memory = (int*)malloc(size); +int tlb(int vaddr) { + + if (vaddr % 4 != 0) + exception_handler(EXCEPTION_ADDRESSERROR); + + if(process !=0){ + vaddr = vaddr + segmentStart; + + } + + // physical memory is word-addressed for lack of byte-sized data type + return vaddr / 4; +} + +int loadMemory(int vaddr) { + return *(memory + tlb(vaddr)); +} + +void storeMemory(int vaddr, int data) { + *(memory + tlb(vaddr)) = data; } // ----------------------------------------------------------------- @@ -3064,12 +3311,13 @@ void allocateMachineMemory(int size) { // ----------------------------------------------------------------- void emitInstruction(int instruction) { - if (codeLength >= maxCodeLength) { - syntaxError(ERR_MAXCODELENGTH); + if (binaryLength >= maxBinaryLength) { + syntaxErrorMessage((int*) "exceeded maximum binary length"); exit(-1); } else { - *(memory + codeLength) = instruction; - codeLength = codeLength + 1; + storeMemory(binaryLength, instruction); + + binaryLength = binaryLength + 4; } } @@ -3107,95 +3355,111 @@ void emitJFormat(int opcode, int instr_index) { } void fixup_relative(int fromAddress) { - *(memory + fromAddress) = encodeIFormat( - getOpcode(*(memory + fromAddress)), - getRS(*(memory + fromAddress)), - getRT(*(memory + fromAddress)), - codeLength - fromAddress - 1); + int instruction; + + instruction = loadMemory(fromAddress); + + storeMemory(fromAddress, + encodeIFormat(getOpcode(instruction), + getRS(instruction), + getRT(instruction), + (binaryLength - fromAddress - 4) / 4)); } void fixup_absolute(int fromAddress, int toAddress) { - *(memory + fromAddress) = - encodeJFormat(getOpcode(*(memory + fromAddress)), toAddress); + storeMemory(fromAddress, + encodeJFormat(getOpcode(loadMemory(fromAddress)), toAddress / 4)); } void fixlink_absolute(int fromAddress, int toAddress) { int previousAddress; while (fromAddress != 0) { - previousAddress = getInstrIndex(*(memory + fromAddress)); + previousAddress = getInstrIndex(loadMemory(fromAddress)) * 4; fixup_absolute(fromAddress, toAddress); fromAddress = previousAddress; } } +int copyStringToMemory(int *s, int a) { + int l; + int w; + + l = stringLength(s) + 1; + + w = a + l; + + if (l % 4 != 0) + w = w + 4 - l % 4; + + while (a < w) { + storeMemory(a, *s); + + s = s + 1; + a = a + 4; + } + + return w; +} + void emitBinary() { - int i; - int *filename; + int *entry; int fd; - i = 0; + entry = global_symbol_table; - // put global variables as 0 at end of codearray - while (i < allocatedGlobalVariables) { - *(memory + codeLength) = 0; + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeMemory(binaryLength, getValue(entry)); - codeLength = codeLength + 1; + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToMemory(getString(entry), binaryLength); - i = i + 1; + entry = getNext(entry); } - filename = (int*)malloc(4*4); - *filename = 7632239; //filename: out - - // assumption: file with name "out" exists prior to execution of compiler - fd = open(filename, 1); // 1 = O_WRONLY + // assert: file with name binaryName exists prior to execution of compiler + fd = open(binaryName, 1); // 1 = O_WRONLY if (fd < 0) { - syntaxError(ERR_FILE_NOT_FOUND); + syntaxErrorMessage((int*) "output file not found"); exit(-1); } - // The mipster_sycall 4004 writes the code array into a binary called 'out'. - // The syscall uses the 'write' system call of the underlying operating - // system and the compiler (gcc/x86). The write system call of our Linux uses - // Little Endian byte ordering. - write(fd, memory, codeLength*4); + // The mipster_syscall 4004 writes the code array into a file. + // The syscall uses the "write" system call of the OS and compiler. + // The write system call of our Linux uses little endian byte ordering. + write(fd, memory, binaryLength); } -int loadBinary(int *filename) { +void loadBinary() { int fd; - int i; - int ret; + int numberOfReadBytes; - fd = open(filename, 0); + fd = open(binaryName, 0); // 0 = O_RDONLY if (fd < 0) exit(-1); - i = 0; - - ret = 4; + numberOfReadBytes = 4; - while (ret == 4) { - ret = read(fd, memory + i, 4); + while (numberOfReadBytes == 4) { + numberOfReadBytes = read(fd, memory + tlb(binaryLength), 4); if (debug_load) { - memset(string_buffer, 33, 0); - print(itoa(i * 4, string_buffer, 16, 4)); - putchar(' '); - putchar('#'); - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa(*(memory+i), string_buffer, 16, 8)); - putchar(CHAR_LF); + print(binaryName); + print((int*) ": "); + print(itoa(binaryLength, string_buffer, 16, 8)); + print((int*) ": "); + print(itoa(loadMemory(binaryLength), string_buffer, 16, 8)); + println(); } - i = i + 1; + if (numberOfReadBytes == 4) + binaryLength = binaryLength + 4; } - - // Return global pointer and bump pointer for malloc - return i * 4; } // ----------------------------------------------------------------- @@ -3203,12 +3467,7 @@ int loadBinary(int *filename) { // ----------------------------------------------------------------- void emitExit() { - int *label; - - // "exit" - label = createString('e','x','i','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "exit", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3226,24 +3485,18 @@ void syscall_exit() { exitCode = *(registers+REG_A0); - printString('[','O','S',']',' ','T', 'e', 'r','m','i','n','a','t','e','d',' ','w','i','t','h'); - putchar(' '); - *(registers+REG_V0) = exitCode; + print(binaryName); + print((int*) ": exiting with error code "); print(itoa(exitCode, string_buffer, 10, 0)); - putchar(CHAR_LF); + println(); exit(0); } void emitRead() { - int *label; - - // "read" - label = createString('r','e','a','d',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3259,48 +3512,40 @@ void emitRead() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_read() { int count; - int address; + int vaddr; int fd; int *buffer; int size; - count = *(registers+REG_A2); - address = *(registers+REG_A1) / 4; - fd = *(registers+REG_A0); + count = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); - buffer = memory + address; + buffer = memory + tlb(vaddr); size = read(fd, buffer, count); *(registers+REG_V0) = size; - if (debug_syscalls) { - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','r','e','a','d',' ',CHAR_TAB,0,0,0,0); - - print(itoa(fd, string_buffer, 10, 0)); - putchar(' '); - memset(string_buffer, 33, 0); - print(itoa((int)buffer, string_buffer, 16, 8)); - putchar(' '); + if (debug_read) { + print(binaryName); + print((int*) ": read "); print(itoa(size, string_buffer, 10, 0)); - putchar(CHAR_LF); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + println(); } } void emitWrite() { - int *label; - - // "write" - label = createString('w','r','i','t','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3316,38 +3561,39 @@ void emitWrite() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_write() { int size; - int address; + int vaddr; int fd; int *buffer; - size = *(registers+REG_A2); - address = *(registers+REG_A1) / 4; - fd = *(registers+REG_A0); + size = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); - buffer = memory + address; + buffer = memory + tlb(vaddr); size = write(fd, buffer, size); *(registers+REG_V0) = size; - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','w','r','i','t','e',CHAR_LF,0,0,0,0); + if (debug_write) { + print(binaryName); + print((int*) ": wrote "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + println(); + } } void emitOpen() { - int *label; - - // "open" - label = createString('o','p','e','n',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "open", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3361,41 +3607,38 @@ void emitOpen() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_open() { int flags; - int address; + int vaddr; int *filename; int fd; - flags = *(registers+REG_A1); - address = *(registers+REG_A0) / 4; + flags = *(registers+REG_A1); + vaddr = *(registers+REG_A0); - filename = memory + address; + filename = memory + tlb(vaddr); fd = open(filename, flags); *(registers+REG_V0) = fd; - if (debug_syscalls) { - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','o','p','e','n',' ',CHAR_TAB,0,0,0,0); - + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 10, 0)); + print((int*) " returning file descriptor "); print(itoa(fd, string_buffer, 10, 0)); - putchar(CHAR_LF); + println(); } } void emitMalloc() { - int *label; - - // "malloc" - label = createString('m','a','l','l','o','c',0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INTSTAR_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "malloc", binaryLength, FUNCTION, INTSTAR_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3411,11 +3654,8 @@ void emitMalloc() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MALLOC); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - // put return value into return register - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - // jump back to caller - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_malloc() { @@ -3425,7 +3665,7 @@ void syscall_malloc() { size = *(registers+REG_A0); if (size % 4 != 0) - size = size + (4 - size % 4); + size = size + 4 - size % 4; bump = *(registers+REG_K1); @@ -3435,17 +3675,18 @@ void syscall_malloc() { *(registers+REG_K1) = bump + size; *(registers+REG_V0) = bump; - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','m','a','l','l','o','c',CHAR_LF,0,0,0); + if (debug_malloc) { + print(binaryName); + print((int*) ": malloc "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8)); + println(); + } } void emitGetchar() { - int *label; - - // "getchar" - label = createString('g','e','t','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0); - - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "getchar", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3455,25 +3696,26 @@ void emitGetchar() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_GETCHAR); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitIFormat(OP_ADDIU, REG_V0, REG_RR, 0); - - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } void syscall_getchar() { - *(registers+REG_V0) = getchar(); + int c; - if (debug_syscalls) - printString('[','O','S',']',' ','c', 'a', 'l','l',' ','g','e','t','c','h','a','r',CHAR_LF,0,0); -} + c = getchar(); -void emitPutchar() { - int *label; + *(registers+REG_V0) = c; - // "putchar" - label = createString('p','u','t','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0); + if (debug_getchar) { + print(binaryName); + print((int*) ": getchar "); + printCharacter(c); + println(); + } +} - createSymbolTableEntry(GLOBAL_TABLE, label, codeLength, FUNCTION, INT_T); +void emitPutchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); @@ -3487,7 +3729,29 @@ void emitPutchar() { emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); - emitRFormat(OP_SPECIAL, REG_LINK, 0, 0, FCT_JR); + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void emitYield(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "yield", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_YIELD); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_yield(){ + scheduler(); } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -3502,8 +3766,8 @@ void emitPutchar() { void fct_syscall() { if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + printFunction(function); + println(); } if (*(registers+REG_V0) == SYSCALL_EXIT) { @@ -3518,95 +3782,91 @@ void fct_syscall() { syscall_malloc(); } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { syscall_getchar(); - } else { + } else if (*(registers+REG_V0) == SYSCALL_YIELD) { + syscall_yield(); + }else { exception_handler(EXCEPTION_UNKNOWNSYSCALL); } - pc = pc + 1; + pc = pc + 4; } void fct_nop() { - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - putchar(CHAR_LF); + printFunction(function); + println(); } } void op_jal() { - *(registers+REG_LINK) = pc * 4 + 8; + *(registers+REG_RA) = pc + 8; - pc = instr_index; + pc = instr_index * 4; // TODO: execute delay slot if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - memset(string_buffer, 33, 0); + printOpcode(opcode); + print((int*) " "); print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + println(); } } void op_j() { - pc = instr_index; + pc = instr_index * 4; // TODO: execute delay slot if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - memset(string_buffer, 33, 0); + printOpcode(opcode); + print((int*) " "); print(itoa(instr_index, string_buffer, 16, 8)); - putchar(CHAR_LF); + println(); } } void op_beq() { - pc = pc + 1; + pc = pc + 4; if (*(registers+rs) == *(registers+rt)) { - pc = pc + signExtend(immediate); + pc = pc + signExtend(immediate) * 4; + // TODO: execute delay slot } if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printOpcode(opcode); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void op_bne() { - pc = pc + 1; + pc = pc + 4; if (*(registers+rs) != *(registers+rt)) { - pc = pc + signExtend(immediate); + pc = pc + signExtend(immediate) * 4; + // TODO: execute delay slot } if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printOpcode(opcode); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } @@ -3615,80 +3875,69 @@ void op_addiu() { // TODO: check for overflow - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void fct_jr() { - pc = *(registers+rs) / 4; + pc = *(registers+rs); if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rs); + println(); } } void op_lui() { *(registers+rt) = leftShift(immediate, 16); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - - putchar(CHAR_LF); + println(); } } void fct_mfhi() { *(registers+rd) = reg_hi; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); } } void fct_mflo() { *(registers+rd) = reg_lo; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); - - putchar(CHAR_LF); + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); } } @@ -3696,17 +3945,15 @@ void fct_multu() { // TODO: 64-bit resolution currently not supported reg_lo = *(registers+rs) * *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } @@ -3714,82 +3961,71 @@ void fct_divu() { reg_lo = *(registers+rs) / *(registers+rt); reg_hi = *(registers+rs) % *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } void fct_addu() { *(registers+rd) = *(registers+rs) + *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); + printRegister(rt); + println(); } } void fct_subu() { *(registers+rd) = *(registers+rs) - *(registers+rt); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - putchar(CHAR_LF); - + printRegister(rt); + println(); } } void op_lw() { int vaddr; - int paddr; vaddr = *(registers+rs) + signExtend(immediate); - paddr = addressTranslation(vaddr) / 4; - - *(registers+rt) = *(memory+paddr); + *(registers+rt) = loadMemory(vaddr); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - putchar('('); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(')'); - - putchar(CHAR_LF); + println(); } } @@ -3799,48 +4035,39 @@ void fct_slt() { else *(registers+rd) = 0; - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(fct_strings+function))); - - putchar(' '); - print((int*)(*(register_strings+rd))); + printFunction(function); + print((int*) " "); + printRegister(rd); putchar(','); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } void op_sw() { int vaddr; - int paddr; - int tmp; vaddr = *(registers+rs) + signExtend(immediate); - paddr = addressTranslation(vaddr) / 4; + storeMemory(vaddr, *(registers+rt)); - *(memory+paddr) = *(registers+rt); - - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)(*(op_strings+opcode))); - - putchar(' '); - print((int*)(*(register_strings+rt))); + printOpcode(opcode); + print((int*) " "); + printRegister(rt); putchar(','); print(itoa(signExtend(immediate), string_buffer, 10, 0)); - putchar('('); - print((int*)(*(register_strings+rs))); + printRegister(rs); putchar(')'); - - putchar(CHAR_LF); + println(); } } @@ -3848,17 +4075,15 @@ void fct_teq() { if (*(registers+rs) == *(registers+rt)) exception_handler(EXCEPTION_SIGNAL); - pc = pc + 1; + pc = pc + 4; if (debug_disassemble) { - print((int*)*(fct_strings+function)); - - putchar(' '); - print((int*)(*(register_strings+rs))); + printFunction(function); + print((int*) " "); + printRegister(rs); putchar(','); - print((int*)(*(register_strings+rt))); - - putchar(CHAR_LF); + printRegister(rt); + println(); } } @@ -3866,34 +4091,25 @@ void fct_teq() { // -------------------------- INTERPRETER -------------------------- // ----------------------------------------------------------------- -void exception_handler(int enumber) { - if (enumber == EXCEPTION_SIGNAL) { - exit(EXCEPTION_SIGNAL); - } else if (enumber == EXCEPTION_ADDRESSERROR) { - exit(EXCEPTION_ADDRESSERROR); - } else if (enumber == EXCEPTION_UNKNOWNINSTRUCTION) { - exit(EXCEPTION_UNKNOWNINSTRUCTION); - } else if (enumber == EXCEPTION_HEAPOVERFLOW) { - exit(EXCEPTION_HEAPOVERFLOW); - } else if (enumber == EXCEPTION_UNKNOWNSYSCALL) { - exit(EXCEPTION_UNKNOWNSYSCALL); - } else if (enumber == EXCEPTION_UNKNOWNFUNCTION) { - exit(EXCEPTION_UNKNOWNFUNCTION); - } +void printException(int enumber) { + print((int*) *(EXCEPTIONS + enumber)); } -int addressTranslation(int vaddr) { - if (vaddr % 4 != 0) - exception_handler(EXCEPTION_ADDRESSERROR); +void exception_handler(int enumber) { + print(binaryName); + print((int*) ": exception: "); + printException(enumber); + println(); - return vaddr; + exit(enumber); } void pre_debug() { if (debug_disassemble) { - memset(string_buffer, 33, 0); // print current PC - print(itoa(4 * pc, string_buffer, 16, 4)); - putchar(CHAR_TAB); + print(binaryName); + print((int*) ": $pc="); + print(itoa(pc, string_buffer, 16, 8)); + print((int*) ": "); } } @@ -3904,21 +4120,21 @@ void post_debug() { while (i < 32) { if (*(registers+i) != 0) { - print((int*)*(register_strings+i)); - putchar(CHAR_TAB); - memset(string_buffer, 33, 0); + print(binaryName); + print((int*) ": "); + printRegister(i); + putchar(CHAR_EQUAL); print(itoa(*(registers+i), string_buffer, 16, 8)); - - putchar(CHAR_LF); + println(); } i = i + 1; } - putchar(CHAR_LF); + println(); } } void fetch() { - ir = *(memory+pc); + ir = loadMemory(pc); } void execute() { @@ -3969,7 +4185,7 @@ void execute() { //A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH void run() { - pop(readyqueue); + process = pop(readyqueue); while (1) { fetch(); decode(); @@ -3979,7 +4195,7 @@ void run() { numberofInstructions = numberofInstructions + 1; if(numberofInstructions > 10){ - scheduler(); + //scheduler(); } } @@ -3987,43 +4203,36 @@ void run() { } -void debug_boot(int memorySize) { - printString('m','e','m',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - - print(itoa(memorySize/1024/1024*4, string_buffer, 10, 0)); - - printString('M','B',CHAR_LF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); -} - -int* parse_args(int argc, int *argv, int *cstar_argv) { +void parse_args(int argc, int *argv) { // assert: ./selfie -m size executable {-m size executable} - int memorySize; - memorySize = atoi((int*)*(cstar_argv+2)) * 1024 * 1024 / 4; + // memory size in bytes and executable file name + initMemory(atoi((int*) *(argv+2)) * 1024 * 1024, (int*) *(argv+3)); - allocateMachineMemory(memorySize*4); - memSize = memorySize; //ADDED A1 - // initialize stack pointer - *(registers+REG_SP) = (memorySize - 1) * 4; + //*(registers+REG_SP) = memorySize - 4; + + memSize = atoi((int*) *(argv+2)) * 1024 * 1024; //ADDED A1 - debug_boot(memorySize); - // return executable file name - return (int*)*(argv+3); + print(binaryName); + print((int*) ": memory size "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0)); + print((int*) "MB"); + println(); } void up_push(int value) { - int address; + int vaddr; // allocate space for one value on the stack *(registers+REG_SP) = *(registers+REG_SP) - 4; // compute address - address = *(registers+REG_SP) / 4; + vaddr = *(registers+REG_SP); // store value - *(memory + address) = value; + storeMemory(vaddr, value); } int up_malloc(int size) { @@ -4034,74 +4243,47 @@ int up_malloc(int size) { return *(registers+REG_V0); } -int CStringLength(int* s) { - int l; - - l = 0; - - while (rightShift(leftShift(*s, 24 - (l % 4) * 8), 24) != 0) { - l = l + 1; - - if (l % 4 == 0) - s = s + 1; - } - - return l; -} - -int up_copyCString(int *s) { - int l; - int r; - int a; - - l = CStringLength(s); - - r = up_malloc(l+1); - - a = r / 4; - - while (a * 4 < r + l + 1) { - *(memory + a) = *s; - - s = s + 1; - a = a + 1; - } - - return r; -} - void up_copyArguments(int argc, int *argv) { - int c_argv; - - up_push(argc); + int vaddr; - c_argv = up_malloc(argc*4); + up_push(argc); - up_push(c_argv); + vaddr = up_malloc(argc * 4); - c_argv = c_argv / 4; + up_push(vaddr); while (argc > 0) { - *(memory + c_argv) = up_copyCString((int*)*argv); + storeMemory(vaddr, up_malloc(stringLength((int*) *argv) + 1)); - c_argv = c_argv + 1; - argv = argv + 1; + copyStringToMemory((int*) *argv, loadMemory(vaddr)); + + vaddr = vaddr + 4; + argv = argv + 1; argc = argc - 1; } } -int main_emulator(int argc, int *argv, int *cstar_argv) { +int main_emulator(int argc, int *argv) { initInterpreter(); - *(registers+REG_GP) = loadBinary(parse_args(argc, argv, cstar_argv)); + parse_args(argc, argv); + + loadBinary(); + + *(registers+REG_GP) = binaryLength; *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the firs segment! + + *(registers+REG_SP) = segSize - 4; up_copyArguments(argc-3, argv+3); createProcessList(3); //ADDED CREATES LIST WITH 3 PROCESSES + run(); exit(0); @@ -4123,44 +4305,48 @@ void memCopy(int *oldMemory, int *newMemory, int length) { } void createProcessList (int numberoOfProcesses){ - int i; - i = 0; + int i = 0; + int pId = 0; while(i 0) { - *cursor = (int)copyC2CStarString((int*)*argv); - - argv = argv + 1; - cursor = cursor + 1; - argc = argc - 1; - } - - return cstar_argv; -} - int main(int argc, int *argv) { - int *cstar_argv; int *firstParameter; initLibrary(); initRegister(); initDecoder(); - initSyscalls(); - - cstar_argv = copyC2CStarArguments(argc, argv); - + if (argc > 1) { - firstParameter = (int*) (*(cstar_argv+1)); + firstParameter = (int*) *(argv+1); - if (*firstParameter == '-') { - if (*(firstParameter+1) == 'c') + if (getCharacter(firstParameter, 0) == '-') { + if (getCharacter(firstParameter, 1) == 'c') main_compiler(); - else if (*(firstParameter+1) == 'm') { + else if (getCharacter(firstParameter, 1) == 'm') { if (argc > 3) - main_emulator(argc, argv, cstar_argv); + main_emulator(argc, (int*) argv); else exit(-1); } @@ -4361,4 +4583,4 @@ int main(int argc, int *argv) { } else // default: compiler main_compiler(); -} +} \ No newline at end of file diff --git a/test.c b/test.c index 22b1999..beb3549 100644 --- a/test.c +++ b/test.c @@ -7,6 +7,7 @@ int INT_MIN; int INT_MAX; int result; int *power_of_two_table; +int a; @@ -227,12 +228,14 @@ int main(){ print(itoa(3, string_buffer, 10, 0)); print(itoa(4, string_buffer, 10, 0)); print(itoa(5, string_buffer, 10, 0)); - + putchar(CHAR_LF); + yield(); print(itoa(6, string_buffer, 10, 0)); print(itoa(7, string_buffer, 10, 0)); print(itoa(8, string_buffer, 10, 0)); print(itoa(9, string_buffer, 10, 0)); putchar(CHAR_LF); + yield(); From fc2afe9d94e2c63d37263e8cc4106bb8ca5c83e3 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Sat, 31 Oct 2015 17:49:21 +0100 Subject: [PATCH 18/26] new versions LICENCE, README --- LICENSE | 27 +-------------------------- README.md | 50 ++------------------------------------------------ 2 files changed, 3 insertions(+), 74 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 index 4848b4b..a10edf9 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,3 @@ -<<<<<<< HEAD Copyright (c) 2015, the Selfie Project authors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -9,38 +8,14 @@ modification, are permitted provided that the following conditions are met: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -======= -Copyright (c) 2015, Christoph Kirsch -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. ->>>>>>> d59eedb453fca7fa76fefc25599d40eb13730f77 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -<<<<<<< HEAD DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -======= -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ->>>>>>> d59eedb453fca7fa76fefc25599d40eb13730f77 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 47bb1b6..d2b26f4 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD # Selfie Selfie is a project of the [Computational Systems Group](http://www.cs.uni-salzburg.at/~ck) at the Department of Computer Sciences of the University of Salzburg in Austria. @@ -98,7 +97,7 @@ You can enable verbose debugging with variables set in `selfie.c`: ### On Mac OS X / 64-bit Linux -On Mac OS X as well as on 64-bit Linux (requires gcc-multiarch. On Ubuntu, install gcc-multilib), you may use the following command to compile `selfie.c`: +On Mac OS X as well as on 64-bit Linux (requires gcc-multiarch or, on Ubuntu, gcc-multilib), you may use the following command to compile `selfie.c`: ```bash clang -w -m32 -D'main(a, b)=main(int argc, char **argv)' -o selfie selfie.c @@ -106,49 +105,4 @@ clang -w -m32 -D'main(a, b)=main(int argc, char **argv)' -o selfie selfie.c After that, you can proceed with the same commands as for 32-bit Linux. -The `-w` option suppresses warnings that can be ignored for now. The `-m32` option makes the compiler generate a 32-bit executable. Selfie only supports 32-bit architectures right now. The `-D` option is needed to bootstrap the main function declaration. The `char` data type is not available in C\* but required by `clang`. -======= -Home Work Flow --------------- - -* Step 0: form a team of 2-3 members -* Step 1: get a github account (for each member) -* Step 2: one person per group forks the AOS-Winter-2015 repository by clicking [here](https://github.com/cksystemsteaching/AOS-Winter-2015/fork) and adds the other team members as collaborators -* Step 3: check out the branch named __selfie-master__ in __your__ fork of AOS-Winter-2015 -* Step 4: implement the first assignment (see below) -* Step 5: add your names to the AUTHORS file -* Step 6: send a pull request containing your solution via github.com to [cksystemsteaching/AOS-Winter-2015/tree/selfie-master](https://github.com/cksystemsteaching/AOS-Winter-2015/tree/selfie-master) - - -Assignment 0: Basic data structures ------------------------------------ - -Review [linked lists](https://en.wikipedia.org/wiki/Linked_list) and implement a simple program using a singly linked list in C*. The minimal requirements are as follows: - -* must be implemented in C* -* must compile with selfie -* must run on selfie -* the list must be dynamically allocated -* every node must be dynamically allocated -* inserting nodes to the list and removing nodes from the list -* list iteration -* Bonus: sort the list. Any way you like -* Deadline: Oct 15, end of day - - -Assignment 1: Loading, scheduling, switching, execution -------------------------------------------------------- - -Implement basic concurrent execution of _n_ processes in mipster. _n >= 2_ - -* understand how mipster [interprets and executes binary instructions](https://github.com/cksystemsteaching/AOS-Winter-2015/blob/selfie-master/selfie.c#L3933). Tipp: add your own comments to the code -* mipster maintains a local state for a process (running executable), e.g., pc, registers, memory -* understand the purpose of each variable and data structure -* duplicate the process state n times -* running mipster like: _./selfie -m 32 yourbinary_ should generate _n_ instances of _yourbinary_ in a single instance of mipster -* implement [preemptive multitasking](https://en.wikipedia.org/wiki/Preemption_(computing)), i.e., switching between the _n_ instances of _yourbinary_ is determined by mipster -* switch processes every m instructions. _1 <= m <= number of instructions in yourbinary_ -* implement [round-robin scheduling](https://en.wikipedia.org/wiki/Round-robin_scheduling) -* add some output in _yourbinary_ to demonstrate context switching -* Deadline: Oct 22, end of day ->>>>>>> d59eedb453fca7fa76fefc25599d40eb13730f77 +The `-w` option suppresses warnings that can be ignored for now. The `-m32` option makes the compiler generate a 32-bit executable. Selfie only supports 32-bit architectures right now. The `-D` option is needed to bootstrap the main function declaration. The `char` data type is not available in C\* but required by `clang`. \ No newline at end of file From 33e5fec4501ca545d787ccdddc3991cfa40caef5 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Fri, 6 Nov 2015 00:03:40 +0100 Subject: [PATCH 19/26] Assignment3, works with 1 process, still contains bugs though" ; --- makefile | 11 +- selfie.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 410 insertions(+), 55 deletions(-) diff --git a/makefile b/makefile index 7a49208..b17113b 100644 --- a/makefile +++ b/makefile @@ -6,10 +6,13 @@ PROGRAMS=selfie default: compile run compile: - -rm -r $ list.mips + -rm -r $ test.mips -touch out - ./selfie < list.c - -mv out list.mips + ./selfie -c < test.c + -mv out test.mips + -touch out + ./selfie -c < selfie.c + -mv out selfie.mips run: - ./selfie -m 32 list.mips + ./selfie -m 32 test.mips diff --git a/selfie.c b/selfie.c index d56674a..fde4020 100755 --- a/selfie.c +++ b/selfie.c @@ -657,8 +657,11 @@ void syscall_getchar(); void emitPutchar(); -void emitYield(); -void syscall_yield(); +void emitYield(); //ADDED A2 +void syscall_yield(); //ADDED A2 + +void emitSwitch(); //ADDED A3 +void syscall_switch(); //ADDED A3 // ------------------------ GLOBAL CONSTANTS ----------------------- @@ -668,7 +671,8 @@ int SYSCALL_WRITE = 4004; int SYSCALL_OPEN = 4005; int SYSCALL_MALLOC = 5001; int SYSCALL_GETCHAR = 5002; -int SYSCALL_YIELD = 5003; +int SYSCALL_YIELD = 5003; //ADDED A2 +int SYSCALL_SWITCH = 5004; //ADDED A3 // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -760,7 +764,7 @@ int reg_lo = 0; // lo register for multiplication/division // -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- -void push(int *mem, int *reg, int *reg_hi, int *reg_lo, int pc,int pId,int *segment, int *head); +void push(int *mem, int *reg, int reg_hi, int reg_lo, int pc,int pId,int *segment,int gp, int sp, int k1, int *head); void setPrcosessNext(int *process, int *next); void setProcessPc(int * process, int pc); @@ -770,6 +774,10 @@ void setProcessRegHi(int *process, int reg_hi); void setProcessRegLo(int *process, int reg_lo); void setProcessId (int *process, int pId); void setProcessSegPointer(int *process, int *segment); +void setProcessGlobalP(int *process, int gp); +void setProcessStackP(int *process, int sp); +void setProcessK1(int *process,int kp); + int* getProcessNext(int *process); int getProcessPc(int *process); @@ -779,6 +787,9 @@ int getProcessRegHi(int *process); int getProcessRegLo(int *process); int getProcessId(int *process); int* getProcessSegPointer(int *process); +int getProcessGlobalP(int *process); +int getProcessStackP(int *process); +int getProcessK1(int *process); void createProcessList(int numberoOfProcesses); @@ -810,11 +821,32 @@ int numberofInstructions = 0; int *process = 0; int *segmentTable = 0; int segPointer = 0; -int segSize = 2 * 1024 * 1024; +int segSize = 2097152; int segmentStart = 0; //this variable is initalized when scheduler is called // so that it doesn't have to be computed every time // tlb is called +// ----------------- ASSIGNMENT 3 -------------------------------- +int main_os(); +int interruptOccured = 0; +int processTable = 0; +void insertInProcessTable(int *process, int gp, int sp,int*head); + + +void setProcessTableNext(int *processEntry, int *next); +void setProcessTableProcess(int *processEntry, int *process); +void setProcessTableGp(int *processEntry, int gp); +void setProcessTableSp(int *processEntry, int sp); +int *getProcessTableNext(int *processEntry); +int *getProcessTableProcess(int *processEntry); +int getProcessTableGp(int *processEntry); +int getProcessTableSp(int *processEntry); + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segstart,int gp,int sp,int k1); +void restoreKernelState(); +int tlb_debug = 0; +void loadProcess(int * name, int id); // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { @@ -828,6 +860,7 @@ void initInterpreter() { *(EXCEPTIONS + EXCEPTION_UNKNOWNFUNCTION) = (int) "unknown function"; registers = malloc(32*4); + } // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ @@ -3091,6 +3124,7 @@ int main_compiler() { emitGetchar(); emitPutchar(); emitYield(); + emitSwitch(); // parser gr_cstar(); @@ -3289,11 +3323,28 @@ int tlb(int vaddr) { if (vaddr % 4 != 0) exception_handler(EXCEPTION_ADDRESSERROR); - if(process !=0){ - vaddr = vaddr + segmentStart; + if(tlb_debug == 1){ + if(process !=0){ + print(itoa(vaddr/4, string_buffer, 10, 0)); + + print((int*)" --> "); + vaddr = vaddr + segmentStart; + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + + else{ + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } } - + else{ + if(process !=0){ + vaddr = vaddr + segmentStart; + } + } + // physical memory is word-addressed for lack of byte-sized data type return vaddr / 4; } @@ -3732,6 +3783,59 @@ void emitPutchar() { emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); } +//----------------------------------------------------------------------------------------- +//---------------------------ASSIGNEMENT 3, CONTAINS BUGS --------------------------------- +//----------------------------------------------------------------------------------------- + + +void emitSwitch(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "switch", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + //emitIFormat(OP_LW, REG_SP, REG_T1, 0); + //emitIFormat(OP_LW, REG_SP, REG_T2, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SWITCH); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_switch(){ + + print("switching"); + println(); + + saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); + if(*(memory+segSize+12) == 0) + registers = malloc(32); + else + registers = *(memory+segSize+12); + + + pc = *(memory+segSize+11); + reg_hi = *(memory+segSize+13); + reg_lo = *(memory+segSize+14); + segmentStart = *(memory+segSize+15); + process = *(memory+segSize+16); + *(registers+REG_GP) = *(memory+segSize+17); + *(registers+REG_SP) = *(memory+segSize+18); + *(registers+REG_K1) = *(memory+segSize+19); + + *(memory+segSize+10) = 0; //exit + + +} + + void emitYield(){ createSymbolTableEntry(GLOBAL_TABLE, (int*) "yield", binaryLength, FUNCTION, INT_T, 0); @@ -3746,14 +3850,170 @@ void emitYield(){ emitRFormat(0, 0, 0, 0, FCT_SYSCALL); emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); - + } void syscall_yield(){ - scheduler(); + + + *(memory+segSize+11) = pc; + *(memory+segSize+12) = registers; + *(memory+segSize+13) = reg_hi; + *(memory+segSize+14) = reg_lo; + *(memory+segSize+15) = segmentStart; + *(memory+segSize+16) = process; + *(memory+segSize+17) = *(registers+REG_GP); + *(memory+segSize+18) = *(registers+REG_SP); + *(memory+segSize+19) = *(registers+REG_K1); + + + restoreKernelState(); + +} + +//------------------------------------------------------------------------ +// MEMORY LAYOUT +// ---------------------------------------------------------------- +// | || | | || || || || +// | OS ||KP| NP| || P1 || P2 || P3 ... PN || +// ---------------------------------------------------------------- +// 0 2MB 4MB 6MB 8MB 32MB +// +// OS - KERNEL +// KP - KERNEL PROCESS +// NP - NEXT PROCESS +// +// ----------------------------------------------------------------------- + + + +// Kernel Process Data Structure : +// +----+------------+ +// | 0 | pc | +// | 1 | reg | +// | 2 | reg_hi | +// | 3 | reg_lo | +// | 4 | segStart | +// | 5 | global p | +// | 6 | stack p | +// +----+------------+ + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ + int pa; + pa = 0; + *(memory+segSize) = pc; + *(memory + segSize+1) = reg; + *(memory + segSize+2) = reg_hi; + *(memory + segSize+3) = reg_lo; + *(memory + segSize+4) = segStart; + *(memory + segSize+5) = gp; + *(memory + segSize+6) = sp; + *(memory + segSize+7) = k1; + +} + +void restoreKernelState(){ + int pa; + pa = 0; + + pc = *(memory + segSize); + registers = *(memory + segSize + 1); + reg_hi = *(memory + segSize + 2); + reg_lo = *(memory + segSize + 3); + segmentStart = 0; + *(registers+REG_GP) = *(memory + segSize + 5); + *(registers+REG_SP) = *(memory + segSize + 6); + *(registers+REG_K1) = *(memory + segSize + 7); + process =0; + pc = pc+4; +} + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- KOS --------------------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +int main_os(){ + int *program; + int *segment; + int i; + int *j; + int *secondSegmentStart; + secondSegmentStart = secondSegmentStart+ 2097152; + + + segSize = 2097152; + segmentStart = 2097152*2; + segPointer =2097152*2; + memory = 0; + j = 2097152; + initInterpreter(); + + readyqueue = 0; + + loadProcess("test.mips",2); + segmentStart = segmentStart + segSize; + + + while(1){ + print("ENTERING KERNEL "); + println(); + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + println(); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + + + + *(secondSegmentStart+10) = 1; //switch + + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); + } + + + exit(0); +} + +void loadProcess(int * name, int id){ + int *segment; + + binaryName = name; + binaryLength = 0; + process =5; + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the second segment! + *(registers+REG_SP) = segSize-4; + + segment = insertSegment(id,segPointer,segSize,segmentTable); + segPointer = segPointer + segSize; //increment segmentPointer + push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),readyqueue); + } + // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- // --------------------- E M U L A T O R --------------------- @@ -3784,6 +4044,8 @@ void fct_syscall() { syscall_getchar(); } else if (*(registers+REG_V0) == SYSCALL_YIELD) { syscall_yield(); + } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { + syscall_switch(); }else { exception_handler(EXCEPTION_UNKNOWNSYSCALL); } @@ -4184,23 +4446,19 @@ void execute() { } //A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH -void run() { - process = pop(readyqueue); +void run(){ + while (1) { fetch(); decode(); pre_debug(); execute(); post_debug(); - - numberofInstructions = numberofInstructions + 1; - if(numberofInstructions > 10){ - //scheduler(); + if(*(memory+segSize+10) == 1){ + syscall_switch(); } - } - - + } void parse_args(int argc, int *argv) { @@ -4210,7 +4468,7 @@ void parse_args(int argc, int *argv) { initMemory(atoi((int*) *(argv+2)) * 1024 * 1024, (int*) *(argv+3)); // initialize stack pointer - //*(registers+REG_SP) = memorySize - 4; + *(registers+REG_SP) = memorySize - 4; memSize = atoi((int*) *(argv+2)) * 1024 * 1024; //ADDED A1 @@ -4225,6 +4483,9 @@ void parse_args(int argc, int *argv) { void up_push(int value) { int vaddr; + print("stack"); + println(); + // allocate space for one value on the stack *(registers+REG_SP) = *(registers+REG_SP) - 4; @@ -4232,6 +4493,7 @@ void up_push(int value) { vaddr = *(registers+REG_SP); // store value + storeMemory(vaddr, value); } @@ -4264,32 +4526,78 @@ void up_copyArguments(int argc, int *argv) { } } -int main_emulator(int argc, int *argv) { - initInterpreter(); +void insertInProcessTable(int *process, int gp, int sp, int *head){ + int *adr; + + adr = malloc(4*4); + + + setProcessTableNext(adr,head); + setProcessTableProcess(adr,process); + setProcessTableGp(adr,gp); + setProcessTableSp(adr,sp); - parse_args(argc, argv); + processTable = adr; - loadBinary(); +} - *(registers+REG_GP) = binaryLength; +void setProcessTableNext(int *processEntry, int *next){ + *processEntry = (int)(next); +} + +void setProcessTableProcess(int *processEntry, int *process){ + *(processEntry+1) = process; +} +void setProcessTableGp(int *processEntry, int gp){ + *(processEntry+2) = gp; +} + +void setProcessTableSp(int *processEntry, int sp){ + *(processEntry+3) = sp; +} + +int* getProcessTableNext(int *processEntry){ + return (int*) *processEntry; +} + +int *getProcessTableProcess(int *processEntry){ + return (int*) *(processEntry+1); +} + +int getProcessTableGp(int *processEntry){ + return *(processEntry+2); +} + +int getProcessTableSp(int *processEntry){ + return *(processEntry+3); +} + + + +int main_emulator(int argc, int *argv) { + + int*segment; + + initInterpreter(); + + initMemory(32 * 1024 * 1024,"selfie.mips"); + binaryLength = 0; + loadBinary(); + + *(registers+REG_GP) = binaryLength; + *(registers+REG_K1) = *(registers+REG_GP); //initialize SP for the firs segment! - *(registers+REG_SP) = segSize - 4; - up_copyArguments(argc-3, argv+3); - - createProcessList(3); //ADDED CREATES LIST WITH 3 PROCESSES - - run(); - exit(0); + } // ---------------------------------------------------------------- -// ---------------------ASSIGNMENT 1 ------------------------------ +// ---------------------ASSIGNMENT 1,2 ------------------------------ // ---------------------------------------------------------------- @@ -4298,6 +4606,14 @@ void memCopy(int *oldMemory, int *newMemory, int length) { i = 0; + //print((int*)"memCopy"); + //println(); + //print(itoa((oldMemory), string_buffer, 10, 0)); + //println(); + //print(itoa((newMemory), string_buffer, 10, 0)); + //println(); + + while (i < length) { *(newMemory+i) = *(oldMemory+i); i = i + 1; @@ -4305,9 +4621,10 @@ void memCopy(int *oldMemory, int *newMemory, int length) { } void createProcessList (int numberoOfProcesses){ - int i = 0; - int pId = 0; - + int i; + int pId; + i = 0; + pId = 2; while(i 3) + main_os(); + else + exit(-1); + } else { exit(-1); } } else { exit(-1); } - } else - // default: compiler - main_compiler(); + } else{ + main_os(); + } } \ No newline at end of file From 32c4d7e3a707e936e59d82cb1211f5b45d251f07 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Sun, 8 Nov 2015 16:47:38 +0100 Subject: [PATCH 20/26] Assignment 3 complete --- selfie.c | 80 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/selfie.c b/selfie.c index fde4020..f6d96e7 100755 --- a/selfie.c +++ b/selfie.c @@ -847,6 +847,7 @@ void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segstart,int void restoreKernelState(); int tlb_debug = 0; void loadProcess(int * name, int id); + // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { @@ -3350,6 +3351,7 @@ int tlb(int vaddr) { } int loadMemory(int vaddr) { + return *(memory + tlb(vaddr)); } @@ -3811,14 +3813,14 @@ void emitSwitch(){ void syscall_switch(){ - print("switching"); - println(); - saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); - if(*(memory+segSize+12) == 0) - registers = malloc(32); - else + + if(*(memory+segSize+12) == 0){ + registers = malloc(32*4); + } + else{ registers = *(memory+segSize+12); + } pc = *(memory+segSize+11); @@ -3829,7 +3831,7 @@ void syscall_switch(){ *(registers+REG_GP) = *(memory+segSize+17); *(registers+REG_SP) = *(memory+segSize+18); *(registers+REG_K1) = *(memory+segSize+19); - + *(memory+segSize+10) = 0; //exit @@ -3901,8 +3903,7 @@ void syscall_yield(){ void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ - int pa; - pa = 0; + *(memory+segSize) = pc; *(memory + segSize+1) = reg; *(memory + segSize+2) = reg_hi; @@ -3915,9 +3916,7 @@ void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int } void restoreKernelState(){ - int pa; - pa = 0; - + process =0; pc = *(memory + segSize); registers = *(memory + segSize + 1); reg_hi = *(memory + segSize + 2); @@ -3926,8 +3925,7 @@ void restoreKernelState(){ *(registers+REG_GP) = *(memory + segSize + 5); *(registers+REG_SP) = *(memory + segSize + 6); *(registers+REG_K1) = *(memory + segSize + 7); - process =0; - pc = pc+4; + } @@ -3943,34 +3941,37 @@ void restoreKernelState(){ int main_os(){ int *program; int *segment; - int i; - int *j; int *secondSegmentStart; - secondSegmentStart = secondSegmentStart+ 2097152; - + secondSegmentStart = 2097152*4; segSize = 2097152; segmentStart = 2097152*2; - segPointer =2097152*2; + + + segPointer =segmentStart; memory = 0; - j = 2097152; initInterpreter(); - readyqueue = 0; - loadProcess("test.mips",2); segmentStart = segmentStart + segSize; - + loadProcess("test.mips",3); + + //BUG becasue it is actually saving kernel process and user process in 4th segment it has to be skipped + segmentStart = segmentStart + segSize+segSize;// + segSize; + segPointer = segPointer + segSize; + + loadProcess("test.mips",4); + segmentStart = segmentStart + segSize; + loadProcess("test.mips",5); + while(1){ print("ENTERING KERNEL "); println(); - + process = pop(readyqueue); segment = getProcessSegPointer(process); - - println(); - + *(secondSegmentStart+11) = getProcessPc(process); *(secondSegmentStart+12) = getProcessRegisters(process); *(secondSegmentStart+13) = getProcessRegHi(process); @@ -3980,16 +3981,18 @@ int main_os(){ *(secondSegmentStart+17) = getProcessGlobalP(process); *(secondSegmentStart+18) = getProcessStackP(process); *(secondSegmentStart+19) = getProcessK1(process); - - - *(secondSegmentStart+10) = 1; //switch + *(secondSegmentStart+10) = 1; //switch + println(); + println(); + + + *(secondSegmentStart+11) = *(secondSegmentStart+11)+4;//increment pc otherwise it always return to the same instruction s push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); } - - exit(0); + exit(0); } void loadProcess(int * name, int id){ @@ -4576,12 +4579,12 @@ int getProcessTableSp(int *processEntry){ int main_emulator(int argc, int *argv) { - int*segment; + int i; initInterpreter(); - initMemory(32 * 1024 * 1024,"selfie.mips"); + initMemory(64 * 1024 * 1024,"selfie.mips"); binaryLength = 0; loadBinary(); @@ -4591,11 +4594,14 @@ int main_emulator(int argc, int *argv) { //initialize SP for the firs segment! *(registers+REG_SP) = segSize - 4; - + run(); + exit(0); } + + // ---------------------------------------------------------------- // ---------------------ASSIGNMENT 1,2 ------------------------------ // ---------------------------------------------------------------- @@ -4653,7 +4659,9 @@ void createProcess(int *head, int pId){ newRegisters = (int*)malloc(32*4); - memCopy(memory+(segSize*2)/4,memory+getSegmentStart(segment)/4,segSize/4); + memCopy(memory,memory+getSegmentStart(segment)/4,segSize/4); + + //memCopy(memory+(segSize*2)/4,memory+getSegmentStart(segment)/4,segSize/4); memCopy(registers,newRegisters,32); From 6ced356a408c284dfd3defae60f12f74ee313312 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Sun, 8 Nov 2015 16:49:46 +0100 Subject: [PATCH 21/26] Assignment3 complete --- makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/makefile b/makefile index b17113b..3fac7c5 100644 --- a/makefile +++ b/makefile @@ -14,5 +14,6 @@ compile: ./selfie -c < selfie.c -mv out selfie.mips + run: ./selfie -m 32 test.mips From 18f7c70d647e2e349cdbe3b2c6235b0830d289f4 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Fri, 13 Nov 2015 00:45:53 +0100 Subject: [PATCH 22/26] Assignment 4 --- selfie.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- test.c | 25 +++++++- 2 files changed, 196 insertions(+), 12 deletions(-) diff --git a/selfie.c b/selfie.c index f6d96e7..ffcf890 100755 --- a/selfie.c +++ b/selfie.c @@ -663,6 +663,15 @@ void syscall_yield(); //ADDED A2 void emitSwitch(); //ADDED A3 void syscall_switch(); //ADDED A3 +void emitLock(); +void syscall_lock(); + +void emitUnlock(); +void syscall_unlock(); + +void emitTrap(); +void syscall_trap(); + // ------------------------ GLOBAL CONSTANTS ----------------------- int SYSCALL_EXIT = 4001; @@ -673,6 +682,9 @@ int SYSCALL_MALLOC = 5001; int SYSCALL_GETCHAR = 5002; int SYSCALL_YIELD = 5003; //ADDED A2 int SYSCALL_SWITCH = 5004; //ADDED A3 +int SYSCALL_LOCK = 5005; //ADDED A4 +int SYSCALL_UNLOCK = 5006; //ADDED A4 +int SYSCALL_TRAP = 6007; //ADDED A4 // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- @@ -848,6 +860,12 @@ void restoreKernelState(); int tlb_debug = 0; void loadProcess(int * name, int id); +// ------------------ ASSIGNMENT 4 ------------------------------- + +void interpretEnvent(); +int processLock = 0; + + // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { @@ -3126,6 +3144,8 @@ int main_compiler() { emitPutchar(); emitYield(); emitSwitch(); + emitLock(); + emitUnlock(); // parser gr_cstar(); @@ -3832,6 +3852,8 @@ void syscall_switch(){ *(registers+REG_SP) = *(memory+segSize+18); *(registers+REG_K1) = *(memory+segSize+19); + numberofInstructions = 0; //reset number of instructions + *(memory+segSize+10) = 0; //exit @@ -3839,7 +3861,7 @@ void syscall_switch(){ void emitYield(){ - createSymbolTableEntry(GLOBAL_TABLE, (int*) "yield", binaryLength, FUNCTION, INT_T, 0); + createSymbolTableEntry(GLOBAL_TABLE, (int*) "sched_yield", binaryLength, FUNCTION, INT_T, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); @@ -3873,6 +3895,57 @@ void syscall_yield(){ restoreKernelState(); } +void emitLock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "lock", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_LOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_lock(){ + *(memory+segSize+20) = 1; //lock flag + + syscall_yield(); + + +} + +void emitUnlock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "unlock", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_UNLOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_unlock(){ + *(memory+segSize+20) = 2; //unlock flag + + syscall_yield(); +} + + //------------------------------------------------------------------------ // MEMORY LAYOUT @@ -3964,11 +4037,34 @@ int main_os(){ segmentStart = segmentStart + segSize; loadProcess("test.mips",5); + *(secondSegmentStart+20) = -1; while(1){ - print("ENTERING KERNEL "); - println(); + interpretEnvent(); + + } + + exit(0); +} + +void interpretEnvent(){ + int *program; + int *segment; + int *secondSegmentStart; + int flag; + + secondSegmentStart = 2097152*4; + flag = *(secondSegmentStart+20); + + //FLAGS + // -1 START, FIRST PROCESS TO BE LOADED + // 1 PROCESS CALLED LOCK + // 2 PROCESS CALLED UNLOCK + // 0 ELSE , LOAD NEW PROCESS + + + if(flag == -1){ process = pop(readyqueue); segment = getProcessSegPointer(process); @@ -3982,19 +4078,66 @@ int main_os(){ *(secondSegmentStart+18) = getProcessStackP(process); *(secondSegmentStart+19) = getProcessK1(process); - + *(secondSegmentStart+20) = 0; + *(secondSegmentStart+10) = 1; //switch - println(); - println(); + } + + if(flag == 1){ + processLock = getProcessId(process); + *(secondSegmentStart+10) = 1; //switch + } + else if(flag == 2){ + if(processLock == getProcessId(process)){ + processLock = 0; + *(secondSegmentStart+20) = 0; + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + + *(secondSegmentStart+10) = 1; //switch + + } + } - *(secondSegmentStart+11) = *(secondSegmentStart+11)+4;//increment pc otherwise it always return to the same instruction s + else{ push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); + + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + + *(secondSegmentStart+10) = 1; //switch + } - exit(0); + + } + void loadProcess(int * name, int id){ int *segment; @@ -4035,25 +4178,38 @@ void fct_syscall() { if (*(registers+REG_V0) == SYSCALL_EXIT) { syscall_exit(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_READ) { syscall_read(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_WRITE) { syscall_write(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_OPEN) { syscall_open(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { syscall_malloc(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { syscall_getchar(); + pc = pc + 4; } else if (*(registers+REG_V0) == SYSCALL_YIELD) { + pc = pc + 4; syscall_yield(); } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { syscall_switch(); + pc = pc + 4; + }else if (*(registers+REG_V0) == SYSCALL_LOCK) { + pc = pc + 4; + syscall_lock(); + }else if (*(registers+REG_V0) == SYSCALL_UNLOCK) { + pc = pc + 4; + syscall_unlock(); }else { exception_handler(EXCEPTION_UNKNOWNSYSCALL); } - pc = pc + 4; } void fct_nop() { @@ -4457,9 +4613,18 @@ void run(){ pre_debug(); execute(); post_debug(); + if(*(memory+segSize+10) == 1){ syscall_switch(); } + if(numberofInstructions == 25){ + if(process !=0){ + syscall_yield(); + + } + } + + numberofInstructions = numberofInstructions + 1; } } diff --git a/test.c b/test.c index beb3549..d46756c 100644 --- a/test.c +++ b/test.c @@ -220,22 +220,41 @@ int main(){ number_buffer = (int*) malloc (10 * 4); init(); + + lock(); + //print("something"); + //putchar(CHAR_LF); + + printString('W','i','t','h',' ','L','o','c','k',' ',0,0,0,0,0,0,0,0,0,0); + putchar(CHAR_LF); - print(itoa(1, string_buffer, 10, 0)); + unlock(); + + //lock(); + //print("somethingElse"); + printString('W','i','t','h','o','u','t',' ','L','o','c','k',' ',0,0,0,0,0,0,0); + + putchar(CHAR_LF); + + + print(itoa(1, string_buffer, 10, 0)); + print(itoa(2, string_buffer, 10, 0)); print(itoa(3, string_buffer, 10, 0)); print(itoa(4, string_buffer, 10, 0)); print(itoa(5, string_buffer, 10, 0)); putchar(CHAR_LF); - yield(); + //sched_yield(); print(itoa(6, string_buffer, 10, 0)); print(itoa(7, string_buffer, 10, 0)); print(itoa(8, string_buffer, 10, 0)); print(itoa(9, string_buffer, 10, 0)); putchar(CHAR_LF); - yield(); + + //switch(); + //sched_yield(); From 7a405412d1334634f86083bf22f5442555f698e5 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 26 Nov 2015 23:23:42 +0100 Subject: [PATCH 23/26] Assignment 5 --- WithPaging.txt | Bin 0 -> 513799 bytes WithoutPaging.txt | Bin 0 -> 555320 bytes selfie.c | 285 ++++++++++++++++++++++++++++++++-------------- test.c | 8 +- 4 files changed, 202 insertions(+), 91 deletions(-) create mode 100644 WithPaging.txt create mode 100644 WithoutPaging.txt diff --git a/WithPaging.txt b/WithPaging.txt new file mode 100644 index 0000000000000000000000000000000000000000..4aadf5f75e671d232599dca45d1c7d5cc5da74a5 GIT binary patch literal 513799 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⋙eQQ8(YP+f}5(2G=r$UfmmGrZ|SWW7l0= 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 N`1ld_mfL+l{STkHcZdK0 literal 0 HcmV?d00001 diff --git a/WithoutPaging.txt b/WithoutPaging.txt new file mode 100644 index 0000000000000000000000000000000000000000..15aec1302a0ca033bcf78f5077f1ecf3a9d123b2 GIT binary patch literal 555320 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

KKhHXi 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⁣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

Iu>mTFAq+3`$JyAVuvQ{M=( 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 "); - - vaddr = vaddr + segmentStart; - print(itoa(vaddr/4, string_buffer, 10, 0)); - println(); - } - else{ - print(itoa(vaddr/4, string_buffer, 10, 0)); - println(); + //if paging is enabled and it is not kernel process + if(pagingFlag == 1){ + if(segmentStart !=0){ + adr = searchPageTable(vaddr); + return adr/4; } } else{ - if(process !=0){ - vaddr = vaddr + segmentStart; + if(tlb_debug == 1){ + if(process !=0){ + print(itoa(vaddr/4, string_buffer, 10, 0)); + + print((int*)" --> "); + + vaddr = vaddr + segmentStart; + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + + else{ + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + } + else{ + if(segmentStart !=0){ + vaddr = vaddr + segmentStart; + } } } - // physical memory is word-addressed for lack of byte-sized data type return vaddr / 4; } +int searchPageTable(int vaddr){ + int i; + int frame; + int offest; + + frame = vaddr/4096; + offest = vaddr%4096; + + if(*(pageTable+frame)==0){ + *(pageTable+frame) = freeList; + memCopy(virtualMemory+(segmentStart+frame*4096)/4, freeList,1024); + freeList = freeList+1024; + + return *(pageTable+frame)-(int)(memory)+offest; + } + else{ + return *(pageTable+frame)-(int)(memory)+offest; + + } + + +} + int loadMemory(int vaddr) { return *(memory + tlb(vaddr)); @@ -3835,26 +3885,33 @@ void syscall_switch(){ saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); - if(*(memory+segSize+12) == 0){ + if(*(memory+communicationSegment+12) == 0){ registers = malloc(32*4); } else{ - registers = *(memory+segSize+12); + registers = *(memory+communicationSegment+12); + } + + if(*(memory+communicationSegment+20) == 0){ + pageTable = malloc(4*1024); //ADDED A5 + } + else{ + pageTable = *(memory+communicationSegment+20); } - pc = *(memory+segSize+11); - reg_hi = *(memory+segSize+13); - reg_lo = *(memory+segSize+14); - segmentStart = *(memory+segSize+15); - process = *(memory+segSize+16); - *(registers+REG_GP) = *(memory+segSize+17); - *(registers+REG_SP) = *(memory+segSize+18); - *(registers+REG_K1) = *(memory+segSize+19); + pc = *(memory+communicationSegment+11); + reg_hi = *(memory+communicationSegment+13); + reg_lo = *(memory+communicationSegment+14); + segmentStart = *(memory+communicationSegment+15); + process = *(memory+communicationSegment+16); + *(registers+REG_GP) = *(memory+communicationSegment+17); + *(registers+REG_SP) = *(memory+communicationSegment+18); + *(registers+REG_K1) = *(memory+communicationSegment+19); numberofInstructions = 0; //reset number of instructions - *(memory+segSize+10) = 0; //exit + *(memory+communicationSegment+10) = 0; //exit } @@ -3881,16 +3938,16 @@ void emitYield(){ void syscall_yield(){ - *(memory+segSize+11) = pc; - *(memory+segSize+12) = registers; - *(memory+segSize+13) = reg_hi; - *(memory+segSize+14) = reg_lo; - *(memory+segSize+15) = segmentStart; - *(memory+segSize+16) = process; - *(memory+segSize+17) = *(registers+REG_GP); - *(memory+segSize+18) = *(registers+REG_SP); - *(memory+segSize+19) = *(registers+REG_K1); - + *(memory+communicationSegment+11) = pc; + *(memory+communicationSegment+12) = registers; + *(memory+communicationSegment+13) = reg_hi; + *(memory+communicationSegment+14) = reg_lo; + *(memory+communicationSegment+15) = segmentStart; + *(memory+communicationSegment+16) = process; + *(memory+communicationSegment+17) = *(registers+REG_GP); + *(memory+communicationSegment+18) = *(registers+REG_SP); + *(memory+communicationSegment+19) = *(registers+REG_K1); + *(memory+communicationSegment+20) = pageTable; restoreKernelState(); @@ -3914,7 +3971,7 @@ void emitLock(){ } void syscall_lock(){ - *(memory+segSize+20) = 1; //lock flag + *(memory+communicationSegment+30) = 1; //lock flag syscall_yield(); @@ -3940,7 +3997,7 @@ void emitUnlock(){ } void syscall_unlock(){ - *(memory+segSize+20) = 2; //unlock flag + *(memory+communicationSegment+30) = 2; //unlock flag syscall_yield(); } @@ -3977,27 +4034,27 @@ void syscall_unlock(){ void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ - *(memory+segSize) = pc; - *(memory + segSize+1) = reg; - *(memory + segSize+2) = reg_hi; - *(memory + segSize+3) = reg_lo; - *(memory + segSize+4) = segStart; - *(memory + segSize+5) = gp; - *(memory + segSize+6) = sp; - *(memory + segSize+7) = k1; + *(memory+communicationSegment) = pc; + *(memory + communicationSegment+1) = reg; + *(memory + communicationSegment+2) = reg_hi; + *(memory + communicationSegment+3) = reg_lo; + *(memory + communicationSegment+4) = segStart; + *(memory + communicationSegment+5) = gp; + *(memory + communicationSegment+6) = sp; + *(memory + communicationSegment+7) = k1; } void restoreKernelState(){ process =0; - pc = *(memory + segSize); - registers = *(memory + segSize + 1); - reg_hi = *(memory + segSize + 2); - reg_lo = *(memory + segSize + 3); + pc = *(memory + communicationSegment); + registers = *(memory + communicationSegment + 1); + reg_hi = *(memory + communicationSegment + 2); + reg_lo = *(memory + communicationSegment + 3); segmentStart = 0; - *(registers+REG_GP) = *(memory + segSize + 5); - *(registers+REG_SP) = *(memory + segSize + 6); - *(registers+REG_K1) = *(memory + segSize + 7); + *(registers+REG_GP) = *(memory + communicationSegment + 5); + *(registers+REG_SP) = *(memory + communicationSegment + 6); + *(registers+REG_K1) = *(memory + communicationSegment + 7); } @@ -4016,28 +4073,29 @@ int main_os(){ int *segment; int *secondSegmentStart; - secondSegmentStart = 2097152*4; - segSize = 2097152; - segmentStart = 2097152*2; - + secondSegmentStart = 4*1024*1024; + segSize = 4*1024*1024; + segmentStart = 4*1024*1024*2; segPointer =segmentStart; memory = 0; initInterpreter(); readyqueue = 0; + loadProcess("test.mips",2); segmentStart = segmentStart + segSize; loadProcess("test.mips",3); - - //BUG becasue it is actually saving kernel process and user process in 4th segment it has to be skipped - segmentStart = segmentStart + segSize+segSize;// + segSize; - segPointer = segPointer + segSize; - + segmentStart = segmentStart + segSize; loadProcess("test.mips",4); segmentStart = segmentStart + segSize; loadProcess("test.mips",5); - *(secondSegmentStart+20) = -1; + + + *(secondSegmentStart+40) = 1;//turn on paging + + *(secondSegmentStart+30) = -1; //set flag to -1 + while(1){ @@ -4054,8 +4112,8 @@ void interpretEnvent(){ int *secondSegmentStart; int flag; - secondSegmentStart = 2097152*4; - flag = *(secondSegmentStart+20); + secondSegmentStart = 4*1024*1024; + flag = *(secondSegmentStart+30); //FLAGS // -1 START, FIRST PROCESS TO BE LOADED @@ -4077,21 +4135,23 @@ void interpretEnvent(){ *(secondSegmentStart+17) = getProcessGlobalP(process); *(secondSegmentStart+18) = getProcessStackP(process); *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); - *(secondSegmentStart+20) = 0; + *(secondSegmentStart+30) = 0; *(secondSegmentStart+10) = 1; //switch } - if(flag == 1){ + else if(flag == 1){ processLock = getProcessId(process); *(secondSegmentStart+10) = 1; //switch } else if(flag == 2){ + if(processLock == getProcessId(process)){ processLock = 0; - *(secondSegmentStart+20) = 0; - push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); + *(secondSegmentStart+30) = 0; + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); process = pop(readyqueue); segment = getProcessSegPointer(process); @@ -4105,6 +4165,7 @@ void interpretEnvent(){ *(secondSegmentStart+17) = getProcessGlobalP(process); *(secondSegmentStart+18) = getProcessStackP(process); *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); *(secondSegmentStart+10) = 1; //switch @@ -4113,7 +4174,7 @@ void interpretEnvent(){ } else{ - push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),readyqueue); + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); process = pop(readyqueue); @@ -4128,6 +4189,7 @@ void interpretEnvent(){ *(secondSegmentStart+17) = getProcessGlobalP(process); *(secondSegmentStart+18) = getProcessStackP(process); *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); *(secondSegmentStart+10) = 1; //switch @@ -4143,7 +4205,7 @@ void loadProcess(int * name, int id){ binaryName = name; binaryLength = 0; - process =5; + //process =5; loadBinary(); *(registers+REG_GP) = binaryLength; @@ -4155,7 +4217,7 @@ void loadProcess(int * name, int id){ segment = insertSegment(id,segPointer,segSize,segmentTable); segPointer = segPointer + segSize; //increment segmentPointer - push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),readyqueue); + push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); } @@ -4198,8 +4260,8 @@ void fct_syscall() { pc = pc + 4; syscall_yield(); } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { - syscall_switch(); pc = pc + 4; + syscall_switch(); }else if (*(registers+REG_V0) == SYSCALL_LOCK) { pc = pc + 4; syscall_lock(); @@ -4614,14 +4676,17 @@ void run(){ execute(); post_debug(); - if(*(memory+segSize+10) == 1){ + if(*(memory+communicationSegment+10) == 1){ syscall_switch(); } - if(numberofInstructions == 25){ - if(process !=0){ - syscall_yield(); + //if(numberofInstructions == 25){ + // if(process !=0){ + // syscall_yield(); - } + // } + //} + if(*(memory+communicationSegment+40) == 1){ + turnOnPaging(); } numberofInstructions = numberofInstructions + 1; @@ -4766,6 +4831,44 @@ int main_emulator(int argc, int *argv) { } +void turnOnPaging(){ + virtualMemory = memory; + memory = malloc(64 * 1024 * 1024); + freeList = (memory + 2097152); //paging after second segment + + memCopy(virtualMemory,memory,2097152); //copy OS segment and communication segment + pagingFlag = 1; + *(memory+communicationSegment+40) = 2; //turn of syscall + +} + +void printMemory(int *adr, int length, int from){ + int i; + int j; + j = 0; + i=from; + print("Memory number, Memory adress, Memory value"); + println(); + while(i Date: Thu, 17 Dec 2015 14:21:06 +0100 Subject: [PATCH 24/26] Assignment 6 --- test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test.c b/test.c index f1f5f7b..2984970 100644 --- a/test.c +++ b/test.c @@ -238,6 +238,7 @@ int main(){ putchar(CHAR_LF); + // print(itoa(1, string_buffer, 10, 0)); From 3fa4fed0ef9c2ecfdb735c839e80f0785e06825c Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Mon, 11 Jan 2016 21:14:21 +0100 Subject: [PATCH 25/26] Assignment 7 --- selfie.c | 181 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 139 insertions(+), 42 deletions(-) diff --git a/selfie.c b/selfie.c index 55d9ab2..b6127ad 100755 --- a/selfie.c +++ b/selfie.c @@ -884,6 +884,18 @@ int *virtualMemory; int freeListPointer = 1; int pagingFlag = 0; //paging turned off +// --------------------ASSIGNEMNT 6+7 ------------------------------- + +int *getPageTableStart(int pID); +int pageFault = 0; +void checkPageFault(int vaddr); +int freeListKernel = 0; +int flag = 0; +int pageTableAdress = 0; +int counterRun = 0; +int loadFlag = 0; + + // ------------------------- INITIALIZATION ------------------------ void initInterpreter() { @@ -3370,6 +3382,10 @@ int tlb(int vaddr) { return adr/4; } } + if(loadFlag == 1){ + adr = searchPageTable(vaddr); + return adr/4; + } else{ if(tlb_debug == 1){ if(process !=0){ @@ -3400,32 +3416,66 @@ int tlb(int vaddr) { int searchPageTable(int vaddr){ int i; int frame; - int offest; + int offset; + int debugFlag = 0; frame = vaddr/4096; - offest = vaddr%4096; + offset = vaddr%4096; if(*(pageTable+frame)==0){ - *(pageTable+frame) = freeList; - memCopy(virtualMemory+(segmentStart+frame*4096)/4, freeList,1024); - freeList = freeList+1024; - - return *(pageTable+frame)-(int)(memory)+offest; + pageFault == 1; + *(pageTable+frame) = freeListKernel;//freeList; + freeListKernel = freeListKernel + 4096; + + return *(pageTable+frame)+offset; } else{ - return *(pageTable+frame)-(int)(memory)+offest; + return *(pageTable+frame)+offset; } } +void checkPageFault (int vaddr){ + int frame; + int offset; + + frame = vaddr/4096; + offset = vaddr%4096; + + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(memory+communicationSegment+41) = vaddr; + } + +} + + int loadMemory(int vaddr) { + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return 0; + } + } + return *(memory + tlb(vaddr)); } void storeMemory(int vaddr, int data) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return; + } + } + *(memory + tlb(vaddr)) = data; } @@ -3894,9 +3944,15 @@ void syscall_switch(){ if(*(memory+communicationSegment+20) == 0){ pageTable = malloc(4*1024); //ADDED A5 + + print("allocating in emulator pageTable "); + print(itoa(process,string_buffer,10,0)); + println(); + + exit(0); } else{ - pageTable = *(memory+communicationSegment+20); + pageTable = memory + (*(memory+communicationSegment+20))/4; } @@ -3947,8 +4003,8 @@ void syscall_yield(){ *(memory+communicationSegment+17) = *(registers+REG_GP); *(memory+communicationSegment+18) = *(registers+REG_SP); *(memory+communicationSegment+19) = *(registers+REG_K1); - *(memory+communicationSegment+20) = pageTable; - + *(memory+communicationSegment+20) = (int)(pageTable)-(int)(memory);//pageTable; + restoreKernelState(); } @@ -4082,6 +4138,9 @@ int main_os(){ initInterpreter(); readyqueue = 0; + loadFlag = 1; + freeListKernel = 2097152; + loadProcess("test.mips",2); segmentStart = segmentStart + segSize; loadProcess("test.mips",3); @@ -4090,8 +4149,8 @@ int main_os(){ segmentStart = segmentStart + segSize; loadProcess("test.mips",5); + loadFlag = 0; - *(secondSegmentStart+40) = 1;//turn on paging *(secondSegmentStart+30) = -1; //set flag to -1 @@ -4112,6 +4171,8 @@ void interpretEnvent(){ int *secondSegmentStart; int flag; + int frame; + secondSegmentStart = 4*1024*1024; flag = *(secondSegmentStart+30); @@ -4119,10 +4180,11 @@ void interpretEnvent(){ // -1 START, FIRST PROCESS TO BE LOADED // 1 PROCESS CALLED LOCK // 2 PROCESS CALLED UNLOCK + // 4 PAGE FAULT // 0 ELSE , LOAD NEW PROCESS - - if(flag == -1){ + if(flag == -1){ + process = pop(readyqueue); segment = getProcessSegPointer(process); @@ -4143,11 +4205,12 @@ void interpretEnvent(){ } else if(flag == 1){ + processLock = getProcessId(process); *(secondSegmentStart+10) = 1; //switch } else if(flag == 2){ - + if(processLock == getProcessId(process)){ processLock = 0; *(secondSegmentStart+30) = 0; @@ -4171,9 +4234,24 @@ void interpretEnvent(){ } + } + else if(flag == 4){ //page fault + + pageTable = *(secondSegmentStart+20); + frame = *(secondSegmentStart+41) / 4096; //adr saved before in *(secondSegmentStart+41) + + *(pageTable+frame) = freeListKernel; + + freeListKernel = freeListKernel + 4096; + + *(secondSegmentStart+30) = 0; //set flag back to 0 + *(secondSegmentStart+10) = 1; //switch + + } else{ + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); @@ -4194,18 +4272,14 @@ void interpretEnvent(){ *(secondSegmentStart+10) = 1; //switch } - - - } - void loadProcess(int * name, int id){ int *segment; binaryName = name; binaryLength = 0; - //process =5; + pageTable = getPageTableStart(id); loadBinary(); *(registers+REG_GP) = binaryLength; @@ -4221,7 +4295,15 @@ void loadProcess(int * name, int id){ } - +int *getPageTableStart(int pId){ + int *pageTableStart; + int *pageTableProcess; + + pageTableStart= 6*1024*1024; // second part of the communication segment + pageTableProcess= pageTableStart + (pId * 1024); + + return pageTableProcess; +} // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- // --------------------- E M U L A T O R --------------------- @@ -4497,7 +4579,9 @@ void op_lw() { *(registers+rt) = loadMemory(vaddr); + if(pageFault == 0){ pc = pc + 4; + } if (debug_disassemble) { printOpcode(opcode); @@ -4539,7 +4623,10 @@ void op_sw() { storeMemory(vaddr, *(registers+rt)); - pc = pc + 4; + if(pageFault == 0){ + pc = pc + 4; + } + //pc = pc + 4; if (debug_disassemble) { printOpcode(opcode); @@ -4671,25 +4758,40 @@ void run(){ while (1) { fetch(); - decode(); - pre_debug(); - execute(); - post_debug(); - - if(*(memory+communicationSegment+10) == 1){ - syscall_switch(); + + if(pageFault == 0){ + decode(); + pre_debug(); + execute(); + post_debug(); + + if(*(memory+communicationSegment+10) == 1){ + syscall_switch(); + } + + + if(*(memory+communicationSegment+40) == 1){ + turnOnPaging(); + } + } - //if(numberofInstructions == 25){ - // if(process !=0){ - // syscall_yield(); - // } - //} - if(*(memory+communicationSegment+40) == 1){ - turnOnPaging(); + if(pageFault == 1){ + pageFault = 0; + numberofInstructions = numberofInstructions + 1; + *(memory+communicationSegment+30) = 4; + syscall_yield(); } + //if(numberofInstructions > 2){ + // if(process !=0){ + // syscall_yield(); + // } + + //} + numberofInstructions = numberofInstructions + 1; + } } @@ -4832,11 +4934,7 @@ int main_emulator(int argc, int *argv) { } void turnOnPaging(){ - virtualMemory = memory; - memory = malloc(64 * 1024 * 1024); - freeList = (memory + 2097152); //paging after second segment - - memCopy(virtualMemory,memory,2097152); //copy OS segment and communication segment + pagingFlag = 1; *(memory+communicationSegment+40) = 2; //turn of syscall @@ -4929,7 +5027,6 @@ void createProcess(int *head, int pId){ newRegisters = (int*)malloc(32*4); memCopy(memory,memory+getSegmentStart(segment)/4,segSize/4); - //memCopy(memory+(segSize*2)/4,memory+getSegmentStart(segment)/4,segSize/4); memCopy(registers,newRegisters,32); From 429dab29f71979ca00023677560212eac34cb5d8 Mon Sep 17 00:00:00 2001 From: Hasic Dalmir Date: Thu, 28 Jan 2016 13:41:33 +0100 Subject: [PATCH 26/26] Assignment8 --- makefile | 4 +- selfie.c | 189 +- selfieProducerConsumer.c | 5518 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 5704 insertions(+), 7 deletions(-) create mode 100755 selfieProducerConsumer.c diff --git a/makefile b/makefile index 3fac7c5..3aa6522 100644 --- a/makefile +++ b/makefile @@ -13,7 +13,9 @@ compile: -touch out ./selfie -c < selfie.c -mv out selfie.mips - + -touch out + ./selfie -c < selfieProducerConsumer.c + -mv out producerConsumer.mips run: ./selfie -m 32 test.mips diff --git a/selfie.c b/selfie.c index b6127ad..1cb922a 100755 --- a/selfie.c +++ b/selfie.c @@ -895,6 +895,21 @@ int pageTableAdress = 0; int counterRun = 0; int loadFlag = 0; +// -------------------ASSIGNMENT 8 -------------------------------- + +int *queue_t; +int *q_tail; +int *q_head; +int mc_bump = 0; +int firstInsertFlag = 1; + +void init_mcqueue(); +void mc_enqueue(int *queue_t, int value); +void mc_decueue(int *queue_t, int * value); +int * init_node(int *queue_t, int value); +void print_mc_queue(int *queue_t); +int CAS(int * node, int old, int new); +void create_thread(int pId); // ------------------------- INITIALIZATION ------------------------ @@ -3967,6 +3982,10 @@ void syscall_switch(){ numberofInstructions = 0; //reset number of instructions + print("Thread: "); + print(itoa(process,string_buffer,10,0)); + println(); + *(memory+communicationSegment+10) = 0; //exit @@ -4141,13 +4160,17 @@ int main_os(){ loadFlag = 1; freeListKernel = 2097152; - loadProcess("test.mips",2); - segmentStart = segmentStart + segSize; - loadProcess("test.mips",3); + loadProcess("producerConsumer.mips",2); + create_thread(3); segmentStart = segmentStart + segSize; - loadProcess("test.mips",4); - segmentStart = segmentStart + segSize; - loadProcess("test.mips",5); + + //loadProcess("test.mips",2); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",3); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",4); + //segmentStart = segmentStart + segSize; + //loadProcess("test.mips",5); loadFlag = 0; @@ -4304,6 +4327,160 @@ int *getPageTableStart(int pId){ return pageTableProcess; } + +void create_thread(int pId){ + int * segment; + + *(registers+REG_SP) = segSize-1024; + segment = insertSegment(pId,segPointer,segSize,segmentTable); + push(memory,0,reg_hi,reg_lo,pc,pId,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + +} + + +//----------------------MICHAEL-SCOTT QUEUE ------------------------ + +void init_mcqueue(){ + int * ab; + int i; + i =0; + queue_t = 3*1024*1024 + 100; + + q_tail = malloc(1*4); + q_head = malloc(1*4); + + *(queue_t) = 0; + *(queue_t+1) = 0; //ref Number + mc_bump = 0; + + *(q_head) = queue_t; + *(q_tail) = queue_t; + +} + + +void mc_enqueue(int * queue_t, int value ){ + int * node; + int * tail; + int tail_count; + int * tail_next; + int tail_next_count; + int l_break; + int next; + + l_break = 0; + node = init_node(queue_t, value); + + while(l_break == 0){ + tail = *(q_tail); + tail_count = *(tail+1); + tail_next = *(tail); + tail_count = *(tail_next+1); + + if(firstInsertFlag == 1){ //fix with shared mememory!!! + firstInsertFlag = 0; + return; + } + + if(tail == *(q_tail)){ + if(tail_next == 0){ + println(); + if(CAS(tail,(int)(tail_next),(int)(node)) == 1){ + l_break = 1; + } + + } + else{ + CAS(q_tail,(int)(tail),(int)(tail_next)); + } + } + + } + CAS(q_tail,(int)(tail),(int)(node)); +} + +void mc_decueue(int * queue_t, int * pvalue){ + int * head; + int * tail; + int * head_next; + int l_break; + + l_break= 0; + + while(l_break == 0){ + head = *(q_head); + tail = *(q_tail); + head_next = *(head); + + if(head == *(q_head)){ + if(head == tail){ + if(*head_next == 0){ + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + l_break =1; //queue empty! + } + CAS(q_tail, tail+12, (int)(*(tail))); + } + else{ + pvalue = head_next + 2; + if(CAS(q_head,(int)(head),(int)(head_next)) == 1){ + l_break = 1; + } + } + } + } + + + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; +} + + + +int * init_node(int * queue_t, int value){ + *(queue_t + mc_bump+1) = *(queue_t + mc_bump+1) + 1; //ref counter + *(queue_t + mc_bump+2) = value; // value + mc_bump = mc_bump + 3; + + return queue_t+(mc_bump-3); +} + +void print_mc_queue(int * queue_t){ + int *queue; + queue= *(q_head); + + print("printing mc queue "); + println(); + + while((int)(queue) !=0){ + print(itoa(*(queue+2),string_buffer,10,0)); + print(" , "); + queue = *(queue); + } + + println(); + +} + +int CAS(int * node, int old, int new){ + + if(*(node) != old){ + return 0; + } + + *(node) = new; + + return 1; +} + + + + + + + // *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ // ----------------------------------------------------------------- // --------------------- E M U L A T O R --------------------- diff --git a/selfieProducerConsumer.c b/selfieProducerConsumer.c new file mode 100755 index 0000000..fc464b7 --- /dev/null +++ b/selfieProducerConsumer.c @@ -0,0 +1,5518 @@ +// Copyright (c) 2015, the Selfie Project authors. All rights reserved. +// Please see the AUTHORS file for details. Use of this source code is +// governed by a BSD license that can be found in the LICENSE file. +// +// Selfie is a project of the Computational Systems Group at the +// Department of Computer Sciences of the University of Salzburg +// in Austria. For further information and code please refer to: +// +// http://selfie.cs.uni-salzburg.at +// +// The Selfie Project provides an educational platform for teaching +// undergraduate and graduate students the design and implementation +// of programming languages and runtime systems. The focus is on the +// construction of compilers, libraries, operating systems, and even +// virtual machine monitors. The common theme is to identify and +// resolve self-reference in systems code which is seen as the key +// challenge when teaching systems engineering, hence the name. +// +// Selfie is a fully self-referential 4k-line C implementation of: +// +// 1. a self-compiling compiler called cstarc that compiles +// a tiny but powerful subset of C called C Star (C*) to +// a tiny but powerful subset of MIPS32 called MIPSter, +// 2. a self-executing emulator called mipster that executes +// MIPSter code including itself when compiled with cstarc, and +// 3. a tiny C* library called libcstar utilized by cstarc and mipster. +// +// Selfie is kept minimal for simplicity and implemented in a single file. +// There is no linker, assembler, or debugger. However, there is minimal +// operating system support in the form of MIPS32 o32 system calls built +// into the emulator. Selfie is meant to be extended in numerous ways. +// +// C* is a tiny Turing-complete subset of C that includes dereferencing +// (the * operator) but excludes data structures, Boolean expressions, and +// many other features. There are only signed 32-bit integers and pointers, +// and character constants for constructing word-aligned strings manually. +// This choice turns out to be helpful for students to understand the +// true role of composite data structures such as arrays and records. +// Bitwise operations are implemented in libcstar using signed integer +// arithmetics helping students gain true understanding of two's complement. +// C* is supposed to be close to the minimum necessary for implementing +// a self-compiling, single-pass, recursive-descent compiler. C* can be +// taught in around two weeks of classes depending on student background. +// +// The compiler can readily be extended to compile features missing in C* +// and to improve performance of the generated code. The compiler generates +// MIPSter executables that can directly be executed by the emulator or +// written to a file in a simple, custom-defined format. Support of standard +// MIPS32 ELF binaries should be easy but remains future work. +// +// MIPSter is a tiny Turing-complete subset of the MIPS32 instruction set. +// It only features arithmetic, memory, and control-flow instructions but +// neither bitwise nor byte-level instructions. MIPSter can be properly +// explained in a single week of classes. +// +// The emulator implements minimal operating system support that is meant +// to be extended by students, first as part of the emulator, and then +// ported to run on top of it, similar to an actual operating system or +// virtual machine monitor. The fact that the emulator can execute itself +// helps exposing the self-referential nature of that challenge. +// +// Selfie is the result of many years of teaching systems engineering. +// The design of the compiler is inspired by the Oberon compiler of +// Professor Niklaus Wirth from ETH Zurich. + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- L I B R A R Y --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ----------------------- LIBRARY FUNCTIONS ----------------------- +// ----------------------------------------------------------------- + +void initLibrary(); + +int twoToThePowerOf(int p); +int leftShift(int n, int b); +int rightShift(int n, int b); + +int stringLength(int *s); +void stringReverse(int *s); +int stringCompare(int *s, int *t); + +int atoi(int *s); +int* itoa(int n, int *s, int b, int a); + +void print(int *s); +void println(); + +void printCharacter(int character); +void printString(int *s); + +void exit(int code); +int* malloc(int size); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int CHAR_EOF = -1; // end of file +int CHAR_TAB = 9; // ASCII code 9 = tabulator +int CHAR_LF = 10; // ASCII code 10 = line feed +int CHAR_CR = 13; // ASCII code 13 = carriage return +int CHAR_SPACE = ' '; +int CHAR_SEMICOLON = ';'; +int CHAR_PLUS = '+'; +int CHAR_DASH = '-'; +int CHAR_ASTERISK = '*'; +int CHAR_HASH = '#'; +int CHAR_SLASH = '/'; +int CHAR_UNDERSCORE = '_'; +int CHAR_EQUAL = '='; +int CHAR_LPARENTHESIS = '('; +int CHAR_RPARENTHESIS = ')'; +int CHAR_LBRACE = '{'; +int CHAR_RBRACE = '}'; +int CHAR_COMMA = ','; +int CHAR_LT = '<'; +int CHAR_GT = '>'; +int CHAR_EXCLAMATION = '!'; +int CHAR_PERCENTAGE = '%'; +int CHAR_SINGLEQUOTE = 39; // ASCII code 39 = ' +int CHAR_DOUBLEQUOTE = '"'; + +int *power_of_two_table; + +int INT_MAX; // maximum numerical value of an integer +int INT_MIN; // minimum numerical value of an integer + +int *string_buffer; + +// ------------------------- INITIALIZATION ------------------------ + +void initLibrary() { + int i; + + power_of_two_table = malloc(31*4); + + *power_of_two_table = 1; // 2^0 + + i = 1; + + while (i < 31) { + *(power_of_two_table + i) = *(power_of_two_table + (i - 1)) * 2; + + i = i + 1; + } + + // computing INT_MAX and INT_MIN without overflows + INT_MAX = (twoToThePowerOf(30) - 1) * 2 + 1; + INT_MIN = -INT_MAX - 1; + + // accommodate 32-bit numbers for itoa + string_buffer = malloc(33); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- C O M P I L E R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- SCANNER ---------------------------- +// ----------------------------------------------------------------- + +void initScanner(); + +void printSymbol(int symbol); +void printLineNumber(int* message); + +void syntaxErrorMessage(int *message); +void syntaxErrorCharacter(int character); + +int isCharacterWhitespace(); +int findNextCharacter(); +int isCharacterLetter(); +int isCharacterDigit(); +int isCharacterLetterOrDigitOrUnderscore(); +int isNotDoubleQuoteOrEOF(); +int identifierStringMatch(int stringIndex); +int identifierOrKeyword(); +int getSymbol(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int SYM_EOF = -1; // end of file +int SYM_IDENTIFIER = 0; // identifier +int SYM_INTEGER = 1; // integer +int SYM_VOID = 2; // VOID +int SYM_INT = 3; // INT +int SYM_SEMICOLON = 4; // ; +int SYM_IF = 5; // IF +int SYM_ELSE = 6; // ELSE +int SYM_PLUS = 7; // + +int SYM_MINUS = 8; // - +int SYM_ASTERISK = 9; // * +int SYM_DIV = 10; // / +int SYM_EQUALITY = 11; // == +int SYM_ASSIGN = 12; // = +int SYM_LPARENTHESIS = 13; // ( +int SYM_RPARENTHESIS = 14; // ) +int SYM_LBRACE = 15; // { +int SYM_RBRACE = 16; // } +int SYM_WHILE = 17; // WHILE +int SYM_RETURN = 18; // RETURN +int SYM_COMMA = 19; // , +int SYM_LT = 20; // < +int SYM_LEQ = 21; // <= +int SYM_GT = 22; // > +int SYM_GEQ = 23; // >= +int SYM_NOTEQ = 24; // != +int SYM_MOD = 25; // % +int SYM_CHARACTER = 26; // character +int SYM_STRING = 27; // string + +int *SYMBOLS; // array of strings representing symbols + +int maxIdentifierLength = 64; // maximum number of characters in an identifier +int maxIntegerLength = 10; // maximum number of characters in an integer +int maxStringLength = 64; // maximum number of characters in a string + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int lineNumber = 1; // current Line Number for error reporting + +int *identifier = (int*) 0; // stores scanned identifier as string +int *integer = (int*) 0; // stores scanned integer as string +int *string = (int*) 0; // stores scanned string + +int constant = 0; // stores numerical value of scanned integer or character + +int initialValue = 0; // stores initial value of variable definitions + +int mayBeINTMINConstant = 0; // support INT_MIN constant +int isINTMINConstant = 0; + +int character; // most recently read character +int symbol; // most recently recognized symbol + +// ------------------------- INITIALIZATION ------------------------ + +void initScanner () { + SYMBOLS = malloc(28*4); + + *(SYMBOLS + SYM_IDENTIFIER) = (int) "identifier"; + *(SYMBOLS + SYM_INTEGER) = (int) "integer"; + *(SYMBOLS + SYM_VOID) = (int) "void"; + *(SYMBOLS + SYM_INT) = (int) "int"; + *(SYMBOLS + SYM_SEMICOLON) = (int) ";"; + *(SYMBOLS + SYM_IF) = (int) "if"; + *(SYMBOLS + SYM_ELSE) = (int) "else"; + *(SYMBOLS + SYM_PLUS) = (int) "+"; + *(SYMBOLS + SYM_MINUS) = (int) "-"; + *(SYMBOLS + SYM_ASTERISK) = (int) "*"; + *(SYMBOLS + SYM_DIV) = (int) "/"; + *(SYMBOLS + SYM_EQUALITY) = (int) "=="; + *(SYMBOLS + SYM_ASSIGN) = (int) "="; + *(SYMBOLS + SYM_LPARENTHESIS) = (int) "("; + *(SYMBOLS + SYM_RPARENTHESIS) = (int) ")"; + *(SYMBOLS + SYM_LBRACE) = (int) "{"; + *(SYMBOLS + SYM_RBRACE) = (int) "}"; + *(SYMBOLS + SYM_WHILE) = (int) "while"; + *(SYMBOLS + SYM_RETURN) = (int) "return"; + *(SYMBOLS + SYM_COMMA) = (int) ","; + *(SYMBOLS + SYM_LT) = (int) "<"; + *(SYMBOLS + SYM_LEQ) = (int) "<="; + *(SYMBOLS + SYM_GT) = (int) ">"; + *(SYMBOLS + SYM_GEQ) = (int) ">="; + *(SYMBOLS + SYM_NOTEQ) = (int) "!="; + *(SYMBOLS + SYM_MOD) = (int) "%"; + *(SYMBOLS + SYM_CHARACTER) = (int) "character"; + *(SYMBOLS + SYM_STRING) = (int) "string"; + + character = getchar(); + symbol = SYM_EOF; +} + +// ----------------------------------------------------------------- +// ------------------------- SYMBOL TABLE -------------------------- +// ----------------------------------------------------------------- + +void createSymbolTableEntry(int which, int *string, int data, int class, int type, int value); +int* getSymbolTableEntry(int *string, int class, int *symbol_table); + +int* getNext(int *entry); +int* getString(int *entry); +int getData(int *entry); +int getClass(int *entry); +int getType(int *entry); +int getValue(int *entry); +int getRegister(int *entry); + +void setNext(int *entry, int *next); +void setString(int *entry, int *identifier); +void setData(int *entry, int data); +void setClass(int *entry, int class); +void setType(int *entry, int type); +void setValue(int *entry, int value); +void setRegister(int *entry, int reg); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +// classes +int VARIABLE = 1; +int FUNCTION = 2; +int STRING = 3; + +// types +int INT_T = 1; +int INTSTAR_T = 2; +int VOID_T = 3; + +// symbol tables +int GLOBAL_TABLE = 1; +int LOCAL_TABLE = 2; + +// ------------------------ GLOBAL VARIABLES ----------------------- + +// table pointers +int *global_symbol_table = (int*) 0; +int *local_symbol_table = (int*) 0; + +// ----------------------------------------------------------------- +// ---------------------------- PARSER ----------------------------- +// ----------------------------------------------------------------- + +void initParser(); + +int isNotRbraceOrEOF(); +int isExpression(); +int isStarOrDivOrModulo(); +int isPlusOrMinus(); +int isComparison(); + +int lookForFactor(); +int lookForStatement(); +int lookForType(); + +void save_temporaries(); +void restore_temporaries(int numberOfTemporaries); + +void syntaxErrorSymbol(int expected); +void syntaxErrorUnexpected(); +int* putType(int type); +void typeWarning(int expected, int found); + +int* getVariable(int *variable); +int load_variable(int *variable); +void load_integer(); +void load_string(); + +int help_call_codegen(int *entry, int *procedure); +void help_procedure_prologue(int localVariables); +void help_procedure_epilogue(int parameters); + +int gr_call(int *procedure); +int gr_factor(); +int gr_term(); +int gr_simpleExpression(); +int gr_expression(); +void gr_while(); +void gr_if(); +void gr_return(int returnType); +void gr_statement(); +int gr_type(); +void gr_variable(int offset); +void gr_initialization(int *name, int offset, int type); +void gr_procedure(int *procedure, int returnType); +void gr_cstar(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int maxBinaryLength; + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int allocatedTemporaries = 0; // number of allocated temporaries + +int allocatedMemory = 0; // number of bytes for global variables and strings + +int mainJumpAddress = 0; // address of main function +int returnBranches = 0; // fixup chain for return statements + +int *currentProcedureName = (int*) 0; // name of currently parsed procedure + +// ------------------------- INITIALIZATION ------------------------ + +void +initParser() { + // set maximum code length in bytes for emitting code + maxBinaryLength = twoToThePowerOf(17); +} + +// ----------------------------------------------------------------- +// ---------------------- MACHINE CODE LIBRARY --------------------- +// ----------------------------------------------------------------- + +void emitLeftShiftBy(int b); +void emitMainEntry(); + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ------------------- I N T E R F A C E ------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void initRegister(); + +void printRegister(int reg); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int REG_ZR = 0; +int REG_AT = 1; +int REG_V0 = 2; +int REG_V1 = 3; +int REG_A0 = 4; +int REG_A1 = 5; +int REG_A2 = 6; +int REG_A3 = 7; +int REG_T0 = 8; +int REG_T1 = 9; +int REG_T2 = 10; +int REG_T3 = 11; +int REG_T4 = 12; +int REG_T5 = 13; +int REG_T6 = 14; +int REG_T7 = 15; +int REG_S0 = 16; +int REG_S1 = 17; +int REG_S2 = 18; +int REG_S3 = 19; +int REG_S4 = 20; +int REG_S5 = 21; +int REG_S6 = 22; +int REG_S7 = 23; +int REG_T8 = 24; +int REG_T9 = 25; +int REG_K0 = 26; +int REG_K1 = 27; +int REG_GP = 28; +int REG_SP = 29; +int REG_FP = 30; +int REG_RA = 31; + +int *REGISTERS; // array of strings representing registers + +// ------------------------- INITIALIZATION ------------------------ + +void initRegister() { + REGISTERS = malloc(32*4); + + *(REGISTERS + REG_ZR) = (int) "$zero"; + *(REGISTERS + REG_AT) = (int) "$at"; + *(REGISTERS + REG_V0) = (int) "$v0"; + *(REGISTERS + REG_V1) = (int) "$v1"; + *(REGISTERS + REG_A0) = (int) "$a0"; + *(REGISTERS + REG_A1) = (int) "$a1"; + *(REGISTERS + REG_A2) = (int) "$a2"; + *(REGISTERS + REG_A3) = (int) "$a3"; + *(REGISTERS + REG_T0) = (int) "$t0"; + *(REGISTERS + REG_T1) = (int) "$t1"; + *(REGISTERS + REG_T2) = (int) "$t2"; + *(REGISTERS + REG_T3) = (int) "$t3"; + *(REGISTERS + REG_T4) = (int) "$t4"; + *(REGISTERS + REG_T5) = (int) "$t5"; + *(REGISTERS + REG_T6) = (int) "$t6"; + *(REGISTERS + REG_T7) = (int) "$t7"; + *(REGISTERS + REG_S0) = (int) "$s0"; + *(REGISTERS + REG_S1) = (int) "$s1"; + *(REGISTERS + REG_S2) = (int) "$s2"; + *(REGISTERS + REG_S3) = (int) "$s3"; + *(REGISTERS + REG_S4) = (int) "$s4"; + *(REGISTERS + REG_S5) = (int) "$s5"; + *(REGISTERS + REG_S6) = (int) "$s6"; + *(REGISTERS + REG_S7) = (int) "$s7"; + *(REGISTERS + REG_T8) = (int) "$t8"; + *(REGISTERS + REG_T9) = (int) "$t9"; + *(REGISTERS + REG_K0) = (int) "$k0"; + *(REGISTERS + REG_K1) = (int) "$k1"; + *(REGISTERS + REG_GP) = (int) "$gp"; + *(REGISTERS + REG_SP) = (int) "$sp"; + *(REGISTERS + REG_FP) = (int) "$fp"; + *(REGISTERS + REG_RA) = (int) "$ra"; +} + +// ----------------------------------------------------------------- +// ---------------------------- ENCODER ---------------------------- +// ----------------------------------------------------------------- + +int encodeRFormat(int opcode, int rs, int rt, int rd, int function); +int encodeIFormat(int opcode, int rs, int rt, int immediate); +int encodeJFormat(int opcode, int instr_index); + +int getOpcode(int instruction); +int getRS(int instruction); +int getRT(int instruction); +int getRD(int instruction); +int getFunction(int instruction); +int getImmediate(int instruction); +int getInstrIndex(int instruction); +int signExtend(int immediate); + +// ----------------------------------------------------------------- +// ---------------------------- DECODER ---------------------------- +// ----------------------------------------------------------------- + +void initDecoder(); + +void printOpcode(int opcode); +void printFunction(int function); + +void decode(); +void decodeRFormat(); +void decodeIFormat(); +void decodeJFormat(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int OP_SPECIAL = 0; +int OP_J = 2; +int OP_JAL = 3; +int OP_BEQ = 4; +int OP_BNE = 5; +int OP_ADDIU = 9; +int OP_LW = 35; +int OP_SW = 43; + +int *OPCODES; // array of strings representing MIPS opcodes + +int FCT_NOP = 0; +int FCT_JR = 8; +int FCT_SYSCALL = 12; +int FCT_MFHI = 16; +int FCT_MFLO = 18; +int FCT_MULTU = 25; +int FCT_DIVU = 27; +int FCT_ADDU = 33; +int FCT_SUBU = 35; +int FCT_SLT = 42; +int FCT_TEQ = 52; + +int *FUNCTIONS; // array of strings representing MIPS functions + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int opcode = 0; +int rs = 0; +int rt = 0; +int rd = 0; +int immediate = 0; +int function = 0; +int instr_index = 0; + +// ------------------------- INITIALIZATION ------------------------ + +void initDecoder() { + OPCODES = malloc(44*4); + + *(OPCODES + OP_SPECIAL) = (int) "nop"; + *(OPCODES + OP_J) = (int) "j"; + *(OPCODES + OP_JAL) = (int) "jal"; + *(OPCODES + OP_BEQ) = (int) "beq"; + *(OPCODES + OP_BNE) = (int) "bne"; + *(OPCODES + OP_ADDIU) = (int) "addiu"; + *(OPCODES + OP_LW) = (int) "lw"; + *(OPCODES + OP_SW) = (int) "sw"; + + FUNCTIONS = malloc(53*4); + + *(FUNCTIONS + FCT_NOP) = (int) "nop"; + *(FUNCTIONS + FCT_JR) = (int) "jr"; + *(FUNCTIONS + FCT_SYSCALL) = (int) "syscall"; + *(FUNCTIONS + FCT_MFHI) = (int) "mfhi"; + *(FUNCTIONS + FCT_MFLO) = (int) "mflo"; + *(FUNCTIONS + FCT_MULTU) = (int) "multu"; + *(FUNCTIONS + FCT_DIVU) = (int) "divu"; + *(FUNCTIONS + FCT_ADDU) = (int) "addu"; + *(FUNCTIONS + FCT_SUBU) = (int) "subu"; + *(FUNCTIONS + FCT_SLT) = (int) "slt"; + *(FUNCTIONS + FCT_TEQ) = (int) "teq"; +} + +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +void initMemory(int size, int* name); + +int tlb(int vaddr); + +int loadMemory(int vaddr); +void storeMemory(int vaddr, int data); + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *memory; +int memorySize; + +int *binaryName; +int binaryLength; + +// ------------------------- INITIALIZATION ------------------------ + +void initMemory(int size, int *name) { + memory = malloc(size); + memorySize = size; + + binaryName = name; + binaryLength = 0; +} + +// ----------------------------------------------------------------- +// ---------------------------- BINARY ----------------------------- +// ----------------------------------------------------------------- + +void emitInstruction(int instruction); +void emitRFormat(int opcode, int rs, int rt, int rd, int function); +void emitIFormat(int opcode, int rs, int rt, int immediate); +void emitJFormat(int opcode, int instr_index); + +void fixup_relative(int fromAddress); +void fixup_absolute(int fromAddress, int toAddress); +void fixlink_absolute(int fromAddress, int toAddress); + +int copyStringToMemory(int *s, int a); + +void emitBinary(); +void loadBinary(); + +// ----------------------------------------------------------------- +// --------------------------- SYSCALLS ---------------------------- +// ----------------------------------------------------------------- + +void emitExit(); +void syscall_exit(); + +void emitRead(); +void syscall_read(); + +void emitWrite(); +void syscall_write(); + +void emitOpen(); +void syscall_open(); + +void emitMalloc(); +void syscall_malloc(); + +void emitGetchar(); +void syscall_getchar(); + +void emitPutchar(); + +void emitYield(); //ADDED A2 +void syscall_yield(); //ADDED A2 + +void emitSwitch(); //ADDED A3 +void syscall_switch(); //ADDED A3 + +void emitLock(); +void syscall_lock(); + +void emitUnlock(); +void syscall_unlock(); + +void emitTrap(); +void syscall_trap(); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int SYSCALL_EXIT = 4001; +int SYSCALL_READ = 4003; +int SYSCALL_WRITE = 4004; +int SYSCALL_OPEN = 4005; +int SYSCALL_MALLOC = 5001; +int SYSCALL_GETCHAR = 5002; +int SYSCALL_YIELD = 5003; //ADDED A2 +int SYSCALL_SWITCH = 5004; //ADDED A3 +int SYSCALL_LOCK = 5005; //ADDED A4 +int SYSCALL_UNLOCK = 5006; //ADDED A4 +int SYSCALL_TRAP = 6007; //ADDED A4 + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ------------------------- INSTRUCTIONS -------------------------- +// ----------------------------------------------------------------- + +void fct_syscall(); +void fct_nop(); +void op_jal(); +void op_j(); +void op_beq(); +void op_bne(); +void op_addiu(); +void fct_jr(); +void op_lui(); +void fct_mfhi(); +void fct_mflo(); +void fct_multu(); +void fct_divu(); +void fct_addu(); +void fct_subu(); +void op_lw(); +void fct_slt(); +void op_sw(); +void op_teq(); + +// ----------------------------------------------------------------- +// -------------------------- INTERPRETER -------------------------- +// ----------------------------------------------------------------- + +void initInterpreter(); + +void printException(int enumber); + +void exception_handler(int enumber); + +void pre_debug(); +void post_debug(); + +void fetch(); +void execute(); +void run(); + +void parse_args(int argc, int *argv); + +void up_push(int value); +int up_malloc(int size); +void up_copyArguments(int argc, int *argv); + +int main_emulator(int argc, int *argv); + +// ------------------------ GLOBAL CONSTANTS ----------------------- + +int debug_load = 0; + +int debug_read = 0; +int debug_write = 0; +int debug_open = 0; +int debug_malloc = 0; +int debug_getchar = 0; + +int debug_registers = 0; +int debug_disassemble = 0; + +int EXCEPTION_SIGNAL = 1; +int EXCEPTION_ADDRESSERROR = 2; +int EXCEPTION_UNKNOWNINSTRUCTION = 3; +int EXCEPTION_HEAPOVERFLOW = 4; +int EXCEPTION_UNKNOWNSYSCALL = 5; +int EXCEPTION_UNKNOWNFUNCTION = 6; + +int *EXCEPTIONS; // array of strings representing exceptions + +// ------------------------ GLOBAL VARIABLES ----------------------- + +int *registers; // general purpose registers + +int pc = 0; // program counter +int ir = 0; // instruction record + +int reg_hi = 0; // hi register for multiplication/division +int reg_lo = 0; // lo register for multiplication/division + + +// -----------------ADDITIONAL METHODS ASSIGNMENT 1 ---------------- + +void push(int *mem, int *reg, int reg_hi, int reg_lo, int pc,int pId,int *segment,int gp, int sp, int k1,int *pageTable, int *head); + +void setPrcosessNext(int *process, int *next); +void setProcessPc(int * process, int pc); +void setProcessMemory(int *process, int *memory); +void setProcessRegisters(int *process, int *registers); +void setProcessRegHi(int *process, int reg_hi); +void setProcessRegLo(int *process, int reg_lo); +void setProcessId (int *process, int pId); +void setProcessSegPointer(int *process, int *segment); +void setProcessGlobalP(int *process, int gp); +void setProcessStackP(int *process, int sp); +void setProcessK1(int *process,int kp); +void setProcessPageTable(int *process, int *pageTable); + + +int* getProcessNext(int *process); +int getProcessPc(int *process); +int* getProcessMemory(int *process); +int* getProcessRegisters(int *process); +int getProcessRegHi(int *process); +int getProcessRegLo(int *process); +int getProcessId(int *process); +int* getProcessSegPointer(int *process); +int getProcessGlobalP(int *process); +int getProcessStackP(int *process); +int getProcessK1(int *process); +int getProcessPageTable(int *process); + + +void createProcessList(int numberoOfProcesses); +void createProcess(int *head, int pId); +void memCopy(int *oldMemory, int *newMemory, int length); + +int * insertSegment(int pId, int start, int size, int *head); + +void setSegmentId(int *segment, int pId); +void setSegmentNext(int *segment, int *next); +void setSegmentStart(int *segment, int start); +void setSegmentSize(int *segment, int size); + +int* getSegmentNext(int *segment); +int getSegmentId(int *segment); +int getSegmentStart(int *segment); +int getSegmentSize(int *segment); + +int* pop(int *head); +void scheduler(); + +// ------------------ADDITIONAL GLOBAL VARIABLES A1 -------------- + +int *readyqueue = 0; +int memSize; +int numberofInstructions = 0; + +// ------------------ADDITIONAL GLOBAL VARIABLES A2--------------- +int *process = 0; +int *segmentTable = 0; +int segPointer = 0; +//int segSize = 2097152; +int segSize = 4194304; +int communicationSegment = 1048576; //adress for the second segment 1048576*4 +int segmentStart = 0; //this variable is initalized when scheduler is called + // so that it doesn't have to be computed every time + // tlb is called + +// ----------------- ASSIGNMENT 3 -------------------------------- +int main_os(); +int interruptOccured = 0; +int processTable = 0; +void insertInProcessTable(int *process, int gp, int sp,int*head); + + +void setProcessTableNext(int *processEntry, int *next); +void setProcessTableProcess(int *processEntry, int *process); +void setProcessTableGp(int *processEntry, int gp); +void setProcessTableSp(int *processEntry, int sp); +int *getProcessTableNext(int *processEntry); +int *getProcessTableProcess(int *processEntry); +int getProcessTableGp(int *processEntry); +int getProcessTableSp(int *processEntry); + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segstart,int gp,int sp,int k1); +void restoreKernelState(); +int tlb_debug = 0; +void loadProcess(int * name, int id); + +// ------------------ ASSIGNMENT 4 ------------------------------- + +void interpretEnvent(); +int processLock = 0; + +// ------------------ ASSIGNMENT 5 ------------------------------- + +void printMemory(int *memory, int length, int from); +int palloc(int adr); +int searchPageTable(int adr); +void turnOnPaging(); +int getNextFrame(); + +int *pageTable = 0; +int *freeList = 0; +int *realMemory; +int *virtualMemory; +int freeListPointer = 1; +int pagingFlag = 0; //paging turned off + +// --------------------ASSIGNEMNT 6+7 ------------------------------- + +int *getPageTableStart(int pID); +int pageFault = 0; +void checkPageFault(int vaddr); +int freeListKernel = 0; +int flag = 0; +int pageTableAdress = 0; +int counterRun = 0; +int loadFlag = 0; + +// -------------------ASSIGNMENT 8 -------------------------------- + +int *queue_t; +int *q_tail; +int *q_head; +void test(); +void init_mcqueue(); +void mc_enqueue(int *queue_t, int value); +void mc_decueue(int *queue_t, int * value); +int * init_node(int *queue_t, int value); +int mc_bump = 0; +void print_mc_queue(int *queue_t); +int CAS(int * node, int old, int new); +int firstInsertFlag = 1; + +// ------------------------- INITIALIZATION ------------------------ + +void initInterpreter() { + EXCEPTIONS = malloc(7*4); + + *(EXCEPTIONS + EXCEPTION_SIGNAL) = (int) "signal"; + *(EXCEPTIONS + EXCEPTION_ADDRESSERROR) = (int) "address error"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNINSTRUCTION) = (int) "unknown instruction"; + *(EXCEPTIONS + EXCEPTION_HEAPOVERFLOW) = (int) "heap overflow"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNSYSCALL) = (int) "unknown syscall"; + *(EXCEPTIONS + EXCEPTION_UNKNOWNFUNCTION) = (int) "unknown function"; + + registers = malloc(32*4); + +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- L I B R A R Y --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ----------------------- LIBRARY FUNCTIONS ----------------------- +// ----------------------------------------------------------------- + +int twoToThePowerOf(int p) { + // assert: 0 <= p < 31 + return *(power_of_two_table + p); +} + +int leftShift(int n, int b) { + // assert: b >= 0; + + if (b > 30) + return 0; + else + return n * twoToThePowerOf(b); +} + +int rightShift(int n, int b) { + // assert: b >= 0 + + if (b > 30) + return 0; + else if (n >= 0) + return n / twoToThePowerOf(b); + else + // works even if n == INT_MIN + return ((n + 1) + INT_MAX) / twoToThePowerOf(b) + + (INT_MAX / twoToThePowerOf(b) + 1); +} + +int getCharacter(int *s, int i) { + // assert: i >= 0 + int a; + + a = i / 4; + + return rightShift(leftShift(*(s + a), 24 - (i % 4) * 8), 24); +} + +int* putCharacter(int *s, int i, int c) { + // assert: i >= 0, all characters are 7-bit + int a; + + a = i / 4; + + *(s + a) = (*(s + a) - leftShift(getCharacter(s, i), (i % 4) * 8)) + leftShift(c, (i % 4) * 8); + + return s; +} + +int stringLength(int *s) { + int i; + + i = 0; + + while (getCharacter(s, i) != 0) + i = i + 1; + + return i; +} + +void stringReverse(int *s) { + int i; + int j; + int tmp; + + i = 0; + j = stringLength(s) - 1; + + while (i < j) { + tmp = getCharacter(s, i); + + putCharacter(s, i, getCharacter(s, j)); + putCharacter(s, j, tmp); + + i = i + 1; + j = j - 1; + } +} + +int stringCompare(int *s, int *t) { + int i; + + i = 0; + + while (1) + if (getCharacter(s, i) == 0) + if (getCharacter(t, i) == 0) + return 1; + else + return 0; + else if (getCharacter(s, i) == getCharacter(t, i)) + i = i + 1; + else + return 0; +} + +int atoi(int *s) { + int i; + int n; + + i = 0; + + n = 0; + + while (getCharacter(s, i) != 0) { + n = n * 10 + getCharacter(s, i) - '0'; + + i = i + 1; + } + + return n; +} + +int* itoa(int n, int *s, int b, int a) { + // assert: b in {2,4,8,10,16} + + int i; + int sign; + + i = 0; + + sign = 0; + + if (n == 0) { + putCharacter(s, 0, '0'); + + i = 1; + } else if (n < 0) { + sign = 1; + + if (b == 10) { + if (n == INT_MIN) { + // rightmost decimal digit of 32-bit INT_MIN + putCharacter(s, 0, '8'); + + n = -(n / 10); + i = i + 1; + } else + n = -n; + } else { + if (n == INT_MIN) { + // rightmost non-decimal digit of INT_MIN + putCharacter(s, 0, '0'); + + n = (rightShift(INT_MIN, 1) / b) * 2; + i = i + 1; + } else + n = rightShift(leftShift(n, 1), 1); + } + } + + while (n != 0) { + if (n % b > 9) + putCharacter(s, i, n % b - 10 + 'A'); + else + putCharacter(s, i, n % b + '0'); + + n = n / b; + i = i + 1; + + if (i == 1) { + if (sign) { + if (b != 10) + n = n + (rightShift(INT_MIN, 1) / b) * 2; + } + } + } + + if (b != 10) { + while (i < a) { + putCharacter(s, i, '0'); // align with zeros + + i = i + 1; + } + + if (b == 16) { + putCharacter(s, i, 'x'); + putCharacter(s, i + 1, '0'); + + i = i + 2; + } + } else if (sign) { + putCharacter(s, i, '-'); + + i = i + 1; + } + + putCharacter(s, i, 0); // null terminated string + + stringReverse(s); + + return s; +} + +void print(int *s) { + int i; + + i = 0; + + while (getCharacter(s, i) != 0) { + putchar(getCharacter(s, i)); + + i = i + 1; + } +} + +void println() { + putchar(CHAR_LF); +} + +void printCharacter(int character) { + putchar(CHAR_SINGLEQUOTE); + + if (character == CHAR_EOF) + print((int*) "end of file"); + else if (character == CHAR_TAB) + print((int*) "tabulator"); + else if (character == CHAR_LF) + print((int*) "line feed"); + else if (character == CHAR_CR) + print((int*) "carriage return"); + else + putchar(character); + + putchar(CHAR_SINGLEQUOTE); +} + +void printString(int *s) { + putchar(CHAR_DOUBLEQUOTE); + + print(s); + + putchar(CHAR_DOUBLEQUOTE); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- C O M P I L E R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- SCANNER ---------------------------- +// ----------------------------------------------------------------- + +void printSymbol(int symbol) { + putchar(CHAR_DOUBLEQUOTE); + + if (symbol == SYM_EOF) + print((int*) "end of file"); + else + print((int*) *(SYMBOLS + symbol)); + + putchar(CHAR_DOUBLEQUOTE); +} + +void printLineNumber(int* message) { + print((int*) "cstarc: "); + print(message); + print((int*) " in line "); + print(itoa(lineNumber, string_buffer, 10, 0)); + print((int*) ": "); +} + +void syntaxErrorMessage(int *message) { + printLineNumber((int*) "error"); + + print(message); + + println(); +} + +void syntaxErrorCharacter(int expected) { + printLineNumber((int*) "error"); + + printCharacter(expected); + print((int*) " expected but "); + + printCharacter(character); + print((int*) " found"); + + println(); +} + +int isCharacterWhitespace() { + if (character == CHAR_SPACE) + return 1; + else if (character == CHAR_TAB) + return 1; + else if (character == CHAR_LF) + return 1; + else if (character == CHAR_CR) + return 1; + else + return 0; +} + +int findNextCharacter() { + int inComment; + + inComment = 0; + + while (1) { + if (inComment) { + character = getchar(); + + if (character == CHAR_LF) + inComment = 0; + else if (character == CHAR_CR) + inComment = 0; + else if (character == CHAR_EOF) + return character; + + } else if (isCharacterWhitespace()) { + if (character == CHAR_LF) + lineNumber = lineNumber + 1; + else if (character == CHAR_CR) + lineNumber = lineNumber + 1; + + character = getchar(); + + } else if (character == CHAR_HASH) { + character = getchar(); + inComment = 1; + + } else if (character == CHAR_SLASH) { + character = getchar(); + if (character == CHAR_SLASH) + inComment = 1; + else { + symbol = SYM_DIV; + return character; + } + + } else + return character; + } +} + +int isCharacterLetter() { + if (character >= 'a') + if (character <= 'z') + return 1; + else + return 0; + else if (character >= 'A') + if (character <= 'Z') + return 1; + else + return 0; + else + return 0; +} + +int isCharacterDigit() { + if (character >= '0') + if (character <= '9') + return 1; + else + return 0; + else + return 0; +} + +int isCharacterLetterOrDigitOrUnderscore() { + if (isCharacterLetter()) + return 1; + else if (isCharacterDigit()) + return 1; + else if (character == CHAR_UNDERSCORE) + return 1; + else + return 0; +} + +int isNotDoubleQuoteOrEOF() { + if (character == CHAR_DOUBLEQUOTE) + return 0; + else if (character == CHAR_EOF) + return 0; + else + return 1; +} + +int identifierStringMatch(int keyword) { + return stringCompare(identifier, (int*) *(SYMBOLS + keyword)); +} + +int identifierOrKeyword() { + if (identifierStringMatch(SYM_WHILE)) + return SYM_WHILE; + if (identifierStringMatch(SYM_IF)) + return SYM_IF; + if (identifierStringMatch(SYM_INT)) + return SYM_INT; + if (identifierStringMatch(SYM_ELSE)) + return SYM_ELSE; + if (identifierStringMatch(SYM_RETURN)) + return SYM_RETURN; + if (identifierStringMatch(SYM_VOID)) + return SYM_VOID; + else + return SYM_IDENTIFIER; +} + +int getSymbol() { + int i; + + symbol = SYM_EOF; + + if (findNextCharacter() == CHAR_EOF) + return SYM_EOF; + else if (symbol == SYM_DIV) + // check here because / was recognized instead of // + return SYM_DIV; + + if (isCharacterLetter()) { + identifier = malloc(maxIdentifierLength + 1); + + i = 0; + + while (isCharacterLetterOrDigitOrUnderscore()) { + if (i >= maxIdentifierLength) { + syntaxErrorMessage((int*) "identifier too long"); + exit(-1); + } + + putCharacter(identifier, i, character); + + i = i + 1; + + character = getchar(); + } + + putCharacter(identifier, i, 0); // null terminated string + + symbol = identifierOrKeyword(); + + } else if (isCharacterDigit()) { + integer = malloc(maxIntegerLength + 1); + + i = 0; + + while (isCharacterDigit()) { + if (i >= maxIntegerLength) { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + + putCharacter(integer, i, character); + + i = i + 1; + + character = getchar(); + } + + putCharacter(integer, i, 0); // null terminated string + + constant = atoi(integer); + + if (constant < 0) { + if (constant == INT_MIN) { + if (mayBeINTMINConstant) + isINTMINConstant = 1; + else { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + } else { + syntaxErrorMessage((int*) "integer out of bound"); + exit(-1); + } + } + + symbol = SYM_INTEGER; + + } else if (character == CHAR_SINGLEQUOTE) { + character = getchar(); + + constant = 0; + + if (character == CHAR_EOF) { + syntaxErrorMessage((int*) "reached end of file looking for a character constant"); + + exit(-1); + } else + constant = character; + + character = getchar(); + + if (character == CHAR_SINGLEQUOTE) + character = getchar(); + else if (character == CHAR_EOF) { + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + exit(-1); + } else + syntaxErrorCharacter(CHAR_SINGLEQUOTE); + + symbol = SYM_CHARACTER; + + } else if (character == CHAR_DOUBLEQUOTE) { + character = getchar(); + + string = malloc(maxStringLength + 1); + + i = 0; + + while (isNotDoubleQuoteOrEOF()) { + if (i >= maxStringLength) { + syntaxErrorMessage((int*) "string too long"); + exit(-1); + } + + putCharacter(string, i, character); + + i = i + 1; + + character = getchar(); + } + + if (character == CHAR_DOUBLEQUOTE) + character = getchar(); + else { + syntaxErrorCharacter(CHAR_DOUBLEQUOTE); + + exit(-1); + } + + putCharacter(string, i, 0); // null terminated string + + symbol = SYM_STRING; + + } else if (character == CHAR_SEMICOLON) { + character = getchar(); + symbol = SYM_SEMICOLON; + + } else if (character == CHAR_PLUS) { + character = getchar(); + symbol = SYM_PLUS; + + } else if (character == CHAR_DASH) { + character = getchar(); + symbol = SYM_MINUS; + + } else if (character == CHAR_ASTERISK) { + character = getchar(); + symbol = SYM_ASTERISK; + + } else if (character == CHAR_EQUAL) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_EQUALITY; + } else + symbol = SYM_ASSIGN; + + } else if (character == CHAR_LPARENTHESIS) { + character = getchar(); + symbol = SYM_LPARENTHESIS; + + } else if (character == CHAR_RPARENTHESIS) { + character = getchar(); + symbol = SYM_RPARENTHESIS; + + } else if (character == CHAR_LBRACE) { + character = getchar(); + symbol = SYM_LBRACE; + + } else if (character == CHAR_RBRACE) { + character = getchar(); + symbol = SYM_RBRACE; + + } else if (character == CHAR_COMMA) { + character = getchar(); + symbol = SYM_COMMA; + + } else if (character == CHAR_LT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_LEQ; + } else + symbol = SYM_LT; + + } else if (character == CHAR_GT) { + character = getchar(); + if (character == CHAR_EQUAL) { + character = getchar(); + symbol = SYM_GEQ; + } else + symbol = SYM_GT; + + } else if (character == CHAR_EXCLAMATION) { + character = getchar(); + if (character == CHAR_EQUAL) + character = getchar(); + else + syntaxErrorCharacter(CHAR_EQUAL); + + symbol = SYM_NOTEQ; + + } else if (character == CHAR_PERCENTAGE) { + character = getchar(); + symbol = SYM_MOD; + + } else { + printLineNumber((int*) "error"); + print((int*) "found unknown character "); + printCharacter(character); + + println(); + + exit(-1); + } + + return symbol; +} + +// ----------------------------------------------------------------- +// ------------------------- SYMBOL TABLE -------------------------- +// ----------------------------------------------------------------- + +void createSymbolTableEntry(int whichTable, int *string, int data, int class, int type, int value) { + int *newEntry; + + // symbol table entry: + // +----+----------+ + // | 0 | next | pointer to next entry + // | 1 | string | identifier string, string constant + // | 2 | data | VARIABLE: offset, FUNCTION: address, STRING: offset + // | 3 | class | VARIABLE, FUNCTION, STRING + // | 4 | type | INT_T, INTSTAR_T, VOID_T + // | 5 | value | VARIABLE: constant value + // | 6 | register | REG_GP, REG_FP + // +----+----------+ + + newEntry = malloc(7 * 4); + + setString(newEntry, string); + setData(newEntry, data); + setClass(newEntry, class); + setType(newEntry, type); + setValue(newEntry, value); + + // create entry at head of symbol table + if (whichTable == GLOBAL_TABLE) { + setRegister(newEntry, REG_GP); + setNext(newEntry, global_symbol_table); + global_symbol_table = newEntry; + } else { + setRegister(newEntry, REG_FP); + setNext(newEntry, local_symbol_table); + local_symbol_table = newEntry; + } +} + +int* getSymbolTableEntry(int *string, int class, int *symbol_table) { + while ((int) symbol_table != 0) { + if (stringCompare(string, getString(symbol_table))) + if (class == getClass(symbol_table)) + return symbol_table; + + // keep looking + symbol_table = getNext(symbol_table); + } + + return (int*) 0; +} + +int* getNext(int *entry) { + // cast only works if size of int and int* is equivalent + return (int*) *entry; +} + +int* getString(int *entry) { + // cast only works if size of int and int* is equivalent + return (int*) *(entry + 1); +} + +int getData(int *entry) { + return *(entry + 2); +} + +int getClass(int *entry) { + return *(entry + 3); +} + +int getType(int *entry) { + return *(entry + 4); +} + +int getValue(int *entry) { + return *(entry + 5); +} + +int getRegister(int *entry) { + return *(entry + 6); +} + +void setNext(int *entry, int *next) { + // cast only works if size of int and int* is equivalent + *entry = (int) next; +} + +void setString(int *entry, int *identifier) { + // cast only works if size of int and int* is equivalent + *(entry + 1) = (int) identifier; +} + +void setData(int *entry, int data) { + *(entry + 2) = data; +} + +void setClass(int *entry, int class) { + *(entry + 3) = class; +} + +void setType(int *entry, int type) { + *(entry + 4) = type; +} + +void setValue(int *entry, int value) { + *(entry + 5) = value; +} + +void setRegister(int *entry, int reg) { + *(entry + 6) = reg; +} + +// ----------------------------------------------------------------- +// ---------------------------- PARSER ----------------------------- +// ----------------------------------------------------------------- + +int isNotRbraceOrEOF() { + if (symbol == SYM_RBRACE) + return 0; + else if(symbol == SYM_EOF) + return 0; + else + return 1; +} + +int isExpression() { + if (symbol == SYM_MINUS) + return 1; + else if (symbol == SYM_LPARENTHESIS) + return 1; + else if (symbol == SYM_IDENTIFIER) + return 1; + else if (symbol == SYM_INTEGER) + return 1; + else if (symbol == SYM_ASTERISK) + return 1; + else if (symbol == SYM_STRING) + return 1; + else if (symbol == SYM_CHARACTER) + return 1; + else + return 0; +} + +int isConstant() { + if (symbol == SYM_INTEGER) + return 1; + else if (symbol == SYM_CHARACTER) + return 1; + else + return 0; +} + +int isStarOrDivOrModulo() { + if (symbol == SYM_ASTERISK) + return 1; + else if (symbol == SYM_DIV) + return 1; + else if (symbol == SYM_MOD) + return 1; + else + return 0; +} + +int isPlusOrMinus() { + if (symbol == SYM_MINUS) + return 1; + else if (symbol == SYM_PLUS) + return 1; + else + return 0; +} + +int isComparison() { + if (symbol == SYM_EQUALITY) + return 1; + else if (symbol == SYM_NOTEQ) + return 1; + else if (symbol == SYM_LT) + return 1; + else if (symbol == SYM_GT) + return 1; + else if (symbol == SYM_LEQ) + return 1; + else if (symbol == SYM_GEQ) + return 1; + else + return 0; +} + +int lookForFactor() { + if (symbol == SYM_LPARENTHESIS) + return 0; + else if (symbol == SYM_ASTERISK) + return 0; + else if (symbol == SYM_IDENTIFIER) + return 0; + else if (symbol == SYM_INTEGER) + return 0; + else if (symbol == SYM_CHARACTER) + return 0; + else if (symbol == SYM_STRING) + return 0; + else if (symbol == SYM_EOF) + return 0; + else + return 1; +} + +int lookForStatement() { + if (symbol == SYM_ASTERISK) + return 0; + else if (symbol == SYM_IDENTIFIER) + return 0; + else if (symbol == SYM_WHILE) + return 0; + else if (symbol == SYM_IF) + return 0; + else if (symbol == SYM_RETURN) + return 0; + else if (symbol == SYM_EOF) + return 0; + else + return 1; +} + +int lookForType() { + if (symbol == SYM_INT) + return 0; + else if (symbol == SYM_VOID) + return 0; + else if (symbol == SYM_EOF) + return 0; + else + return 1; +} + +void talloc() { + // we use registers REG_T0-REG_T9 and REG_S0-REG_S7 for temporaries + if (allocatedTemporaries < REG_T9 - REG_A3) + allocatedTemporaries = allocatedTemporaries + 1; + else { + syntaxErrorMessage((int*) "out of registers"); + + exit(-1); + } +} + +int currentTemporary() { + if (allocatedTemporaries > 0) + return allocatedTemporaries + REG_A3; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int previousTemporary() { + if (allocatedTemporaries > 1) + return currentTemporary() - 1; + else { + syntaxErrorMessage((int*) "illegal register access"); + + exit(-1); + } +} + +int nextTemporary() { + if (allocatedTemporaries < REG_T9 - REG_A3) + return currentTemporary() + 1; + else { + syntaxErrorMessage((int*) "out of registers"); + + exit(-1); + } +} + +void tfree(int numberOfTemporaries) { + allocatedTemporaries = allocatedTemporaries - numberOfTemporaries; + + if (allocatedTemporaries < 0) { + syntaxErrorMessage((int*) "illegal register deallocation"); + + exit(-1); + } +} + +void save_temporaries() { + while (allocatedTemporaries > 0) { + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } +} + +void restore_temporaries(int numberOfTemporaries) { + while (allocatedTemporaries < numberOfTemporaries) { + talloc(); + + emitIFormat(OP_LW, REG_SP, currentTemporary(), 0); + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + } +} + +void syntaxErrorSymbol(int expected) { + printLineNumber((int*) "error"); + + printSymbol(expected); + print((int*) " expected but "); + + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +void syntaxErrorUnexpected() { + printLineNumber((int*) "error"); + + print((int*) "unexpected symbol "); + printSymbol(symbol); + print((int*) " found"); + + println(); +} + +int* putType(int type) { + if (type == INT_T) + return (int*) "int"; + else if (type == INTSTAR_T) + return (int*) "int*"; + else if (type == VOID_T) + return (int*) "void"; + else + return (int*) "unknown"; +} + +void typeWarning(int expected, int found) { + printLineNumber((int*) "warning"); + + print((int*) "type mismatch, "); + + print(putType(expected)); + + print((int*) " expected but "); + + print(putType(found)); + + print((int*) " found"); + + println(); +} + +int* getVariable(int *variable) { + int *entry; + + entry = getSymbolTableEntry(variable, VARIABLE, local_symbol_table); + + if (entry == (int*) 0) { + entry = getSymbolTableEntry(variable, VARIABLE, global_symbol_table); + + if (entry == (int*) 0) { + printLineNumber((int*) "error"); + + print(variable); + + print((int*) " undeclared"); + println(); + + exit(-1); + } + } + + return entry; +} + +int load_variable(int *variable) { + int *entry; + + entry = getVariable(variable); + + talloc(); + + emitIFormat(OP_LW, getRegister(entry), currentTemporary(), getData(entry)); + + return getType(entry); +} + +void load_integer() { + // assert: constant >= 0 or constant == INT_MIN + + talloc(); + + if (constant >= 0) { + if (constant < twoToThePowerOf(15)) + // ADDIU can only load numbers < 2^15 without sign extension + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); + else if (constant < twoToThePowerOf(28)) { + // load 14 msbs of a 28-bit number first + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 14)); + + // shift left by 14 bits + emitLeftShiftBy(14); + + // and finally add 14 lsbs + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 18), 18)); + } else { + // load 14 msbs of a 31-bit number first + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), rightShift(constant, 17)); + + emitLeftShiftBy(14); + + // then add the next 14 msbs + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 15), 18)); + + emitLeftShiftBy(3); + + // and finally add the remaining 3 lsbs + emitIFormat(OP_ADDIU, currentTemporary(), currentTemporary(), rightShift(leftShift(constant, 29), 29)); + } + } else { + // load largest positive 16-bit number with a single bit set: 2^14 + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), twoToThePowerOf(14)); + + // and then multiply 2^14 by 2^14*2^3 to get to 2^31 == INT_MIN + emitLeftShiftBy(14); + emitLeftShiftBy(3); + } +} + +void load_string() { + int l; + + l = stringLength(string) + 1; + + allocatedMemory = allocatedMemory + l; + + if (l % 4 != 0) + allocatedMemory = allocatedMemory + 4 - l % 4; + + createSymbolTableEntry(GLOBAL_TABLE, string, -allocatedMemory, STRING, INTSTAR_T, 0); + + talloc(); + + emitIFormat(OP_ADDIU, REG_GP, currentTemporary(), -allocatedMemory); +} + +int help_call_codegen(int *entry, int *procedure) { + int type; + + if (entry == (int*) 0) { + // CASE 1: function call, no definition, no declaration. + createSymbolTableEntry(GLOBAL_TABLE, procedure, binaryLength, FUNCTION, INT_T, 0); + + emitJFormat(OP_JAL, 0); + + type = INT_T; //assume default return type 'int' + + } else { + type = getType(entry); + + if (getData(entry) == 0) { + // CASE 2: function call, no definition, but declared. + setData(entry, binaryLength); + + emitJFormat(OP_JAL, 0); + } else if (getOpcode(loadMemory(getData(entry))) == OP_JAL) { + // CASE 3: function call, no declaration + emitJFormat(OP_JAL, getData(entry) / 4); + + setData(entry, binaryLength - 8); + } else + // CASE 4: function defined, use the address + emitJFormat(OP_JAL, getData(entry) / 4); + } + + return type; +} + +void help_procedure_prologue(int localVariables) { + // allocate space for return address + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + + // save return address + emitIFormat(OP_SW, REG_SP, REG_RA, 0); + + // allocate space for caller's frame pointer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + + // save caller's frame pointer + emitIFormat(OP_SW, REG_SP, REG_FP, 0); + + // set callee's frame pointer + emitIFormat(OP_ADDIU, REG_SP, REG_FP, 0); + + // allocate space for callee's local variables + if (localVariables != 0) + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4 * localVariables); +} + +void help_procedure_epilogue(int parameters) { + // deallocate space for callee's frame pointer and local variables + emitIFormat(OP_ADDIU, REG_FP, REG_SP, 0); + + // restore caller's frame pointer + emitIFormat(OP_LW, REG_SP, REG_FP, 0); + + // deallocate space for caller's frame pointer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + // restore return address + emitIFormat(OP_LW, REG_SP, REG_RA, 0); + + // deallocate space for return address and parameters + emitIFormat(OP_ADDIU, REG_SP, REG_SP, (parameters + 1) * 4); + + // return + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +int gr_call(int *procedure) { + int *entry; + int numberOfTemporaries; + int type; + + // assert: n = allocatedTemporaries + + entry = getSymbolTableEntry(procedure, FUNCTION, global_symbol_table); + + numberOfTemporaries = allocatedTemporaries; + + save_temporaries(); + + // assert: allocatedTemporaries == 0 + + if (isExpression()) { + gr_expression(); + + // TODO: check if types/number of parameters is correct + // push first parameter onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + + while (symbol == SYM_COMMA) { + getSymbol(); + + gr_expression(); + + // push more parameters onto stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, -4); + emitIFormat(OP_SW, REG_SP, currentTemporary(), 0); + + tfree(1); + } + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); + + type = INT_T; + } + } else if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + type = help_call_codegen(entry, procedure); + } else { + syntaxErrorSymbol(SYM_RPARENTHESIS); + + type = INT_T; + } + + // assert: allocatedTemporaries == 0 + + restore_temporaries(numberOfTemporaries); + + // assert: allocatedTemporaries == n + return type; +} + +int gr_factor() { + int hasCast; + int cast; + int type; + + int *variableOrProcedureName; + + // assert: n = allocatedTemporaries + + hasCast = 0; + + type = INT_T; + + while (lookForFactor()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + // cast: "(" "int" [ "*" ] ")" + if (symbol == SYM_INT) { + hasCast = 1; + + cast = gr_type(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + + // not a cast: "(" expression ")" + } else { + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + + // assert: allocatedTemporaries == n + 1 + + return type; + } + } + + // dereference? + if (symbol == SYM_ASTERISK) { + getSymbol(); + + // ["*"] identifier + if (symbol == SYM_IDENTIFIER) { + type = load_variable(identifier); + + getSymbol(); + + // * "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); + + if (type != INTSTAR_T) + typeWarning(INTSTAR_T, type); + + // dereference + emitIFormat(OP_LW, currentTemporary(), currentTemporary(), 0); + + type = INT_T; + + // identifier? + } else if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + // function call: identifier "(" ... ")" + type = gr_call(variableOrProcedureName); + + talloc(); + + emitIFormat(OP_ADDIU, REG_V0, currentTemporary(), 0); + } else + // variable access: identifier + type = load_variable(variableOrProcedureName); + + // integer? + } else if (symbol == SYM_INTEGER) { + load_integer(); + + getSymbol(); + + type = INT_T; + + // character? + } else if (symbol == SYM_CHARACTER) { + talloc(); + + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), constant); + + getSymbol(); + + type = INT_T; + + // string? + } else if (symbol == SYM_STRING) { + load_string(); + + getSymbol(); + + type = INTSTAR_T; + + // "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + type = gr_expression(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorUnexpected(); + + // assert: allocatedTemporaries == n + 1 + + if (hasCast) + return cast; + else + return type; +} + +int gr_term() { + int ltype; + int operatorSymbol; + int rtype; + + // assert: n = allocatedTemporaries + + ltype = gr_factor(); + + // assert: allocatedTemporaries == n + 1 + + // * / or % ? + while (isStarOrDivOrModulo()) { + operatorSymbol = symbol; + + getSymbol(); + + rtype = gr_factor(); + + // assert: allocatedTemporaries == n + 2 + + if (ltype != rtype) + typeWarning(ltype, rtype); + + if (operatorSymbol == SYM_ASTERISK) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + + } else if (operatorSymbol == SYM_DIV) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFLO); + + } else if (operatorSymbol == SYM_MOD) { + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), 0, FCT_DIVU); + emitRFormat(OP_SPECIAL, 0, 0, previousTemporary(), FCT_MFHI); + } + + tfree(1); + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +int gr_simpleExpression() { + int sign; + int ltype; + int operatorSymbol; + int rtype; + + // assert: n = allocatedTemporaries + + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; + + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; + + ltype = gr_term(); + + // assert: allocatedTemporaries == n + 1 + + if (sign == 1) { + if (ltype != INT_T) { + typeWarning(INT_T, ltype); + + ltype = INT_T; + } + + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), currentTemporary(), FCT_SUBU); + } + + // + or -? + while (isPlusOrMinus()) { + operatorSymbol = symbol; + + getSymbol(); + + rtype = gr_term(); + + // assert: allocatedTemporaries == n + 2 + + if (operatorSymbol == SYM_PLUS) { + if (ltype == INTSTAR_T) { + if (rtype == INT_T) + // pointer arithmetic: factor of 2^2 of integer operand + emitLeftShiftBy(2); + } else if (rtype == INTSTAR_T) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_ADDU); + + } else if (operatorSymbol == SYM_MINUS) { + if (ltype != rtype) + typeWarning(ltype, rtype); + + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); + } + + tfree(1); + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +int gr_expression() { + int ltype; + int operatorSymbol; + int rtype; + + // assert: n = allocatedTemporaries + + ltype = gr_simpleExpression(); + + // assert: allocatedTemporaries == n + 1 + + //optional: ==, !=, <, >, <=, >= simpleExpression + if (isComparison()) { + operatorSymbol = symbol; + + getSymbol(); + + rtype = gr_simpleExpression(); + + // assert: allocatedTemporaries == n + 2 + + if (ltype != rtype) + typeWarning(ltype, rtype); + + if (operatorSymbol == SYM_EQUALITY) { + // subtract, if result = 0 then 1, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); + + tfree(1); + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); + + } else if (operatorSymbol == SYM_NOTEQ) { + // subtract, if result = 0 then 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SUBU); + + tfree(1); + + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); + + } else if (operatorSymbol == SYM_LT) { + // set to 1 if a < b, else 0 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + } else if (operatorSymbol == SYM_GT) { + // set to 1 if b < a, else 0 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + } else if (operatorSymbol == SYM_LEQ) { + // if b < a set 0, else 1 + emitRFormat(OP_SPECIAL, currentTemporary(), previousTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + + } else if (operatorSymbol == SYM_GEQ) { + // if a < b set 0, else 1 + emitRFormat(OP_SPECIAL, previousTemporary(), currentTemporary(), previousTemporary(), FCT_SLT); + + tfree(1); + + emitIFormat(OP_BNE, REG_ZR, currentTemporary(), 4); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 1); + emitIFormat(OP_BEQ, REG_ZR, REG_ZR, 2); + emitIFormat(OP_ADDIU, REG_ZR, currentTemporary(), 0); + } + } + + // assert: allocatedTemporaries == n + 1 + + return ltype; +} + +void gr_while() { + int brBackToWhile; + int brForwardToEnd; + + // assert: allocatedTemporaries == 0 + + brBackToWhile = binaryLength; + + brForwardToEnd = 0; + + // while ( expression ) + if (symbol == SYM_WHILE) { + getSymbol(); + + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + gr_expression(); + + // do not know where to branch, fixup later + brForwardToEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + } + // only one statement without {} + else + gr_statement(); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } else + syntaxErrorSymbol(SYM_WHILE); + + // unconditional branch to beginning of while + emitIFormat(OP_BEQ, 0, 0, (brBackToWhile - binaryLength - 4) / 4); + + if (brForwardToEnd != 0) + // first instruction after loop comes here + // now we have our address for the conditional jump from above + fixup_relative(brForwardToEnd); + + // assert: allocatedTemporaries == 0 +} + +void gr_if() { + int brForwardToElseOrEnd; + int brForwardToEnd; + + // assert: allocatedTemporaries == 0 + + // if ( expression ) + if (symbol == SYM_IF) { + getSymbol(); + + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + gr_expression(); + + // if the "if" case is not true, we jump to "else" (if provided) + brForwardToElseOrEnd = binaryLength; + + emitIFormat(OP_BEQ, REG_ZR, currentTemporary(), 0); + + tfree(1); + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + } + // only one statement without {} + else + gr_statement(); + + //optional: else + if (symbol == SYM_ELSE) { + getSymbol(); + + // if the "if" case was true, we jump to the end + brForwardToEnd = binaryLength; + emitIFormat(OP_BEQ, 0, 0, 0); + + // if the "if" case was not true, we jump here + fixup_relative(brForwardToElseOrEnd); + + // zero or more statements: { statement } + if (symbol == SYM_LBRACE) { + getSymbol(); + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + + // only one statement without {} + } else + gr_statement(); + + // if the "if" case was true, we jump here + fixup_relative(brForwardToEnd); + } else + // if the "if" case was not true, we jump here + fixup_relative(brForwardToElseOrEnd); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } else + syntaxErrorSymbol(SYM_IF); + + // assert: allocatedTemporaries == 0 +} + +void gr_return(int returnType) { + int type; + + // assert: allocatedTemporaries == 0 + + if (symbol == SYM_RETURN) + getSymbol(); + else + syntaxErrorSymbol(SYM_RETURN); + + // optional: expression + if (symbol != SYM_SEMICOLON) { + type = gr_expression(); + + if (returnType == VOID_T) + typeWarning(type, returnType); + else if (type != returnType) + typeWarning(returnType, type); + + // save value of expression in return register + emitRFormat(OP_SPECIAL, REG_ZR, currentTemporary(), REG_V0, FCT_ADDU); + + tfree(1); + } + + // unconditional branch to procedure epilogue + // maintain fixup chain for later fixup + emitJFormat(OP_J, returnBranches / 4); + + // new head of fixup chain + // offest is 8 rather than 4 bytes because of delay slot NOP + returnBranches = binaryLength - 8; + + // assert: allocatedTemporaries == 0 +} + +void gr_statement() { + int ltype; + int rtype; + int *variableOrProcedureName; + int *entry; + + // assert: allocatedTemporaries == 0; + + while (lookForStatement()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // ["*"] + if (symbol == SYM_ASTERISK) { + getSymbol(); + + // "*" identifier + if (symbol == SYM_IDENTIFIER) { + ltype = load_variable(identifier); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + + getSymbol(); + + // "*" identifier "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); + + rtype = gr_expression(); + + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + tfree(2); + } else + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + + // "*" "(" expression ")" + } else if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + ltype = gr_expression(); + + if (ltype != INTSTAR_T) + typeWarning(INTSTAR_T, ltype); + + if (symbol == SYM_RPARENTHESIS) { + getSymbol(); + + // "*" "(" expression ")" "=" + if (symbol == SYM_ASSIGN) { + getSymbol(); + + rtype = gr_expression(); + + if (rtype != INT_T) + typeWarning(INT_T, rtype); + + emitIFormat(OP_SW, previousTemporary(), currentTemporary(), 0); + + tfree(2); + } else + syntaxErrorSymbol(SYM_ASSIGN); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + } + // identifier "=" expression | call + else if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + // call + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + gr_call(variableOrProcedureName); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + + // identifier = expression + } else if (symbol == SYM_ASSIGN) { + entry = getVariable(variableOrProcedureName); + + ltype = getType(entry); + + getSymbol(); + + rtype = gr_expression(); + + if (ltype != rtype) + typeWarning(ltype, rtype); + + emitIFormat(OP_SW, getRegister(entry), currentTemporary(), getData(entry)); + + tfree(1); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorUnexpected(); + } + // while statement? + else if (symbol == SYM_WHILE) { + gr_while(); + } + // if statement? + else if (symbol == SYM_IF) { + gr_if(); + } + // return statement? + else if (symbol == SYM_RETURN) { + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + gr_return(getType(entry)); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } +} + +int gr_type() { + int type; + + type = INT_T; + + if (symbol == SYM_INT) { + getSymbol(); + + if (symbol == SYM_ASTERISK) { + type = INTSTAR_T; + + getSymbol(); + } + } else + syntaxErrorSymbol(SYM_INT); + + return type; +} + +void gr_variable(int offset) { + int type; + + type = gr_type(); + + if (symbol == SYM_IDENTIFIER) { + createSymbolTableEntry(LOCAL_TABLE, identifier, offset, VARIABLE, type, 0); + + getSymbol(); + } else { + syntaxErrorSymbol(SYM_IDENTIFIER); + + createSymbolTableEntry(LOCAL_TABLE, (int*) "missing variable name", offset, VARIABLE, type, 0); + } +} + +void gr_initialization(int *name, int offset, int type) { + int hasCast; + int cast; + int sign; + + initialValue = 0; + + hasCast = 0; + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else if (symbol == SYM_ASSIGN) { + getSymbol(); + + // optional cast: [ cast ] + if (symbol == SYM_LPARENTHESIS) { + hasCast = 1; + + getSymbol(); + + cast = gr_type(); + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } + + // optional: - + if (symbol == SYM_MINUS) { + sign = 1; + + mayBeINTMINConstant = 1; + isINTMINConstant = 0; + + getSymbol(); + + mayBeINTMINConstant = 0; + + if (isINTMINConstant) { + isINTMINConstant = 0; + + // avoids 0-INT_MIN overflow when bootstrapping + // even though 0-INT_MIN == INT_MIN + sign = 0; + } + } else + sign = 0; + + if (isConstant()) { + initialValue = constant; + + getSymbol(); + + if (sign == 1) + initialValue = -initialValue; + } else + syntaxErrorUnexpected(); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } else + syntaxErrorUnexpected(); + + if (hasCast) { + if (type != cast) + typeWarning(type, cast); + } else if (type != INT_T) + typeWarning(type, INT_T); + + createSymbolTableEntry(GLOBAL_TABLE, name, offset, VARIABLE, type, initialValue); +} + +void gr_procedure(int *procedure, int returnType) { + int numberOfParameters; + int parameters; + int localVariables; + int functionStart; + int *entry; + + currentProcedureName = procedure; + + numberOfParameters = 0; + + // ( variable , variable ) ; + if (symbol == SYM_LPARENTHESIS) { + getSymbol(); + + if (symbol != SYM_RPARENTHESIS) { + gr_variable(0); + + numberOfParameters = 1; + + while (symbol == SYM_COMMA) { + getSymbol(); + + gr_variable(0); + + numberOfParameters = numberOfParameters + 1; + } + + entry = local_symbol_table; + + parameters = 0; + + while (parameters < numberOfParameters) { + // 8 bytes offset to skip frame pointer and link + setData(entry, parameters * 4 + 8); + + parameters = parameters + 1; + entry = getNext(entry); + } + + if (symbol == SYM_RPARENTHESIS) + getSymbol(); + else + syntaxErrorSymbol(SYM_RPARENTHESIS); + } else + getSymbol(); + } else + syntaxErrorSymbol(SYM_LPARENTHESIS); + + if (symbol == SYM_SEMICOLON) { + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, 0, FUNCTION, returnType, 0); + + getSymbol(); + + // ( variable, variable ) { variable; variable; statement } + } else if (symbol == SYM_LBRACE) { + functionStart = binaryLength; + + getSymbol(); + + entry = getSymbolTableEntry(currentProcedureName, FUNCTION, global_symbol_table); + + if (entry == (int*) 0) + createSymbolTableEntry(GLOBAL_TABLE, currentProcedureName, binaryLength, FUNCTION, returnType, 0); + else { + if (getData(entry) != 0) { + if (getOpcode(loadMemory(getData(entry))) == OP_JAL) + fixlink_absolute(getData(entry), functionStart); + else { + printLineNumber((int*) "error"); + + print((int*) "multiple definitions of "); + + print(currentProcedureName); + + println(); + } + } + + setData(entry, functionStart); + + if (getType(entry) != returnType) + typeWarning(getType(entry), returnType); + + setType(entry, returnType); + } + + localVariables = 0; + + while (symbol == SYM_INT) { + localVariables = localVariables + 1; + + gr_variable(-4 * localVariables); + + if (symbol == SYM_SEMICOLON) + getSymbol(); + else + syntaxErrorSymbol(SYM_SEMICOLON); + } + + help_procedure_prologue(localVariables); + + // create a fixup chain for return statements + returnBranches = 0; + + while (isNotRbraceOrEOF()) + gr_statement(); + + if (symbol == SYM_RBRACE) + getSymbol(); + else { + syntaxErrorSymbol(SYM_RBRACE); + + exit(-1); + } + + fixlink_absolute(returnBranches, binaryLength); + + returnBranches = 0; + + help_procedure_epilogue(numberOfParameters); + + } else + syntaxErrorUnexpected(); + + local_symbol_table = (int*) 0; + + // assert: allocatedTemporaries == 0 +} + +void gr_cstar() { + int type; + int *variableOrProcedureName; + + while (symbol != SYM_EOF) { + while (lookForType()) { + syntaxErrorUnexpected(); + + if (symbol == SYM_EOF) + exit(-1); + else + getSymbol(); + } + + // void identifier procedure + if (symbol == SYM_VOID) { + type = VOID_T; + + getSymbol(); + + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + gr_procedure(variableOrProcedureName, type); + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } else { + type = gr_type(); + + if (symbol == SYM_IDENTIFIER) { + variableOrProcedureName = identifier; + + getSymbol(); + + // type identifier "(" procedure declaration or definition + if (symbol == SYM_LPARENTHESIS) + gr_procedure(variableOrProcedureName, type); + else { + allocatedMemory = allocatedMemory + 4; + + // type identifier ";" global variable declaration + if (symbol == SYM_SEMICOLON) { + getSymbol(); + + createSymbolTableEntry(GLOBAL_TABLE, variableOrProcedureName, -allocatedMemory, VARIABLE, type, 0); + + // type identifier "=" global variable definition + } else + gr_initialization(variableOrProcedureName, -allocatedMemory, type); + } + } else + syntaxErrorSymbol(SYM_IDENTIFIER); + } + } +} + +// ----------------------------------------------------------------- +// ------------------------ MACHINE CODE LIBRARY ------------------- +// ----------------------------------------------------------------- + +void emitLeftShiftBy(int b) { + // assert: 0 <= b < 15 + + // load multiplication factor less than 2^15 to avoid sign extension + emitIFormat(OP_ADDIU, REG_ZR, nextTemporary(), twoToThePowerOf(b)); + emitRFormat(OP_SPECIAL, currentTemporary(), nextTemporary(), 0, FCT_MULTU); + emitRFormat(OP_SPECIAL, 0, 0, currentTemporary(), FCT_MFLO); +} + +void emitMainEntry() { + // instruction at address zero cannot be fixed up + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); + + createSymbolTableEntry(GLOBAL_TABLE, (int*) "main", binaryLength, FUNCTION, INT_T, 0); + + mainJumpAddress = binaryLength; + + emitJFormat(OP_JAL, 0); +} + +// ----------------------------------------------------------------- +// ----------------------------- MAIN ------------------------------ +// ----------------------------------------------------------------- + +int main_compiler() { + initScanner(); + initParser(); + + // memory in bytes and executable file name "out" + initMemory(maxBinaryLength, (int*) "out"); + + getSymbol(); + + // jump to main + emitMainEntry(); + + // library: + // exit must be first to exit main + // if exit call in main is missing + emitExit(); + emitRead(); + emitWrite(); + emitOpen(); + emitMalloc(); + emitGetchar(); + emitPutchar(); + emitYield(); + emitSwitch(); + emitLock(); + emitUnlock(); + + // parser + gr_cstar(); + + if (getInstrIndex(loadMemory(mainJumpAddress)) != 0) + emitBinary(); + else { + print((int*) "cstarc: main function missing"); + println(); + } + + exit(0); +} + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// ------------------- I N T E R F A C E ------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ---------------------------- REGISTER --------------------------- +// ----------------------------------------------------------------- + +void printRegister(int reg) { + print((int*) *(REGISTERS + reg)); +} + +// ----------------------------------------------------------------- +// ---------------------------- ENCODER ---------------------------- +// ----------------------------------------------------------------- + +// ----------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+-----+-----+------+ +// |opcode| rs | rt | rd |00000|fction| +// +------+-----+-----+-----+-----+------+ +// 6 5 5 5 5 6 +int encodeRFormat(int opcode, int rs, int rt, int rd, int function) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= rs < 2^5 + // assert: 0 <= rt < 2^5 + // assert: 0 <= rd < 2^5 + // assert: 0 <= function < 2^6 + return leftShift(leftShift(leftShift(leftShift(opcode, 5) + rs, 5) + rt, 5) + rd, 11) + function; +} + +// ----------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+----------------+ +// |opcode| rs | rt | immediate | +// +------+-----+-----+----------------+ +// 6 5 5 16 +int encodeIFormat(int opcode, int rs, int rt, int immediate) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= rs < 2^5 + // assert: 0 <= rt < 2^5 + // assert: -2^15 <= immediate < 2^15 + if (immediate < 0) + // convert from 32-bit to 16-bit two's complement + immediate = immediate + twoToThePowerOf(16); + + return leftShift(leftShift(leftShift(opcode, 5) + rs, 5) + rt, 16) + immediate; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+--------------------------+ +// |opcode| instr_index | +// +------+--------------------------+ +// 6 26 +int encodeJFormat(int opcode, int instr_index) { + // assert: 0 <= opcode < 2^6 + // assert: 0 <= immediate < 2^26 + return leftShift(opcode, 26) + instr_index; +} + +int getOpcode(int instruction) { + return rightShift(instruction, 26); +} + +int getRS(int instruction) { + return rightShift(leftShift(instruction, 6), 27); +} + +int getRT(int instruction) { + return rightShift(leftShift(instruction, 11), 27); +} + +int getRD(int instruction) { + return rightShift(leftShift(instruction, 16), 27); +} + +int getFunction(int instruction) { + return rightShift(leftShift(instruction, 26), 26); +} + +int getImmediate(int instruction) { + return rightShift(leftShift(instruction, 16), 16); +} + +int getInstrIndex(int instruction) { + return rightShift(leftShift(instruction, 6), 6); +} + +int signExtend(int immediate) { + // sign-extend from 16-bit to 32-bit two's complement + if (immediate < twoToThePowerOf(15)) + return immediate; + else + return immediate - twoToThePowerOf(16); +} + +// ----------------------------------------------------------------- +// ---------------------------- DECODER ---------------------------- +// ----------------------------------------------------------------- + +void printOpcode(int opcode) { + print((int*) *(OPCODES + opcode)); +} + +void printFunction(int function) { + print((int*) *(FUNCTIONS + function)); +} + +void decode() { + opcode = getOpcode(ir); + + if (opcode == 0) + decodeRFormat(); + else if (opcode == OP_JAL) + decodeJFormat(); + else if (opcode == OP_J) + decodeJFormat(); + else + decodeIFormat(); +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+-----+-----+------+ +// |opcode| rs | rt | rd |00000|fction| +// +------+-----+-----+-----+-----+------+ +// 6 5 5 5 5 6 +void decodeRFormat() { + rs = getRS(ir); + rt = getRT(ir); + rd = getRD(ir); + immediate = 0; + function = getFunction(ir); + instr_index = 0; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+-----+-----+----------------+ +// |opcode| rs | rt | immediate | +// +------+-----+-----+----------------+ +// 6 5 5 16 +void decodeIFormat() { + rs = getRS(ir); + rt = getRT(ir); + rd = 0; + immediate = getImmediate(ir); + function = 0; + instr_index = 0; +} + +// -------------------------------------------------------------- +// 32 bit +// +// +------+--------------------------+ +// |opcode| instr_index | +// +------+--------------------------+ +// 6 26 +void decodeJFormat() { + rs = 0; + rt = 0; + rd = 0; + immediate = 0; + function = 0; + instr_index = getInstrIndex(ir); +} + +// ----------------------------------------------------------------- +// ---------------------------- MEMORY ----------------------------- +// ----------------------------------------------------------------- + +int tlb(int vaddr) { + int adr; + + if (vaddr % 4 != 0) + exception_handler(EXCEPTION_ADDRESSERROR); + + //if paging is enabled and it is not kernel process + if(pagingFlag == 1){ + if(segmentStart !=0){ + adr = searchPageTable(vaddr); + return adr/4; + } + } + if(loadFlag == 1){ + adr = searchPageTable(vaddr); + return adr/4; + } + else{ + if(tlb_debug == 1){ + if(process !=0){ + print(itoa(vaddr/4, string_buffer, 10, 0)); + + print((int*)" --> "); + + vaddr = vaddr + segmentStart; + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + + else{ + print(itoa(vaddr/4, string_buffer, 10, 0)); + println(); + } + } + else{ + if(segmentStart !=0){ + vaddr = vaddr + segmentStart; + } + } + } + // physical memory is word-addressed for lack of byte-sized data type + return vaddr / 4; +} + +int searchPageTable(int vaddr){ + int i; + int frame; + int offset; + int debugFlag; + debugFlag= 0; + + frame = vaddr/4096; + offset = vaddr%4096; + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(pageTable+frame) = freeListKernel;//freeList; + freeListKernel = freeListKernel + 4096; + + return *(pageTable+frame)+offset; + } + else{ + return *(pageTable+frame)+offset; + + } + + +} + +void checkPageFault (int vaddr){ + int frame; + int offset; + + frame = vaddr/4096; + offset = vaddr%4096; + + + if(*(pageTable+frame)==0){ + pageFault = 1; + *(memory+communicationSegment+41) = vaddr; + } + +} + + +int loadMemory(int vaddr) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return 0; + } + } + + return *(memory + tlb(vaddr)); +} + +void storeMemory(int vaddr, int data) { + + if(process != 0){ + checkPageFault(vaddr); + + if(pageFault == 1){ + return; + } + } + + *(memory + tlb(vaddr)) = data; +} + +// ----------------------------------------------------------------- +// ---------------------------- BINARY ----------------------------- +// ----------------------------------------------------------------- + +void emitInstruction(int instruction) { + if (binaryLength >= maxBinaryLength) { + syntaxErrorMessage((int*) "exceeded maximum binary length"); + exit(-1); + } else { + storeMemory(binaryLength, instruction); + + binaryLength = binaryLength + 4; + } +} + +void emitRFormat(int opcode, int rs, int rt, int rd, int function) { + emitInstruction(encodeRFormat(opcode, rs, rt, rd, function)); + + if (opcode == OP_SPECIAL) { + if (function == FCT_JR) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot + else if (function == FCT_MFLO) { + // In MIPS I-III two instructions after MFLO/MFHI + // must not modify the LO/HI registers + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + } else if (function == FCT_MFHI) { + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // pipeline delay + } + } +} + +void emitIFormat(int opcode, int rs, int rt, int immediate) { + emitInstruction(encodeIFormat(opcode, rs, rt, immediate)); + + if (opcode == OP_BEQ) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot + else if (opcode == OP_BNE) + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot +} + +void emitJFormat(int opcode, int instr_index) { + emitInstruction(encodeJFormat(opcode, instr_index)); + + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_NOP); // delay slot +} + +void fixup_relative(int fromAddress) { + int instruction; + + instruction = loadMemory(fromAddress); + + storeMemory(fromAddress, + encodeIFormat(getOpcode(instruction), + getRS(instruction), + getRT(instruction), + (binaryLength - fromAddress - 4) / 4)); +} + +void fixup_absolute(int fromAddress, int toAddress) { + storeMemory(fromAddress, + encodeJFormat(getOpcode(loadMemory(fromAddress)), toAddress / 4)); +} + +void fixlink_absolute(int fromAddress, int toAddress) { + int previousAddress; + + while (fromAddress != 0) { + previousAddress = getInstrIndex(loadMemory(fromAddress)) * 4; + fixup_absolute(fromAddress, toAddress); + fromAddress = previousAddress; + } +} + +int copyStringToMemory(int *s, int a) { + int l; + int w; + + l = stringLength(s) + 1; + + w = a + l; + + if (l % 4 != 0) + w = w + 4 - l % 4; + + while (a < w) { + storeMemory(a, *s); + + s = s + 1; + a = a + 4; + } + + return w; +} + +void emitBinary() { + int *entry; + int fd; + + entry = global_symbol_table; + + // allocate space for global variables and copy strings + while ((int) entry != 0) { + if (getClass(entry) == VARIABLE) { + storeMemory(binaryLength, getValue(entry)); + + binaryLength = binaryLength + 4; + } else if (getClass(entry) == STRING) + binaryLength = copyStringToMemory(getString(entry), binaryLength); + + entry = getNext(entry); + } + + // assert: file with name binaryName exists prior to execution of compiler + fd = open(binaryName, 1); // 1 = O_WRONLY + + if (fd < 0) { + syntaxErrorMessage((int*) "output file not found"); + exit(-1); + } + + // The mipster_syscall 4004 writes the code array into a file. + // The syscall uses the "write" system call of the OS and compiler. + // The write system call of our Linux uses little endian byte ordering. + write(fd, memory, binaryLength); +} + +void loadBinary() { + int fd; + int numberOfReadBytes; + + fd = open(binaryName, 0); // 0 = O_RDONLY + + if (fd < 0) + exit(-1); + + numberOfReadBytes = 4; + + while (numberOfReadBytes == 4) { + numberOfReadBytes = read(fd, memory + tlb(binaryLength), 4); + + if (debug_load) { + print(binaryName); + print((int*) ": "); + print(itoa(binaryLength, string_buffer, 16, 8)); + print((int*) ": "); + print(itoa(loadMemory(binaryLength), string_buffer, 16, 8)); + println(); + } + + if (numberOfReadBytes == 4) + binaryLength = binaryLength + 4; + } +} + +// ----------------------------------------------------------------- +// --------------------------- SYSCALLS ---------------------------- +// ----------------------------------------------------------------- + +void emitExit() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "exit", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_EXIT); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); +} + +void syscall_exit() { + int exitCode; + + exitCode = *(registers+REG_A0); + + *(registers+REG_V0) = exitCode; + + print(binaryName); + print((int*) ": exiting with error code "); + print(itoa(exitCode, string_buffer, 10, 0)); + println(); + + exit(0); +} + +void emitRead() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "read", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // count + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_READ); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_read() { + int count; + int vaddr; + int fd; + int *buffer; + int size; + + count = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); + + buffer = memory + tlb(vaddr); + + size = read(fd, buffer, count); + + *(registers+REG_V0) = size; + + if (debug_read) { + print(binaryName); + print((int*) ": read "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes from file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + print((int*) " into buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + println(); + } +} + +void emitWrite() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "write", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_LW, REG_SP, REG_A2, 0); // size + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // *buffer + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // fd + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_write() { + int size; + int vaddr; + int fd; + int *buffer; + + size = *(registers+REG_A2); + vaddr = *(registers+REG_A1); + fd = *(registers+REG_A0); + + buffer = memory + tlb(vaddr); + + size = write(fd, buffer, size); + + *(registers+REG_V0) = size; + + if (debug_write) { + print(binaryName); + print((int*) ": wrote "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes from buffer at address "); + print(itoa((int) buffer, string_buffer, 16, 8)); + print((int*) " into file with descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + println(); + } +} + +void emitOpen() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "open", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + + emitIFormat(OP_LW, REG_SP, REG_A1, 0); // flags + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_LW, REG_SP, REG_A0, 0); // filename + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_OPEN); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_open() { + int flags; + int vaddr; + int *filename; + int fd; + + flags = *(registers+REG_A1); + vaddr = *(registers+REG_A0); + + filename = memory + tlb(vaddr); + + fd = open(filename, flags); + + *(registers+REG_V0) = fd; + + if (debug_open) { + print(binaryName); + print((int*) ": opened file "); + printString(filename); + print((int*) " with flags "); + print(itoa(flags, string_buffer, 10, 0)); + print((int*) " returning file descriptor "); + print(itoa(fd, string_buffer, 10, 0)); + println(); + } +} + +void emitMalloc() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "malloc", binaryLength, FUNCTION, INTSTAR_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + // load argument for malloc (size) + emitIFormat(OP_LW, REG_SP, REG_A0, 0); + + // remove the argument from the stack + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + // load the correct syscall number and invoke syscall + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_MALLOC); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + // jump back to caller, return value is in REG_V0 + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_malloc() { + int size; + int bump; + + size = *(registers+REG_A0); + + if (size % 4 != 0) + size = size + 4 - size % 4; + + bump = *(registers+REG_K1); + + if (bump + size >= *(registers+REG_SP)) + exception_handler(EXCEPTION_HEAPOVERFLOW); + + *(registers+REG_K1) = bump + size; + *(registers+REG_V0) = bump; + + if (debug_malloc) { + print(binaryName); + print((int*) ": malloc "); + print(itoa(size, string_buffer, 10, 0)); + print((int*) " bytes returning address "); + print(itoa(bump, string_buffer, 16, 8)); + println(); + } +} + +void emitGetchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "getchar", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_GETCHAR); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +void syscall_getchar() { + int c; + + c = getchar(); + + *(registers+REG_V0) = c; + + if (debug_getchar) { + print(binaryName); + print((int*) ": getchar "); + printCharacter(c); + println(); + } +} + +void emitPutchar() { + createSymbolTableEntry(GLOBAL_TABLE, (int*) "putchar", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 4); // write one integer, 4 bytes + + emitIFormat(OP_ADDIU, REG_SP, REG_A1, 0); // pointer to character + emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A0, 1); // stdout file descriptor + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_WRITE); + emitRFormat(OP_SPECIAL, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); +} + +//----------------------------------------------------------------------------------------- +//---------------------------ASSIGNEMENT 3, CONTAINS BUGS --------------------------------- +//----------------------------------------------------------------------------------------- + + +void emitSwitch(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "switch", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + //emitIFormat(OP_LW, REG_SP, REG_T1, 0); + //emitIFormat(OP_LW, REG_SP, REG_T2, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_SWITCH); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_switch(){ + + saveKernelState(pc,registers,reg_hi,reg_lo,segmentStart,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1)); + + if(*(memory+communicationSegment+12) == 0){ + registers = malloc(32*4); + } + else{ + registers = *(memory+communicationSegment+12); + } + + if(*(memory+communicationSegment+20) == 0){ + pageTable = malloc(4*1024); //ADDED A5 + + print("allocating in emulator pageTable "); + print(itoa(process,string_buffer,10,0)); + println(); + + exit(0); + } + else{ + pageTable = memory + (*(memory+communicationSegment+20))/4; + } + + + pc = *(memory+communicationSegment+11); + reg_hi = *(memory+communicationSegment+13); + reg_lo = *(memory+communicationSegment+14); + segmentStart = *(memory+communicationSegment+15); + process = *(memory+communicationSegment+16); + *(registers+REG_GP) = *(memory+communicationSegment+17); + *(registers+REG_SP) = *(memory+communicationSegment+18); + *(registers+REG_K1) = *(memory+communicationSegment+19); + + numberofInstructions = 0; //reset number of instructions + + *(memory+communicationSegment+10) = 0; //exit + + +} + + +void emitYield(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "sched_yield", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_YIELD); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_yield(){ + + + *(memory+communicationSegment+11) = pc; + *(memory+communicationSegment+12) = registers; + *(memory+communicationSegment+13) = reg_hi; + *(memory+communicationSegment+14) = reg_lo; + *(memory+communicationSegment+15) = segmentStart; + *(memory+communicationSegment+16) = process; + *(memory+communicationSegment+17) = *(registers+REG_GP); + *(memory+communicationSegment+18) = *(registers+REG_SP); + *(memory+communicationSegment+19) = *(registers+REG_K1); + *(memory+communicationSegment+20) = (int)(pageTable)-(int)(memory);//pageTable; + + restoreKernelState(); + +} +void emitLock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "lock", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_LOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_lock(){ + *(memory+communicationSegment+30) = 1; //lock flag + + syscall_yield(); + + +} + +void emitUnlock(){ + createSymbolTableEntry(GLOBAL_TABLE, (int*) "unlock", binaryLength, FUNCTION, INT_T, 0); + + emitIFormat(OP_ADDIU, REG_ZR, REG_A3, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A2, 0); + emitIFormat(OP_ADDIU, REG_ZR, REG_A1, 0); + + //emitIFormat(OP_LW, REG_SP, REG_A0, 0); // exit code + //emitIFormat(OP_ADDIU, REG_SP, REG_SP, 4); + + emitIFormat(OP_ADDIU, REG_ZR, REG_V0, SYSCALL_UNLOCK); + emitRFormat(0, 0, 0, 0, FCT_SYSCALL); + + emitRFormat(OP_SPECIAL, REG_RA, 0, 0, FCT_JR); + + +} + +void syscall_unlock(){ + *(memory+communicationSegment+30) = 2; //unlock flag + + syscall_yield(); +} + + + +//------------------------------------------------------------------------ +// MEMORY LAYOUT +// ---------------------------------------------------------------- +// | || | | || || || || +// | OS ||KP| NP| || P1 || P2 || P3 ... PN || +// ---------------------------------------------------------------- +// 0 2MB 4MB 6MB 8MB 32MB +// +// OS - KERNEL +// KP - KERNEL PROCESS +// NP - NEXT PROCESS +// +// ----------------------------------------------------------------------- + + + +// Kernel Process Data Structure : +// +----+------------+ +// | 0 | pc | +// | 1 | reg | +// | 2 | reg_hi | +// | 3 | reg_lo | +// | 4 | segStart | +// | 5 | global p | +// | 6 | stack p | +// +----+------------+ + + +void saveKernelState(int pc, int *reg, int reg_hi, int reg_lo, int segStart,int gp,int sp, int k1){ + + *(memory+communicationSegment) = pc; + *(memory + communicationSegment+1) = reg; + *(memory + communicationSegment+2) = reg_hi; + *(memory + communicationSegment+3) = reg_lo; + *(memory + communicationSegment+4) = segStart; + *(memory + communicationSegment+5) = gp; + *(memory + communicationSegment+6) = sp; + *(memory + communicationSegment+7) = k1; + +} + +void restoreKernelState(){ + process =0; + pc = *(memory + communicationSegment); + registers = *(memory + communicationSegment + 1); + reg_hi = *(memory + communicationSegment + 2); + reg_lo = *(memory + communicationSegment + 3); + segmentStart = 0; + *(registers+REG_GP) = *(memory + communicationSegment + 5); + *(registers+REG_SP) = *(memory + communicationSegment + 6); + *(registers+REG_K1) = *(memory + communicationSegment + 7); + +} + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- KOS --------------------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +int main_os(){ + int *program; + int *segment; + int *secondSegmentStart; + + secondSegmentStart = 4*1024*1024; + segSize = 4*1024*1024; + segmentStart = 4*1024*1024*2; + + segPointer =segmentStart; + memory = 0; + initInterpreter(); + readyqueue = 0; + + loadFlag = 1; + freeListKernel = 2097152; + + + init_mcqueue(); + + loadProcess("test.mips",2); + segmentStart = segmentStart + segSize; + loadProcess("test.mips",3); + segmentStart = segmentStart + segSize; + loadProcess("test.mips",4); + segmentStart = segmentStart + segSize; + //loadProcess("test.mips",5); + loadProcess("selfieForTesting.mips",5); + + loadFlag = 0; + + *(secondSegmentStart+40) = 1;//turn on paging + + *(secondSegmentStart+30) = -1; //set flag to -1 + + + while(1){ + + interpretEnvent(); + + } + + exit(0); +} + +void interpretEnvent(){ + int *program; + int *segment; + int *secondSegmentStart; + int flag; + + int frame; + + secondSegmentStart = 4*1024*1024; + flag = *(secondSegmentStart+30); + + //FLAGS + // -1 START, FIRST PROCESS TO BE LOADED + // 1 PROCESS CALLED LOCK + // 2 PROCESS CALLED UNLOCK + // 4 PAGE FAULT + // 0 ELSE , LOAD NEW PROCESS + + if(flag == -1){ + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+30) = 0; + + *(secondSegmentStart+10) = 1; //switch + } + + else if(flag == 1){ + + processLock = getProcessId(process); + *(secondSegmentStart+10) = 1; //switch + } + else if(flag == 2){ + + if(processLock == getProcessId(process)){ + processLock = 0; + *(secondSegmentStart+30) = 0; + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } + + } + else if(flag == 4){ //page fault + + pageTable = *(secondSegmentStart+20); + frame = *(secondSegmentStart+41) / 4096; //adr saved before in *(secondSegmentStart+41) + + *(pageTable+frame) = freeListKernel; + + freeListKernel = freeListKernel + 4096; + + *(secondSegmentStart+30) = 0; //set flag back to 0 + *(secondSegmentStart+10) = 1; //switch + + + } + + else{ + + push(memory,*(secondSegmentStart+12),*(secondSegmentStart+13),*(secondSegmentStart+14),*(secondSegmentStart+11),getProcessId(process),segment,*(secondSegmentStart+17),*(secondSegmentStart+18),*(secondSegmentStart+19),*(secondSegmentStart+20),readyqueue); + + + process = pop(readyqueue); + segment = getProcessSegPointer(process); + + *(secondSegmentStart+11) = getProcessPc(process); + *(secondSegmentStart+12) = getProcessRegisters(process); + *(secondSegmentStart+13) = getProcessRegHi(process); + *(secondSegmentStart+14) = getProcessRegLo(process); + *(secondSegmentStart+15) = getSegmentStart(segment); + *(secondSegmentStart+16) = getProcessId(process); + *(secondSegmentStart+17) = getProcessGlobalP(process); + *(secondSegmentStart+18) = getProcessStackP(process); + *(secondSegmentStart+19) = getProcessK1(process); + *(secondSegmentStart+20) = getProcessPageTable(process); + + *(secondSegmentStart+10) = 1; //switch + + } +} + +void loadProcess(int * name, int id){ + int *segment; + + binaryName = name; + binaryLength = 0; + pageTable = getPageTableStart(id); + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the second segment! + *(registers+REG_SP) = segSize-4; + + segment = insertSegment(id,segPointer,segSize,segmentTable); + segPointer = segPointer + segSize; //increment segmentPointer + push(memory,0,reg_hi,reg_lo,pc,id,segment,*(registers+REG_GP),*(registers+REG_SP),*(registers+REG_K1),pageTable,readyqueue); + +} + +int *getPageTableStart(int pId){ + int *pageTableStart; + int *pageTableProcess; + + pageTableStart= 6*1024*1024; // second part of the communication segment + pageTableProcess= pageTableStart + (pId * 1024); + + return pageTableProcess; +} + +//----------------------MICHAEL-SCOTT QUEUE ------------------------ + +void init_mcqueue(){ + int * ab; + + queue_t = 4*1024*1024 + 100; + q_tail = malloc(1*4); + q_head = malloc(1*4); + mc_bump = *(4*1024*1024 + 92);// = mc_bump; + + *(q_head) = queue_t; + *(q_tail) = queue_t; + + + +} + + +void mc_enqueue(int * queue_t, int value ){ + int * node; + int * tail; + int tail_count; + int * tail_next; + int tail_next_count; + int l_break; + int next; + + l_break = 0; + node = init_node(queue_t, value); + + while(l_break == 0){ + + tail = *(q_tail); + tail_count = *(tail+1); + tail_next = *(tail); + tail_count = *(tail_next+1); + + if(firstInsertFlag == 1){ + firstInsertFlag = 0; + return; + } + + if(tail == *(q_tail)){ + if(tail_next == 0){ + + if(CAS(tail,(int)(tail_next),(int)(node)) == 1){ + l_break = 1; + } + + } + else{ + + CAS(q_tail,(int)(tail),(int)(tail_next)); + } + } + + } + CAS(q_tail,(int)(tail),(int)(node)); + +} + +void mc_decueue(int * queue_t, int * pvalue){ + int * head; + int * tail; + int * head_next; + int l_break; + l_break= 0; + + + + while(l_break == 0){ + head = *(q_head); + tail = *(q_tail); + head_next = *(head); + + if(head == *(q_head)){ + if(head == tail){ + if(*head_next == 0){ + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + l_break =1; //queue empty! + } + CAS(q_tail, tail+12, (int)(*(tail))); + } + else{ + + pvalue = head_next + 2; + if(CAS(q_head,(int)(head),(int)(head_next)) == 1){ + l_break = 1; + } + } + } + } + + *(head) = 0; + *(head+1) = 0; + *(head+2) = 0; + + + +} + + + +int * init_node(int * queue_t, int value){ + *(queue_t + mc_bump+1) = *(queue_t + mc_bump+1) + 1; //ref counter + *(queue_t + mc_bump+2) = value; // value + mc_bump = mc_bump + 3; + + *(4*1024*1024 + 92) = mc_bump; + + return queue_t+(mc_bump-3); +} + +void print_mc_queue(int * queue_t){ + int *queue; + queue= *(q_head); + + + while((int)(queue) !=0){ + print(itoa(*(queue+2),string_buffer,10,0)); + print(" , "); + queue = *(queue); + } + + println(); + +} + +int CAS(int * node, int old, int new){ + + if(*(node) != old){ + return 0; + } + + + *(node) = new; + + + return 1; +} + + + + + + + + +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ +// ----------------------------------------------------------------- +// --------------------- E M U L A T O R --------------------- +// ----------------------------------------------------------------- +// *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ *~*~ + +// ----------------------------------------------------------------- +// ------------------------- INSTRUCTIONS -------------------------- +// ----------------------------------------------------------------- + +void fct_syscall() { + if (debug_disassemble) { + printFunction(function); + println(); + } + + if (*(registers+REG_V0) == SYSCALL_EXIT) { + syscall_exit(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_READ) { + syscall_read(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_WRITE) { + syscall_write(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_OPEN) { + syscall_open(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_MALLOC) { + syscall_malloc(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_GETCHAR) { + syscall_getchar(); + pc = pc + 4; + } else if (*(registers+REG_V0) == SYSCALL_YIELD) { + pc = pc + 4; + syscall_yield(); + } else if (*(registers+REG_V0) == SYSCALL_SWITCH) { + pc = pc + 4; + syscall_switch(); + }else if (*(registers+REG_V0) == SYSCALL_LOCK) { + pc = pc + 4; + syscall_lock(); + }else if (*(registers+REG_V0) == SYSCALL_UNLOCK) { + pc = pc + 4; + syscall_unlock(); + }else { + exception_handler(EXCEPTION_UNKNOWNSYSCALL); + } + +} + +void fct_nop() { + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + println(); + } +} + +void op_jal() { + *(registers+REG_RA) = pc + 8; + + pc = instr_index * 4; + + // TODO: execute delay slot + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 8)); + println(); + } +} + +void op_j() { + pc = instr_index * 4; + + // TODO: execute delay slot + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + print(itoa(instr_index, string_buffer, 16, 8)); + println(); + } +} + +void op_beq() { + pc = pc + 4; + + if (*(registers+rs) == *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; + + // TODO: execute delay slot + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void op_bne() { + pc = pc + 4; + + if (*(registers+rs) != *(registers+rt)) { + pc = pc + signExtend(immediate) * 4; + + // TODO: execute delay slot + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void op_addiu() { + *(registers+rt) = *(registers+rs) + signExtend(immediate); + + // TODO: check for overflow + + pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + printRegister(rs); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void fct_jr() { + pc = *(registers+rs); + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + println(); + } +} + +void op_lui() { + *(registers+rt) = leftShift(immediate, 16); + + pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + println(); + } +} + +void fct_mfhi() { + *(registers+rd) = reg_hi; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); + } +} + +void fct_mflo() { + *(registers+rd) = reg_lo; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + println(); + } +} + +void fct_multu() { + // TODO: 64-bit resolution currently not supported + reg_lo = *(registers+rs) * *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_divu() { + reg_lo = *(registers+rs) / *(registers+rt); + reg_hi = *(registers+rs) % *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_addu() { + *(registers+rd) = *(registers+rs) + *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void fct_subu() { + *(registers+rd) = *(registers+rs) - *(registers+rt); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void op_lw() { + int vaddr; + + vaddr = *(registers+rs) + signExtend(immediate); + + *(registers+rt) = loadMemory(vaddr); + + if(pageFault == 0){ + pc = pc + 4; + } + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + putchar('('); + printRegister(rs); + putchar(')'); + println(); + } +} + +void fct_slt() { + if (*(registers+rs) < *(registers+rt)) + *(registers+rd) = 1; + else + *(registers+rd) = 0; + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rd); + putchar(','); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +void op_sw() { + int vaddr; + + vaddr = *(registers+rs) + signExtend(immediate); + + storeMemory(vaddr, *(registers+rt)); + + if(pageFault == 0){ + pc = pc + 4; + } + //pc = pc + 4; + + if (debug_disassemble) { + printOpcode(opcode); + print((int*) " "); + printRegister(rt); + putchar(','); + print(itoa(signExtend(immediate), string_buffer, 10, 0)); + putchar('('); + printRegister(rs); + putchar(')'); + println(); + } +} + +void fct_teq() { + if (*(registers+rs) == *(registers+rt)) + exception_handler(EXCEPTION_SIGNAL); + + pc = pc + 4; + + if (debug_disassemble) { + printFunction(function); + print((int*) " "); + printRegister(rs); + putchar(','); + printRegister(rt); + println(); + } +} + +// ----------------------------------------------------------------- +// -------------------------- INTERPRETER -------------------------- +// ----------------------------------------------------------------- + +void printException(int enumber) { + print((int*) *(EXCEPTIONS + enumber)); +} + +void exception_handler(int enumber) { + print(binaryName); + print((int*) ": exception: "); + printException(enumber); + println(); + + exit(enumber); +} + +void pre_debug() { + if (debug_disassemble) { + print(binaryName); + print((int*) ": $pc="); + print(itoa(pc, string_buffer, 16, 8)); + print((int*) ": "); + } +} + +void post_debug() { + int i; + if (debug_registers) { + i = 0; + + while (i < 32) { + if (*(registers+i) != 0) { + print(binaryName); + print((int*) ": "); + printRegister(i); + putchar(CHAR_EQUAL); + print(itoa(*(registers+i), string_buffer, 16, 8)); + println(); + } + i = i + 1; + } + println(); + } +} + +void fetch() { + ir = loadMemory(pc); +} + +void execute() { + if (opcode == OP_SPECIAL) { + if (function == FCT_NOP) { + fct_nop(); + } else if (function == FCT_ADDU) { + fct_addu(); + } else if (function == FCT_SUBU) { + fct_subu(); + } else if (function == FCT_MULTU) { + fct_multu(); + } else if (function == FCT_DIVU) { + fct_divu(); + } else if (function == FCT_MFHI) { + fct_mfhi(); + } else if (function == FCT_MFLO) { + fct_mflo(); + } else if (function == FCT_SLT) { + fct_slt(); + } else if (function == FCT_JR) { + fct_jr(); + } else if (function == FCT_SYSCALL) { + fct_syscall(); + } else if (function == FCT_TEQ) { + fct_teq(); + } else { + exception_handler(EXCEPTION_UNKNOWNINSTRUCTION); + } + } else if (opcode == OP_ADDIU) { + op_addiu(); + } else if (opcode == OP_LW) { + op_lw(); + } else if (opcode == OP_SW) { + op_sw(); + } else if (opcode == OP_BEQ) { + op_beq(); + } else if (opcode == OP_BNE) { + op_bne(); + } else if (opcode == OP_JAL) { + op_jal(); + } else if (opcode == OP_J) { + op_j(); + } else { + exception_handler(EXCEPTION_UNKNOWNINSTRUCTION); + } +} + +//A1 NEW RUN METHOD TO SUPPORT PROCESS SWITCH +void run(){ + + while (1) { + fetch(); + + if(pageFault == 0){ + decode(); + pre_debug(); + execute(); + post_debug(); + + if(*(memory+communicationSegment+10) == 1){ + syscall_switch(); + } + + + if(*(memory+communicationSegment+40) == 1){ + turnOnPaging(); + } + + } + + if(pageFault == 1){ + pageFault = 0; + numberofInstructions = numberofInstructions + 1; + *(memory+communicationSegment+30) = 4; + syscall_yield(); + } + + //if(numberofInstructions > 2){ + // if(process !=0){ + // syscall_yield(); + // } + + //} + + numberofInstructions = numberofInstructions + 1; + + } + +} + +void parse_args(int argc, int *argv) { + // assert: ./selfie -m size executable {-m size executable} + + // memory size in bytes and executable file name + initMemory(atoi((int*) *(argv+2)) * 1024 * 1024, (int*) *(argv+3)); + + // initialize stack pointer + *(registers+REG_SP) = memorySize - 4; + + memSize = atoi((int*) *(argv+2)) * 1024 * 1024; //ADDED A1 + + + print(binaryName); + print((int*) ": memory size "); + print(itoa(memorySize / 1024 / 1024, string_buffer, 10, 0)); + print((int*) "MB"); + println(); +} + +void up_push(int value) { + int vaddr; + + print("stack"); + println(); + + // allocate space for one value on the stack + *(registers+REG_SP) = *(registers+REG_SP) - 4; + + // compute address + vaddr = *(registers+REG_SP); + + // store value + + storeMemory(vaddr, value); +} + +int up_malloc(int size) { + *(registers+REG_A0) = size; + + syscall_malloc(); + + return *(registers+REG_V0); +} + +void up_copyArguments(int argc, int *argv) { + int vaddr; + + up_push(argc); + + vaddr = up_malloc(argc * 4); + + up_push(vaddr); + + while (argc > 0) { + storeMemory(vaddr, up_malloc(stringLength((int*) *argv) + 1)); + + copyStringToMemory((int*) *argv, loadMemory(vaddr)); + + vaddr = vaddr + 4; + + argv = argv + 1; + argc = argc - 1; + } +} + +void insertInProcessTable(int *process, int gp, int sp, int *head){ + int *adr; + + adr = malloc(4*4); + + + setProcessTableNext(adr,head); + setProcessTableProcess(adr,process); + setProcessTableGp(adr,gp); + setProcessTableSp(adr,sp); + + processTable = adr; + +} + +void setProcessTableNext(int *processEntry, int *next){ + *processEntry = (int)(next); +} + +void setProcessTableProcess(int *processEntry, int *process){ + *(processEntry+1) = process; +} + +void setProcessTableGp(int *processEntry, int gp){ + *(processEntry+2) = gp; +} + +void setProcessTableSp(int *processEntry, int sp){ + *(processEntry+3) = sp; +} + +int* getProcessTableNext(int *processEntry){ + return (int*) *processEntry; +} + +int *getProcessTableProcess(int *processEntry){ + return (int*) *(processEntry+1); +} + +int getProcessTableGp(int *processEntry){ + return *(processEntry+2); +} + +int getProcessTableSp(int *processEntry){ + return *(processEntry+3); +} + + + +int main_emulator(int argc, int *argv) { + int*segment; + int i; + + initInterpreter(); + + initMemory(64 * 1024 * 1024,"selfie.mips"); + binaryLength = 0; + loadBinary(); + + *(registers+REG_GP) = binaryLength; + + *(registers+REG_K1) = *(registers+REG_GP); + + //initialize SP for the firs segment! + *(registers+REG_SP) = segSize - 4; + + run(); + + exit(0); + +} + +void turnOnPaging(){ + + pagingFlag = 1; + *(memory+communicationSegment+40) = 2; //turn of syscall + +} + +void printMemory(int *adr, int length, int from){ + int i; + int j; + j = 0; + i=from; + print("Memory number, Memory adress, Memory value"); + println(); + while(i 1) { + firstParameter = (int*) *(argv+1); + + if (getCharacter(firstParameter, 0) == '-') { + if (getCharacter(firstParameter, 1) == 'c') + main_compiler(); + else if (getCharacter(firstParameter, 1) == 'm') { + if (argc > 3) + main_emulator(argc, (int*) argv); + else + exit(-1); + } + else if(getCharacter(firstParameter, 1) == 'k'){ + if (argc > 3) + main_os(); + else + exit(-1); + } + else { + exit(-1); + } + } else { + exit(-1); + } + } else{ + test(); + } +} \ No newline at end of file