diff --git a/cpu_assignment_2.c b/cpu_assignment_2.c index 3143aca..4b53ae8 100644 --- a/cpu_assignment_2.c +++ b/cpu_assignment_2.c @@ -1,9 +1,10 @@ /* ****************************************************************************************************** - PROGRAM NAME: cpu_setup.c + PROGRAM NAME: cpu_3.c OBJECTIVE: Develop Best CPU. - DESCRIPTION: Setup CPU architecture with LOAD and STORE data and ALU operations and FLAGS. + DESCRIPTION: Setup CPU architecture with LOAD, STORE,LEA and ALU operations, Condition Codes, Jump, FLAGS + and Recursive Binary Search with Stack implementations. TEAM MEMBERS: Sanket Dhami, Karthik Sadanand, Ramyashree, Neha Rege - DATE: 8th Oct, 2016 + DATE: 2nd Nov, 2016 ****************************************************************************************************** */ #include @@ -18,23 +19,41 @@ #define DATA_MEMORY_BASE_ADD 1024 /* Base Address of Data Memory = 1024 */ #define INSTR_MEMORY_BASE_ADD 256 /* Base Address of Instruction Memory = 256 */ #define BOOT_MEMORY_BASE_ADD 0 /* Base Address of BIOS = 0 */ - +#define location_recursive_binary_search 500 +#define LOOP_ADDRESS 900 /* Looping function */ #define STORE_OPCODE 3 /* Opcode for STORE instruction */ #define LOAD_OPCODE 4 /* Opcode for LOAD instruction */ +#define ADD_OPCODE 5 +#define SUB_OPCODE 6 +#define DIV_OPCODE 7 +#define MUL_OPCODE 8 +#define MOD_OPCODE 9 +#define CMPQ_OPCODE 10 +#define ADDQ_OPCODE 11 +#define SETE_OPCODE 12 +#define SETS_OPCODE 13 +#define SETNS_OPCODE 14 +#define SETL_OPCODE 15 +#define SETLE_OPCODE 16 +#define SETG_OPCODE 17 +#define JMP_OPCODE 18 +#define PUSH_OPCODE 19 +#define POP_OPCODE 20 + /******add opcodes*****************************************************************************************************/ int memory[MEMORY_SIZE]; /* Total Memory size = 2048 bytes */ int reg[REG_COUNT]; /* Number of General Purpose Registers = 16 */ int temp_reg[TEMP_REG_COUNT]; /* Number of Temporary Registers = 16 */ -enum registers{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P}; + enum registers{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P}; int src=0, dest=0,inti=0; /* Index for source and destination registers */ int opcode = 0; int offset=0; -int i = 0; + int i = 0; -char *destreg = NULL, *srcreg = NULL,*basereg = NULL, *indexreg = NULL,*intreg = NULL; -bool flags[4]={ false }; /* flag register for setting various flags*/ + char *destreg = NULL, *srcreg = NULL,*basereg = NULL, *indexreg = NULL,*intreg = NULL; + bool flags[4]={ false }; /* flag register for setting various flags*/ /*Carry Flag = flags[0] * Zero Flag = flags[1] * Sign Flag = flags[2] @@ -46,23 +65,42 @@ bool flags[4]={ false }; /* flag register for setting various flags*/ /* Stack Pointer */ int sp = MEMORY_SIZE-1; -char *p1 = NULL; -int address,part_address,result; + char *p1 = NULL; + + int address,part_address,result; /******Function Declarations*********/ -bool load_and_store(); +bool load_store_and_lea(); bool alu_operations(); +bool cond_codes(); +bool jump_instructions(); +bool binary_search(); void init_memory(); int execute_load(); int execute_store(); +int execute_lea(); int print_values(); int add(int inti, int src); int sub(int inti, int src); int mul(int inti, int src); int division(int inti, int src); int mod(int inti, int src); +int recursive_binary_search(int, int, int); int rem =0; - +int addq(int src,int dest); +int cmpq(int src,int dest); +int sete(); +int sets(); +int setns(); +int setl(); +int setle(); +int setg(); +void push(int); +int pop(); +int looping(int dest,int count,int max); +bool loops(); +int jump(int loc); +int loopingwhile(int dest,int max); /***************Function pointers*******/ @@ -73,7 +111,7 @@ int (*fun_ptr_division)(int, int) = &division; int (*fun_ptr_mod)(int, int) = &mod; - +/************************Initialize Memory values to 0*******************/ void init_memory( ) { int i; @@ -127,9 +165,144 @@ int print_values(){ printf("\n\n\n"); return 0; } + /****************************************Jump Label*******************************************/ + int jump(int loc) + { + pc = loc; + return pc; + } + + +/******************************************************************************************** +This is the main function for binary search where it asks user to enter elements in ascending +order and the element to be searched. Later it calls recursive_binary_search function which +returns the index for the searched element and displays the position og found element. +**********************************************************************************************/ +bool binary_search(){ + p1 = "CALL"; + printf("Enter number of elements for binary search\n"); + char element_char[5]; + int element_int,element; + fgets(element_char,5,stdin); + sscanf(element_char,"%d",&element_int); + int c; + int key,index; + temp_reg[12] = 1900; + printf("Enter elements in ascending order. Press enter after each element!!\n"); + scanf("%d",&element); + memory[temp_reg[12]] = element; + temp_reg[12] = temp_reg[12] + 1; + for(c=1;cmemory[temp_reg[12]]){ + printf("Elements entered are not in ascending order!!\n"); + exit(0); + } + temp_reg[12] = temp_reg[12] + 1; + } + + temp_reg[12] = 1900; + printf("The Elements are \n"); + for(c=0;c P){ + printf("Source register should be from Register A-P \n"); + return false; + } + p2 = strtok(NULL," "); + destreg = strtok(p2,","); + dest = destreg[0]-'A'; + if(dest > P){ + printf("Destination register should be from Register A-P \n"); + return false; + } + printf("Dest = %s\t Src reg = %s\n",destreg,srcreg); + + if (strcasecmp(p1, "ADDQ")==0) { + reg[dest] = addq(reg[src],reg[dest]); + printf("Result %d\n", reg[dest]); + pc = pc + 4; + print_values(); + return true; + } + else if (strcasecmp(p1, "CMPQ")==0) { + reg[dest] = cmpq(reg[src],reg[dest]); + printf("Result %d\n", reg[dest]); + pc = pc + 4; + print_values(); + return true; + } + else + { + return false; + } +} +/**************************************ADDQ*******************************************************/ +int addq(int src, int dest){ + temp_reg[9] = src; + temp_reg[10] = dest; + temp_reg[11] = add(temp_reg[9],temp_reg[10]); + if(temp_reg[11] == 0) + { + printf("Zero Flag is set\n"); + flags[1] = 1; + } + if(temp_reg[11] < 0) + { + printf("Sign Flag is set\n"); + flags[2] = 1; + } + if((temp_reg[9]>0 && temp_reg[10]>0 && temp_reg[11]<0)||(temp_reg[9]<0 && temp_reg[10]<0) && temp_reg[10]>=0) + { + printf("Overflow Flag is set\n"); + flags[3] = 1; + } + return temp_reg[11]; +} + +/**************************************CMPQ*******************************************************/ +int cmpq(int src, int dest){ + temp_reg[9] = src; + temp_reg[10] = dest; + temp_reg[11] = sub(temp_reg[9],temp_reg[10]); + if(temp_reg[9] == temp_reg[10]) + { + //printf("Zero Flag is set\n"); + flags[1] =1; + } + if(temp_reg[11] < 0) + { + //printf("Sign Flag is set\n"); + flags[2] = 1; + } + if((temp_reg[9]>0 && temp_reg[10]<0 && temp_reg[11]<0)||(temp_reg[9]<0 && temp_reg[10]>0) && temp_reg[10]>0) + { + //printf("Overflow Flag is set"); + flags[3] = 1; + } + return temp_reg[11]; +} + /********************************************************************************************* Simple Function which calls the respective instruction. A function pointer is implemented to point the functions like add, sub, mul, division and mod. @@ -356,6 +615,170 @@ bool alu_operations(){ return true; } +/*********************************************************************************************************** +Loops +For loop Increments till the maximum number is reached by the counter. +dowhile loop Increments if the source register is less than than the Comparing register or equal if it is +greater nothing is done. +whiledo loop increments if the source register is less than than the Comparing register if it is equal and +greater nothing is done. +*********************************************************************************************************/ +bool loops() +{ + printf("1. Format for For operation: to increment a number by one till the max is reached For Eg: for B,F\n"); + printf("2. Format for Do..While operation: it increments once without checking condition then it checks the condition to increment for Eg: dowhile B,F \n"); + printf("3. Format for While..do operation: it increments after the condition is true for Eg: whiledo B,F\n"); + char instruction[20]; + int len; + char *p2 = NULL; + fgets(instruction,20,stdin); + len = strlen(instruction); + instruction[len-1] = '\0'; + p1 = strtok(instruction, " "); + p2 = strtok(NULL," "); + srcreg = strtok(p2,","); + src = srcreg[0]-'A'; + if(src > P){ + printf("Source register should be from Register A-P \n"); + return false; + } + p2 = strtok(NULL," "); + destreg = strtok(p2,","); + dest = destreg[0]-'A'; + if(dest > P){ + printf("Destination register should be from Register A-P \n"); + return false; + } + printf("Dest = %s\t Src destreg = %s\n",destreg,srcreg); + if (strcasecmp(p1, "for")==0) { + int count = 0; + printf("dest register %d \n",reg[dest]); + cmpq(count,reg[dest]); + pc = pc + 4; + if(flags[2]) + { + jump(LOOP_ADDRESS); //jumps to particular location + looping(reg[src],count,reg[dest]); + printf("Result %d\n", reg[src]); + print_values(); + return true; + } + else if(flags[1]) + { + printf("Cannot increment as the value Max is equal to the count\n"); + print_values(); + return true; + } + } + else if (strcasecmp(p1, "dowhile") == 0) + { + cmpq(reg[src],reg[dest]); + pc = pc + 4; + if(flags[1]) + { + reg[src] = add(reg[src],1); //incrementing + pc = pc + 4; + printf("Result %d\n", reg[src]); + print_values(); + return true; + } + else if(flags[2]) + { + jump(LOOP_ADDRESS); //jumps to particular location + loopingwhile(reg[src],reg[dest]); + printf("Result %d\n", reg[src]); + print_values(); + return true; + } + else if (!flags[1]) + { + reg[src] = add(reg[src],1); //incrementing + pc = pc + 4; + printf("Result %d\n", reg[src]); + print_values(); + return true; + } + } + else if (strcasecmp(p1,"whiledo") == 0) + { + int count = 0; + cmpq(reg[src],reg[dest]); + pc = pc + 4; + if(flags[2]) + { + jump(LOOP_ADDRESS); //jumps to particular location + loopingwhile(reg[src],reg[dest]); + printf("Result %d\n", reg[src]); + print_values(); + return true; + } + else if(flags[1]) + { + printf("Values are equal so cannot increment \n"); + print_values(); + return true; + } + else if (!flags[1]) + { + printf("Cannot increment as the src is greater than the given number so cannot increment\n"); + print_values(); + return true; + } + + } + else { + return false; + } +} +/********************************************Looping********************************************* +Increments till the count reaches the max. this is for "for loop" +************************************************************************************************/ +int looping(int dest,int count,int max) +{ + temp_reg[16] = dest; + temp_reg[11] = 1; + temp_reg[12] = count; + temp_reg[13] = max; + + temp_reg[16]= add(temp_reg[16],temp_reg[11]); // ADD R3,R1,R2 + pc = pc + 4; + temp_reg[12] = add(temp_reg[12],temp_reg[11]); // ADD R3,R1,R2 + pc = pc + 4; + cmpq(temp_reg[12],temp_reg[13]); + pc = pc + 4; + if(flags[2]) + { + pc = pc + 4; + jump(900); + looping(temp_reg[16],temp_reg[12],temp_reg[13]); + } + reg[src] = temp_reg[16]; + return 0; +} +/********************************************LoopingWhile******************************************** +Increments till the source equal to the destination. this is for "do while" and "while do" +************************************************************************************************/ +int loopingwhile(int dest,int max) +{ + temp_reg[16] = dest; + temp_reg[11] = 1; + temp_reg[13] = max; + + temp_reg[16]= add(temp_reg[16],temp_reg[11]); // ADD R3,R1,R2 + pc = pc + 4; + cmpq(temp_reg[16],temp_reg[13]); + pc = pc + 4; + if(flags[2]) //compare check sign + { + pc = pc + 4; + jump(900); + loopingwhile(temp_reg[16],temp_reg[13]); + } + reg[src] = temp_reg[16]; + return 0; +} + + /*****************************************ADDITION FUNCTION***************************************** This function adds the content of inti and src and returns the value. The returned value is stored in @@ -364,10 +787,6 @@ operand instruction. Also, flags like sign flag, carry flag, overflow flag and z /**************************************************************************************************/ int add(int inti, int src){ - //opcode = memory[pc]; - //dest = memory[pc+1]; - //inti = memory[pc+2]; - //src = memory[pc+3]; int carry; temp_reg[0] = src; temp_reg[1] = inti; @@ -412,9 +831,9 @@ destination register. Thus making it a 3 operand instruction. Basically it perfo of the negative number and calls the addition function. /******************************************************************************************************/ int sub(int inti, int src){ - printf("Performing Subtraction \n"); + //printf("Performing Subtraction \n"); temp_reg[4] = src; - temp_reg[5] = inti; //2'S complement + temp_reg[5] = inti; temp_reg[4] = (*fun_ptr_add)(~temp_reg[4], 1); temp_reg[4] = (*fun_ptr_add)(temp_reg[4], temp_reg[5]); return temp_reg[4]; @@ -428,7 +847,7 @@ destination register. Thus making it a 3 operand instruction. Primarily, with th multiplication instruction is carried out. /*********************************************************************************************************/ int mul(int inti, int src){ - printf("Performing Multiplication Operation\n"); + //printf("Performing Multiplication Operation\n"); int result = 0; temp_reg[2] = src; temp_reg[3] = inti; @@ -466,11 +885,11 @@ int division(int inti, int src){ } if (temp_reg[6]!= 0 ) { - printf("dividing"); + // printf("dividing"); while (temp_reg[5]>=temp_reg[6]) { temp_reg[5] = (*fun_ptr_sub)(temp_reg[5],temp_reg[6]); - printf("temp_reg[5] afteR sub %d",temp_reg[5]); +// printf("temp_reg[5] afteR sub %d",temp_reg[5]); result++; } } @@ -492,7 +911,7 @@ int division(int inti, int src){ else{ flags[1] = false; } - printf(" rem = %d \n",temp_reg[0]); + // printf(" rem = %d \n",temp_reg[0]); return result; } @@ -535,10 +954,11 @@ int c= 0 ,sign = 0; } -/*****************************************LOAD AND STORE FUNCTION*****************************************/ -bool load_and_store(){ +/*****************************************LOAD,STORE and LEA FUNCTION*****************************************/ +bool load_store_and_lea(){ printf("1. Format for LOAD operation: LOAD dest_reg,offset(src_reg) Eg: LOAD A,30(RB,RI,4) \n"); printf("2 .Format for STORE opcode: STORE dest_reg,offset(src_reg) Eg: STORE A,30(B) \n"); + printf("3. Format for LEA operation: LEA dest_reg,offset(src_reg) EG: LEA A,30(RB,RI,4) \n"); char *p2 = NULL,*p3 = NULL,*p4 = NULL; char instruction[20]; int s,base,index; @@ -639,6 +1059,104 @@ bool load_and_store(){ return false; } } + else if (strcasecmp(p1, "LEA")==0) { + p2 = strtok(NULL,""); + + destreg = strtok(p2,","); + + dest = destreg[0] - 'A'; + + if(dest > P) { + printf("Destination registers should be from Register A-P \n"); + return false; + } + + p2 = strtok(NULL,""); + + p2 = strtok(p2,"("); + + if(p2==NULL){ + offset = 0; + } + else{ + offset = atoi(p2); + } + + p3 = strtok(NULL,"("); + + if(p3 == NULL){ + if(p2==NULL){ + + } + else{ + p3=p2; + } + } + + p4 =strtok(p3,",)"); + + if(p4 == NULL){ + basereg = NULL; + } + else{ + basereg = p4; + base = basereg[0] - 'A'; /*Index for source register*/ + if(base > P){ + printf("Base registers should be from Register A-P \n"); + return false; + } + } + + p2 = strtok(NULL,""); + + indexreg = strtok(p2,",)"); + + if(indexreg == NULL){ + + } + else{ + index = indexreg[0] - 'A'; /*Index for source register*/ + if(index > P){ + printf("Index registers should be from Register A-P \n"); + return false; + } + } + p2 = strtok(NULL,")"); + + if(p2==NULL){ + s = 0; + } + else{ + s = atoi(strtok(p2,")")); + } + if(s==0 || s==1 || s==2 || s==4 || s==8){ + } + else{ + printf("S should be 1,2,4 or 8\n"); + exit(0); + } + + part_address = reg[base]+s*reg[index]; + + memory[INSTR_MEMORY_BASE_ADD + i] = opcode; + memory[INSTR_MEMORY_BASE_ADD + i+1] = dest; + memory[INSTR_MEMORY_BASE_ADD + i+2] = offset; + memory[INSTR_MEMORY_BASE_ADD + i+3] = part_address; + i = i+4; + + result = execute_lea(); + if (result !=0){ + printf("Error in executing Lea Instruction \n"); + return false; + } + result = print_values(); + if (result !=0){ + printf("Error in printing values \n"); + return false; + } + + } + else if (strcasecmp(p1, "STORE")==0) { opcode = STORE_OPCODE; p2 = strtok(NULL," "); @@ -752,7 +1270,7 @@ int execute_load(){ offset = memory[pc+2]; part_address = memory[pc+3]; address = part_address + offset; -// printf("part_address = %d\t full address = %d\n",part_address,address); + if(address >= DATA_MEMORY_BASE_ADD && address < MEMORY_SIZE){ reg[dest] = memory[address]; pc = pc + 4; @@ -764,6 +1282,34 @@ int execute_load(){ } } +/****************Function for LEA Instruction *********************************************/ +/* On executing LEA destreg,offset(srcreg) instruction, the address or + value present in source register is added with offset which will result + into final address. The final address is then loaded directly into the + destination register.*/ +/*******************************************************************************************/ +int execute_lea() { + + opcode = memory[pc]; + dest = memory[pc+1]; + offset = memory[pc+2]; + + part_address = memory[pc+3]; + address = part_address + offset; + + if(address >= INSTR_MEMORY_BASE_ADD && address < MEMORY_SIZE){ + reg[dest] = address; + pc = pc+4; + printf("LEA Instruction executed successfully\n\n\n"); + return 0; +} +else{ + printf("Invalid location\n"); + } + +} + + /****************Function for STORE Instruction *********************************************/ /* On executing STORE destreg,offset(srcreg) instruction, the address or value present in source register is added with offset which will result @@ -776,7 +1322,7 @@ int execute_store(){ offset = memory[pc+2]; part_address = memory[pc+3]; address = part_address + offset; - printf("part_address = %d\t full address = %d\n",part_address,address); + //printf("part_address = %d\t full address = %d\n",part_address,address); if(address >= DATA_MEMORY_BASE_ADD && address < MEMORY_SIZE){ memory[address] = reg[src]; pc = pc + 4; @@ -788,7 +1334,7 @@ int execute_store(){ } } - +/******************************Main********************************/ int main(){ bool res = true; int option; @@ -805,17 +1351,18 @@ int main(){ while(res == true){ printf("Enter instructions number from the menu\n"); printf("****************Instructions Menu****************\n"); - printf("1. Load/Store Instruction\n"); + printf("1. Load/Store/LEA Instruction\n"); printf("2. ALU operations - ADD/SUB/MUL/DIV/MOD\n"); - printf("3. Condition Codes - setne,sete,setle,setg,sets,setns,compq\n"); - printf("4. EXIT\n"); + printf("3. Condition Codes - setne,sete,setle,setg,sets,setns\n"); + printf("4. Condition Codes - compq,addq\n"); + printf("5. Perform Recursive Binary Search with Stack operations\n"); + printf("6. Loops implementing Jump Instruction for, do..while, while..do\n"); + printf("7. EXIT\n"); fgets(char_option,5,stdin); sscanf(char_option,"%d",&option); - //option = option - '0'; - //printf(" %d\n",option); switch(option){ case 1: - res = load_and_store(); + res = load_store_and_lea(); if(res == false){ printf("Wrong Instruction\n"); exit(-1); @@ -827,7 +1374,7 @@ int main(){ printf("Wrong Instruction\n"); exit(-1); } - break; + break; case 3: res = cond_codes(); if(res == false){ @@ -836,7 +1383,32 @@ int main(){ } break; case 4: + res = condcode_two(); + if(res == false){ + printf("Wrong Instruction\n"); + exit(-1); + } + break; + + case 5: + res = binary_search(); + if(res == false){ + printf("Wrong Instruction\n"); + exit(-1); + } + exit(0); + case 6: + res = loops(); + if(res == false){ + printf("Wrong Instruction\n"); + exit(-1); + } + break; + + case 7: res = false; + exit(-1); + default: break; }