/******************************************/ /* */ /* This program translates the MAR macro*/ /* nmumonics to MIPS R2000/3000 assember. */ /* The resulting code can then be run on */ /* SPIM. */ /* The code implements a stack based */ /* archetecture. */ /* */ /******************************************/ #include #include #include #include #define Debug 0 /*Set to 0 for no debug code 1 for debug code*/ #define St_offset -56 /*Offset used to conform to VAX Arc.*/ #define Heap_Size -1000 /*Heap size of virtual machine*/ FILE *ip; /*File pointer to input file */ FILE *op; /*File pointer to output file */ char opcode[60]; /*operations code*/ char p1[30]; /*First Parameter*/ char p2[30]; /*Second Parameter*/ char p3[10]; /*Third Parameter*/ char p4[10]; /*Forth Parameter*/ char p5[10]; /*Fifth Parameter*/ char strL[100]; /*Holds the string literal for the str macro*/ char lbl[100]; /*If a label is found in input string, then it is copied here*/ int found_lbl=0; /*If a label was found then this flag is set*/ int in_data=0; /*A flag which will be set if a data section is started*/ int internal_label_cnt=0; /*Used to generate an internal label*/ char ilabel[10]; /*Holds the current internal label*/ void var_procedure(); /*Prototype for var_procedure */ /************************************************/ /* */ /* CopyWrite Notice and Version information */ /* */ /************************************************/ void CopyWrite(){ printf("########################################################\n"); printf("#\n"); printf("# Marmalaid translator.\n"); printf("# Ver 2.07 Nov 18 2005\n"); printf("# Copywrite Dave Bockus, Brock University - Computer Science\n"); printf("#\n"); printf("########################################################\n"); } /******************************************/ /* */ /* This procedure will convert an int */ /* to a string via ptr. */ /* */ /******************************************/ void itoa(int num, char ptr[]) { int i,j,tmp,tmp1; /*index and pointers used for conversion*/ tmp=num; if (num==0) /*Takes care of num == 0 case */ i=1; else i=0; while (tmp > 0) { tmp = tmp/10; i++; } tmp1=num; for (j=i-1; j>=0; j--) { tmp = tmp1/10; tmp = tmp1-(tmp*10); ptr[j]=(char) ('0' + tmp); tmp1 = tmp1/10; } ptr[i]='\0'; } /************************************************/ /* */ /* Tests reg to see if it corresponds to a */ /* register. Returns 1 if true otherwise 0. */ /* */ /************************************************/ int isreg(char reg[]){ if (reg[0]=='$') return 1; else return 0; } /************************************************/ /* */ /* Generates a new internal label prefixed by */ /* _ML. */ /* */ /************************************************/ void new_ilabel(int il, char new_il[]){ char tmp[10]; /*temp used to generate next label*/ char tmp2[10]; /*Secondary temp*/ char tmp3[]="_ML\0"; /*Label header*/ itoa(il,tmp2); strcpy(tmp,tmp3); strcat(tmp,tmp2); strcpy(new_il,tmp); } /************************************************/ /* */ /* Short form of printf for code generation. */ /* */ /************************************************/ void pn(char toprint[]){ printf("\t\t\t%s\n",toprint); } /************************************************/ /* */ /* Converts the contents of mp which is */ /* assumed to be a register into the MAL */ /* equivelent. If unable to map the contents */ /* is left untouched. Input r0 - r13 is */ /* mapped to MAL CPU registers $9 - $22. */ /* Program registers $t0, $t8, $t9, $s7 */ /* */ /************************************************/ void map(char mp[]) { char tmp[20]; /*Temp to hold translated register */ char tmp2[20]; /*Secondary Temp*/ char *ptr; /*pointer used to index tmp*/ int reg; /*integer representation of Mar register*/ int is_float=0; char *is_r="r"; char *is_f="fp"; if (strlen(mp)>4) return; /*string longer then a possible register so return*/ strcpy(tmp,mp); strcpy(tmp2,mp); ptr = tmp; ptr++; if (0==strncasecmp(tmp,is_r,1)){ /*Identify mp as a general purpose r register*/ tmp[0] = '$'; if (tmp[1] == 'R' || tmp[1] == 'r'){ /*Special case the rr register to $v0 */ tmp[1] = 'v'; tmp[2] = '0'; tmp[3] = '\0'; strcpy(mp,tmp); return; } } else if (0==strncasecmp(tmp,is_f,2)){ /*Identify mp as a floating point register*/ tmp[0] = '$'; tmp[1] = 'f'; tmp2[1]= ' '; /*blow out 2nd char of tmp2, the rest should be an integer*/ ptr++; /*inc pointer to 3rd char in tmp to start the concat*/ is_float=1; /*We have a floating point register*/ } else /*Not a register so return without modifying*/ return; tmp2[0]=' '; /* must be a normal register so convert it*/ reg = atoi(tmp2); if (!is_float) reg = reg + 9; else printf("floating reg is %4d\n",reg); itoa(reg,tmp2); strcpy(ptr,tmp2); strcpy(mp,tmp); } /************************************************/ /* */ /* Usage information. */ /* */ /************************************************/ void Usage(){ printf("\nCommand Line Usage: marmalaid file [| file] > output\n"); } /************************************************/ /* */ /* Following routines decode the related */ /* opcode and generate the mal equivelent. */ /* No documentation regarding the individual */ /* routines is provided, except via the */ /* instruction set definitions provided by */ /* Dave Hughes. */ /* */ /************************************************/ void gen_header(){ CopyWrite(); pn(".data"); printf("new_line:\t\t.asciiz \"\\n\"\t\t#EOL character\n"); printf("blk:\t\t.asciiz \" \"\t\t#blank space \n"); printf("str2:\t\t\t.asciiz \" \"\t\t#Memory to hold 1 input character\n"); printf("lblow:\t\t\t.asciiz \"**** ERROR: Execution error, lower array bounds\\n\"\n"); printf("lbhi:\t\t\t.asciiz \"**** ERROR: Execution error, upper array bounds\\n\"\n"); printf("badipbl:\t\t.asciiz \"**** ERROR: Execution error, Can not parse Boolean\\n\"\n"); printf("true:\t\t\t.asciiz \"true\"\t\t#String to represent a boolean true value\n"); printf("false:\t\t\t.asciiz \"false\"\t\t#String to represent a boolean false value\n"); printf("heap:\t\t\t.word %d \t\t#pointer to base of heap\n",Heap_Size*-1); pn(".text"); printf("main:\t\t\tla $ra, ENDIT1 \n"); printf("\t\t\tsw $sp, heap \t#Initialize heap to location on stack\n"); printf("\t\t\tli $t9, 4\n"); printf("\t\t\tmul $t9, $t9, %4d\n",Heap_Size); printf("\t\t\tadd $sp, $sp, $t9 \t#create space on stack for heap\n "); printf("\t\t\tmove $s7,$sp \t#Set register s7 to point to parameter area for initial stack frame\n"); printf("\t\t\tadd $sp, $sp, -4\n"); printf("\t\t\tadd $sp, $sp, %2d\t#create space for initial dummy routine\n",St_offset); pn("move $t0, $sp\t#Set to where initial fp will be"); pn("add, $t0, $t0, -8"); pn("move $fp, $t0"); pn("sw $sp, 0($fp)"); pn("j ENDIT"); var_procedure(); /*generate the code for the var mal procedure*/ } void ntr(char p1[], char p2[]){ /*Enter procedure*/ map(p2); printf("\t\t\t\t\t###### ntr -%s-%s-\n",p1,p2); pn(".data"); pn(".text"); printf("%s:\t\t\tnop\n",p1); pn("sw $t0, 0($sp)\t#push scope pointer to stack"); pn("addi $sp, $sp, -4"); pn("sw $ra, 0($sp) \t#Push return address onto stack"); pn("addi $sp, $sp, -4"); pn("sw $fp, 0($sp) \t#Push frame pointer to stack"); pn("move $fp, $sp \t# Set FP to new frame"); pn("addi $sp, $sp, -4 \t#Inc sp"); pn("sw $9, 68($sp)"); /*Save the registers on the stack*/ pn("sw $10, 64($sp)"); pn("sw $11, 60($sp)"); pn("sw $12, 56($sp)"); pn("sw $13, 52($sp)"); pn("sw $14, 48($sp)"); pn("sw $15, 44($sp)"); pn("sw $16, 40($sp)"); pn("sw $17, 36($sp)"); pn("sw $18, 32($sp)"); pn("sw $19, 28($sp)"); pn("sw $20, 24($sp)"); pn("sw $21, 20($sp)"); pn("sw $22, 16($sp)"); /*pn("sw $23, 12($sp)");*/ printf("\t\t\tli $t0, %s \t#Load size into to, calc space\n",p2); printf("\t\t\tmul $t0, $t0,-4\n"); pn("add $sp, $sp, $t0\n"); } void rtn(char p1[], char p2[]){ /*Return from Call*/ char *ptr; /*Points to the size of the return area*/ printf("\t\t\t\t\t###### rtn -%s-%s \n",p1,p2); new_ilabel(internal_label_cnt++,ilabel); map(p1); if (isreg(p1)){ ptr = p2; printf("\t\t\tmove $v0, %s\t#copy content in %s to $v0\n",p1,p1); } else ptr = p1; pn("lw $t0, 4($fp) \t#move return address into t0\n"); pn("move $sp, $fp \t#adjust sp to current frame pointer"); pn("lw $9, 64($sp)"); /*Restore the registers from the stack*/ pn("lw $10, 60($sp)"); pn("lw $11, 56($sp)"); pn("lw $12, 52($sp)"); pn("lw $13, 48($sp)"); pn("lw $14, 44($sp)"); pn("lw $15, 40($sp)"); pn("lw $16, 36($sp)"); pn("lw $17, 32($sp)"); pn("lw $18, 28($sp)"); pn("lw $19, 24($sp)"); pn("lw $20, 20($sp)"); pn("lw $21, 16($sp)"); pn("lw $22, 12($sp)"); pn("addi $sp, $sp, 60\t#adjust sp to below stack save area"); printf("\t\t\tli $t9, %s \t#load number of parameters on stack\n",ptr); printf("\t\t\tmul $t9, $t9, 4 \t#Adjust stack wiping out pushed parameters\n"); pn("add $sp, $sp, $t9"); pn("lw $fp, 0($fp)\t#Update fp to previous frame"); pn("jr $t0 \t#Jump to return address in t0"); printf("%s:\t\t\tnop\n",ilabel); } void cal(char p1[], char p2[]){ /*Call Procedure*/ char il1[10]; /*string to hold internal label*/ map(p2); printf("\t\t\t\t\t###### cal -disp-%s -name-%s \n",p1,p2); new_ilabel(internal_label_cnt++,ilabel); new_ilabel(internal_label_cnt++,il1); pn("sw $0, 0($sp)"); printf("\t\t\tadd $sp, $sp, %3i\t#Adjust sp to conform to VAX stack frame size\n",St_offset); pn("move $t0, $sp\t#store next fp in t0"); pn("addi $t0, $t0, -8 \t#Where the new FP will point"); pn("move $t9, $fp"); pn("add $t9, $t9, 8"); pn("move $t0, $t9"); /*pn("sw $t9 , 0($t0)");*/ /*pn("sw $fp, 0($t0)"); */ /*********** Old line replace by above*/ printf("\t\t\tli $t8, %s\t#Load t8 with displacement +1\n",p1); pn("addi $t8, $t8, 1"); printf("%s:\t\t\tbeqz $t8, %s \t#Skip back disp times through the call stack\n",il1,ilabel); pn("addi $t8, $t8, -1"); pn("lw $t0, 0($t0)"); printf("\t\t\tb %s \n",il1); printf("%s:\t\t\tnop\n",ilabel); printf("\t\t\tjalr %s \t #Jump to procedure %s and link\n",p2,p2); } /************************************************/ /* */ /* This is the generic var code, a call to var */ /* will execute this code. Since var is called */ /* many times in a program it makes sence to */ /* turn it into a procedure call. */ /* */ /************************************************/ void var_procedure(){ printf("########## VAR PROCEDURE CALL CODE ###############\n"); printf("_var_:\t\tnop\n"); pn("move $a2, $fp\t\t#Scope pointer is located fp+8"); pn("addi $a2, $a2,8"); pn("move $t0, $a0\t\t#Delta frames is loaded into $t0"); printf("_var_2:\t\tbeqz $t0, _var_1\t\t#jump back delta frames\n"); pn("addi $t0, $t0, -1"); pn("lw $a2,0($a2)"); pn("b _var_2"); printf("_var_1:\t\tnop\n"); pn("move $t9, $a1\t\t#From frame cllc displacement and get var"); pn("addi $t8, $t9, 1"); pn("mul $t8, $t8, -4"); pn("add $t8, $t8, $a2"); pn("move $v0, $t8"); pn("jr $ra"); } void var(char p1[], char p2[], char p3[]){ /*Get Variable from Stack*/ map(p3); printf("\t\t\t\t\t###### var delta-%s disp-%s reg-%s-\n",p1,p2,p3); printf("\t\t\tli $a0, %s\t\t#load delta into a0\n",p1); printf("\t\t\tli $a1, %s\t\t#load displacement into a1\n",p2); /*printf("\t\t\tmove $a2, %s\t\t#Return register is %s\n",p3,p3);*/ pn("jal _var_"); printf("\t\t\tmove %s, $v0\t\t#Move var to return reg%s\n",p3,p3); } void var1(char p1[], char p2[], char p3[]){ /*Get Variable from Stack*/ char il1[10]; /*string to hold first internal*/ map(p3); new_ilabel(internal_label_cnt++,il1); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t###### var delta-%s disp-%s reg-%s-\n",p1,p2,p3); /*printf("\t\t\tli $t0, %s\n",p1); printf("\t\t\tbeqz $t0, %s\t#Check to see if 0 displacement\n",il1); printf("\t\t\tlw %s, 8($fp)\t#Scope ptr to register\n",p3); printf("\t\t\tb %s\n",ilabel);*/ printf("%s:\t\tmove %s, $fp\n",il1,p3); printf("\t\t\taddi %s, %s, 8\n",p3,p3); printf("%s:\t\tnop\n",ilabel); new_ilabel(internal_label_cnt++,ilabel); new_ilabel(internal_label_cnt++,il1); printf("\t\t\tli $t0, %s\t#Load delta to t0\n",p1); printf("%s:\t\t\tbeqz $t0, %s\t#Check to see if we skipped back delta frames\n",il1,ilabel); pn("add $t0, $t0, -1"); printf("\t\t\tlw %s, 0(%s)\t#to next frame\n",p3,p3); printf("\t\t\tb %s\n",il1); printf("%s:\t\tnop\n",ilabel); printf("\t\t\tli $t9, %s \n",p2); printf("\t\t\taddi $t8, $t9, 1\t#Calc displacement and get value of var\n"); printf("\t\t\tmul $t8, $t8, -4\n"); printf("\t\t\tadd $t8, $t8, %s\n",p3); printf("\t\t\tmove %s, $t8\n",p3); /*printf("\t\t\tlw %s, 0(%s)\n\n",p3,p3);*/ } void val(char p1[]){ /*Value of the Variable*/ map(p1); printf("\t\t\t\t\t# val -%s-\n",p1); printf("\t\t\tlw %s, 0(%s) \t#move value of the reg into reg\n\n",p1,p1); } void valf(char p1[], char p2[]){ /*Value of the Variable*/ map(p1); map(p2); printf("\t\t\t\t\t# valf -%s-%s-\n",p1,p2); printf("\t\t\tl.s %s, 0(%s) \t#move value of the reg into float reg\n",p2,p1); } /**********************************************************/ /* */ /* Old spec ndx r2, lbound, ubound, size, r1 */ /* */ /* New spec ndx r2, lbound, size, r1 */ /* where r1 <- r1 + [r1 -l]*s */ /* */ /**********************************************************/ void ndx(char p1[],char p2[],char p3[],char p4[]){ /*Index Array*/ map(p1); map(p4); printf("\t\t\t\t\t# ndx -%s-%s-%s-%s-\n",p1,p2,p3,p4); /*new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\tbge %s, %s, %s\t#Check lower bound\n",p1,p2,ilabel); pn("la $a0, lblow"); pn("li $v0, 4"); pn("syscall"); printf("%s:\t\t\tnop \n",ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\tble %s, %s, %s\t#Check upper bound\n",p1,p3,ilabel); pn("la $a0, lbhi"); pn("li $v0, 4"); pn("syscall"); printf("%s:\t\t\tnop \n",ilabel); */ /*NOTE: bounds checking disabled*/ printf("\t\t\tli $t8, %s\t#load size into t8 and mul by word size 4\n",p3); printf("\t\t\tmul $t8, $t8, 4\n"); printf("\t\t\tli $t0, %s\t#load lbound into t0 sub from %s * size\n",p2,p1); printf("\t\t\tsub %s,%s,$t0\n",p1,p1); printf("\t\t\tmul %s,%s,$t8\n",p1,p1); printf("\t\t\tadd %s,%s,%s\t#add to base %s\n",p4,p4,p1,p4); } void sel(char p1[], char p2[]){ map(p2); printf("\t\t\t\t\t# sel -%s-%s- \n",p1,p2); printf("\t\t\tli $t9, %s \t#load displacement\n",p1); /*printf("\t\t\tadd $t9, $t9, -1\n");*/ printf("\t\t\tmul $t8, $t9, 4 \t#displacement multiplied by 4\n"); printf("\t\t\tadd $t8, $t8, %s \t#added to base supplied by register %s\n",p2,p2); printf("\t\t\tmove %s, $t8 \t#move value pointed by $t8 to reg\n\n",p2); } /*void mov(char p1[],char p2[],char p3[]){ map(p2); map(p3); printf("\t\t\t\t\t# mov -%s-%s-%s- \n",p1,p2,p3); }*/ void alc(char p1[],char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# alc -%s-%s- \n",p1,p2); printf("\t\t\tlw $t8, heap\n"); printf("\t\t\tli $t9, -4 \t#Adjust heap\n"); printf("\t\t\tmove $t0, %s\n",p1); printf("\t\t\tmul $t9, $t9, $t0\n"); printf("\t\t\tadd $t8, $t8, $t9\n"); printf("\t\t\tsw $t8, heap\t#New heap boundary\n"); printf("\t\t\tadd $t8 $t8, 4\t#Move base up 1 word from heap ptr\n"); printf("\t\t\tmove %s, $t8 \t#Base address of memory is assigned to %s\n",p2,p2); } void cls(char p1[], char p2[]){ printf("\t\t\t\t\t# cls -%s-%s- \n",p1,p2); in_data=1; /*Entering .data area*/ printf("\t\t\t.data\n"); printf("%s:\t\t\t.word %s \t#superclass %s defined\n",p1,p2,p2); } void mth(char p1[]){ printf("\t\t\t\t\t# mth -%s- \n",p1); printf("\t\t\t.word %s \n",p1); } void add(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# add -%s-%s-\n",p1,p2); printf("\t\t\tadd %s, %s, %s \t\n",p2,p2,p1); } void addf(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# addf -%s-%s-\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tadd.s $f2, $f2, $f4 \n"); printf("\t\t\tmfc1 %s, $f2\t#move result to gp\n",p2); } void sub(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# sub -%s-%s-\n",p1,p2); printf("\t\t\tsub %s, %s, %s \t\n\n",p2,p2,p1); } void subf(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# subf -%s-%s-\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tsub.s $f2, $f4, $f2 \n"); printf("\t\t\tmfc1 %s, $f2\t#move result to gp\n",p2); } void mul(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# mul -%s-%s-\n",p1,p2); printf("\t\t\tmul %s, %s, %s \t\n\n",p2,p2,p1); } void mulf(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# mulf -%s-%s-\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tmul.s $f2, $f4, $f2 \n"); printf("\t\t\tmfc1 %s, $f2\t#move result to gp\n",p2); } void div1(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# div -%s-%s-\n",p1,p2); printf("\t\t\tdiv %s, %s, %s \t\n\n",p2,p2,p1); } void div1f(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# divf -%s-%s-\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tdiv.s $f2, $f4, $f2 \n"); printf("\t\t\tmfc1 %s, $f2\t#move result to gp\n",p2); } void rem(char p1[], char p2[]){ map(p1); map(p2); printf("\t\t\t\t\t# rem -%s-%s-\n",p1,p2); printf("\t\t\trem %s, %s, %s \t\n\n",p2,p2,p1); } void pint(char p1[]){ map(p1); printf("\t\t\t\t\t#pint -%s-\n",p1); printf("\t\t\tmove $a0, %s \t#Print Integer\n",p1); pn("li $v0, 1"); pn("syscall"); pn("la $a0, blk"); pn("li $v0, 4"); pn("syscall"); } void gint(char p1[]){ map(p1); printf("\t\t\t\t\t#gint -%s-\n",p1); pn("li $v0, 5"); pn("syscall"); printf("\t\t\tmove %s, $v0\t#move integer into register %s\n",p1,p1); } void gbln(char p1[]){ char il1[10]; /*Internal label*/ char il2[10]; char il3[10]; char il4[10]; char il5[10]; char il6[10]; char il7[10]; char il8[10]; char il9[10]; new_ilabel(internal_label_cnt++,il1); new_ilabel(internal_label_cnt++,il2); new_ilabel(internal_label_cnt++,il3); new_ilabel(internal_label_cnt++,il4); new_ilabel(internal_label_cnt++,il5); new_ilabel(internal_label_cnt++,il6); new_ilabel(internal_label_cnt++,il7); new_ilabel(internal_label_cnt++,il8); new_ilabel(internal_label_cnt++,il9); map(p1); /*Map input register to a MAL reg*/ printf("\t\t\t\t\t#gbln -%s-\n",p1); printf("\t\t\tli %s, 0 \t\t#Assume false so set %s = 0\n",p1,p1); /*Assumes input will be false*/ printf("%s:\t\tnop \t\t#Find the start of a boolean\n",il1); pn("la $t0, true"); pn("la $a0, str2"); pn("li $a1, 2"); pn("li $v0, 8"); pn("syscall"); pn("lb $t9, str2"); pn("lb $t0,0($t0)"); printf("\t\t\tbeq $t0, $t9, %s \n",il2); pn("la $t0, false"); pn("lb $t0,0($t0)"); printf("\t\t\tbeq $t0, $t9, %s \n",il2); printf("\t\t\tb %s \n",il1); printf("%s:\t\tnop\t\t#Found start of a boolean\n",il2); printf("\t\t\tbeq $t0, \'f\', %s\n",il3); pn("la $t0, true \t\t#Looks like a true"); pn("li $t8, 3"); printf("\t\t\tli %s, 1\t\t#Set register %s to 1\n",p1,p1); printf("\t\t\tb %s\n",il4); printf("%s:\t\tnop \t\t#Looks like a false\n",il3); pn("la $t0, false"); pn("li $t8, 4"); printf("%s:\t\tnop\n",il4); pn("addi $t0,1 \t\t#Already read first char so inc"); printf("%s:\t\tnop\n",il5); printf("\t\t\tbeq $t8, 0, %s\t\t#Read rest of boolean literal\n",il8); pn("la $a0, str2"); pn("li $a1, 2"); pn("li $v0, 8"); pn("syscall"); pn("lb $t9, str2"); pn("lb $s7, 0($t0)"); printf("\t\t\tbeq $s7, $t9, %s\n",il6); printf("\t\t\tb %s\n",il7); printf("%s:\t\tnop\n",il6); pn("addi $t0, 1"); pn("addi $t8, -1"); printf("\t\t\tb %s\t\t#Still reading valid chars, get another char\n",il5); printf("%s:\t\tnop\t\t\t#Got an error reading, so emit error message\n",il7); pn("la $a0, badipbl"); pn("li $a1,100"); pn("li $v0, 4"); pn("syscall"); printf("\t\t\tb %s\n",il9); printf("%s:\t\tnop \n",il8); printf("%s:\t\tnop \n",il9); pn("li $v0, 5 \t\t#do a get int to simulate a skipline"); pn("syscall"); } void pbln(char p1[]){ map(p1); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t#pbln -%s-\n",p1); printf("\t\t\tmove $a0, %s \t#Print Boolean\n",p1); pn("move $t0, $a0"); pn("la $a0, false"); printf("\t\tbeqz $t0, %s \t#if equal to 0 the boolean is false\n",ilabel); pn("la $a0, true"); printf("%s:\t\tnop\n",ilabel); pn("li $v0, 4"); pn("syscall"); pn("la $a0, blk"); pn("li $v0, 4"); pn("syscall"); } void pflt(char p1[]){ map(p1); printf("\t\t\t\t\t#pflt -%s-\n",p1); printf("\t\t\tmtc1 %s, $f12 \t#move gp regs to f12 reg\n",p1); pn("li $v0, 2"); pn("syscall"); pn("la $a0, blk"); pn("li $v0, 4"); pn("syscall"); } void gflt(char p1[]){ map(p1); printf("\t\t\t\t\t#gflt -%s-\n",p1); pn("li $v0, 6"); pn("syscall"); printf("\t\t\tmfc1 %s $f0 \t#store float into register %s\n",p1,p1); } void pstr(char p1[]){ map(p1); printf("\t\t\t\t\t#pstr -%s-\n",p1); printf("\t\t\tmove $a0, %s\t#move address of string into $a0\n",p1); pn("li $v0, 4"); pn("syscall"); } void gstr(char p1[], char p2[]){ char il1[10]; /*string to hold first internal*/ new_ilabel(internal_label_cnt++,ilabel); new_ilabel(internal_label_cnt++,il1); map(p1); printf("\t\t\t\t\t#gstr -%s-%s-\n",p1,p2); printf("\t\t\tlw $t8, heap \t#Allocate 100 spaces on the heap for the string\n"); printf("\t\t\tli $t9, -4 \t#Adjust heap\n"); printf("\t\t\tli $t0, 25\n"); printf("\t\t\tmul $t9, $t9, $t0\n"); printf("\t\t\tadd $t8, $t8, $t9\n"); printf("\t\t\tsw $t8, heap\t#New heap boundary\n"); printf("\t\t\tadd $t8 $t8, 4\t#Move base up 1 word from heap ptr\n"); printf("\t\t\tmove $a0, $t8 \t#move address of allocated memory to $a0\n"); if (p2[0]!='\0') printf("\t\t\tli $a1, %s\t#optional length field present\n",p2); else pn("li $a1, 100 \t#Length field not present, default to 100"); pn("li $v0, 8"); pn("syscall"); printf("\t\t\tmove %s, $t8\t#Assign %s to base of string\n",p1,p1); } void gchr(char p1[]){ char il1[10]; /*string to hold first internal*/ new_ilabel(internal_label_cnt++,ilabel); new_ilabel(internal_label_cnt++,il1); map(p1); printf("\t\t\t\t\t#gchr -%s-\n",p1); pn("la $a0, str2\t#address on place to store char"); pn("li $a1, 2"); pn("li $v0, 8"); pn("syscall"); pn("move $t0, $0\t#clear t0"); pn("lb $t0, str2"); printf("\t\t\tmove %s, $t0\t#store char into register %s\n",p1,p1); printf("\t\t\tbeq $t0, 10, %s\t#check for eol char\n",il1); printf("\t\t\tmove $0, $a3\n"); printf("\t\t\tb %s \n",ilabel); printf("%s:\t\t\tnop \n",il1); printf("\t\t\tli $a3, 1\n"); printf("%s:\t\t\tnop \n",ilabel); } void pchr(char p1[]){ map(p1); printf("\t\t\t\t\t#pchr -%s-\n",p1); printf("\t\t\tsb %s, str2\t#store char to print in str1\n",p1); pn("la $a0, str2"); pn("li $v0, 4"); pn("syscall"); } void pln(){ printf("\t\t\t\t\t#pln \n"); pn("la $a0, new_line # Print a newline"); pn("li $v0, 4"); pn("syscall"); } void tfl(char p1[]){ /*Test if eol was read*/ map(p1); printf("\t\t\t\t\t#tfl -%s-\n",p1); printf("\t\t\tsw $a3, 0(%s)\n",p1); printf("\t\t\tmove $0, $a3\n"); } void end1(char p1[], char p2[], char p3[]){ /*End program*/ printf("\t\t\t\t\t# end -%s-%s-%s-\n",p1,p2,p3); printf("ENDIT:\t\t\tlw $t8, heap\t#Allocate %s words on heap \n",p1); printf("\t\t\tli $t9, -4 \t#Adjust heap\n"); printf("\t\t\tmul $t9, $t9, %s\n",p1); printf("\t\t\tadd $t8, $t8, $t9\n"); printf("\t\t\tsw $t8, heap\n"); printf("\t\t\tadd $t8,$t8,4\n"); printf("\t\t\tla $t9, %s \t#store address %s in memory location $t8\n",p2,p2); printf("\t\t\tsw $t9, 0($t8)\n"); pn("sw $t8, 0($s7)\t#then push this address of the words on stack at $s7\n"); printf("\t\t\tjal %s\t#Call main constructor %s\n",p3,p3); printf("ENDIT1:\t\t\tli $v0, 10\n"); pn("syscall\n"); } void cst(char p1[], char p2[]){ int i; map(p2); /*If any part of p1 is text then must be an address label*/ /*so treat it as a label, otherwise must be a numeric literal*/ printf("\t\t\t\t\t# cst -%s-%s-\n",p1,p2); for (i=0; ip1 -> p2, p2=1*/ printf("\t\t\tbgt %s, %s, %s\n",p2,p1,il1); printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void gtrf(char p1[], char p2[]){ char il1[10]; /*string to hold first internal label*/ map(p1); map(p2); new_ilabel(internal_label_cnt++,ilabel); strcpy(il1,ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# gtrf -%s-%s-\t $$$$Needs Major Verification$$$$$$\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tc.le.s $f4, $f2\t#Compare negative i.e. is it less then\n"); printf("\t\t\tbc1f %s\t#if comparison was false then %s > %s\n",il1,p1,p2); /*printf("\t\t\tbge %s, %s, %s\n",p2,p1,il1);*/ printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void geq(char p1[], char p2[]){ char il1[10]; /*string to hold first internal label*/ map(p1); map(p2); new_ilabel(internal_label_cnt++,ilabel); strcpy(il1,ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# geq -%s-%s-\n",p1,p2); printf("\t\t\tbge %s, %s, %s\n",p2,p1,il1); printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void geqf(char p1[], char p2[]){ char il1[10]; /*string to hold first internal label*/ map(p1); map(p2); new_ilabel(internal_label_cnt++,ilabel); strcpy(il1,ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# geqf -%s-%s-\t $$$$Needs Major Verification$$$$$$\n",p1,p2); printf("\t\t\tmtc1 %s, $f2 \t#move gp regs to fp regs\n",p1); printf("\t\t\tmtc1 %s, $f4\n",p2); printf("\t\t\tc.lt.s $f4, $f2\t#Compare negative i.e. is it less then\n"); printf("\t\t\tbc1f %s\t#if comparison was false then %s >= %s\n",il1,p1,p2); /*printf("\t\t\tbge %s, %s, %s\n",p2,p1,il1);*/ printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void neq(char p1[], char p2[]){ char il1[10]; /*string to hold first internal label*/ map(p1); map(p2); new_ilabel(internal_label_cnt++,ilabel); strcpy(il1,ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# neq -%s-%s-\n",p1,p2); printf("\t\t\tbne %s, %s, %s\n",p2,p1,il1); printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void eql(char p1[], char p2[]){ char il1[10]; /*string to hold first internal label*/ map(p1); map(p2); new_ilabel(internal_label_cnt++,ilabel); strcpy(il1,ilabel); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# eql -%s-%s-\n",p1,p2); printf("\t\t\tbeq %s, %s, %s\n",p1,p2,il1); printf("\t\t\tli %s, 0\n",p2); printf("\t\t\tb %s\n",ilabel); printf("%s:\t\t\tli %s, 1\n",il1,p2); printf("%s:\t\t\tnop\n",ilabel); } void brf(char p1[], char p2[]){ map(p1); new_ilabel(internal_label_cnt++,ilabel); printf("\t\t\t\t\t# brf -%s-%s-\n",p1,p2); printf("\t\t\tbeqz %s, %s\t #test %s == 0,true jump, false do nothing\n",p1,p2,p1); /*printf("\t\t\tj %s\n",p2); printf("%s:\t\t\tnop\n",ilabel);*/ } void bra(char p1[]){ printf("\t\t\t\t\t# bra -%s-\n",p1); printf("\t\t\tb %s\t#branch to label %s \n",p1,p1); } void psh(char p1[]){ map(p1); printf("\t\t\t\t\t# psh -%s-\n",p1); printf("\t\t\tsw %s, 0($sp)\n",p1); pn("addi $sp, $sp, -4"); } void pshf(char p1[]){ map(p1); printf("\t\t\t\t\t# pshf -%s-\n",p1); printf("\t\t\tmfc1 $t0, %s\n",p1); printf("\t\t\tsw $t0 , 0($sp)\n"); pn("addi $sp, $sp, -4"); } void str1(char p1[], char p2[]){ printf("\t\t\t\t\t# str -%s-%s-\n",p1,strL); printf("\t\t\t.data\n"); printf("%s:\t\t\t.asciiz \"%s\"\n",p1,strL); printf("\t\t\t.text\n"); } void mov(char p1[], char p2[]){ /*implements the mnumonic mov r1 -> r2*/ map(p1); map(p2); printf("\t\t\t\t\t# mov -%s-%s-\n",p1,p2); printf("\t\t\tmove %s, %s\n",p2,p1); } /************************************************/ /* */ /* Opens and checks the input file. */ /* */ /************************************************/ void open_ip(char *name) { /*printf("Input file is %s\n",name);*/ if ((ip = fopen(name,"r")) != NULL) return; else printf("Command Line Error: Input file %s not found.\n",name); } /************************************************/ /* */ /* Breaks the contents of tmp into tokens and */ /* places the results as strings into opcode, */ /* p1,p2 and p3 formatted as strings. */ /* */ /************************************************/ void tokonize(char tmp[]){ int i; int j; /*int s;*/ /*Used for parsing strings, set to 1 if " encountered*/ char *first; /*Will point to first occurence of " in tmp*/ char *second; /*Points to second occurence of " in tmp*/ char *ptr; i=0; for (i=0;i<99;i++){ /*Removes comments from the macro file*/ if (tmp[i]=='/' && tmp[i+1]=='/'){ tmp[i]='\0'; for (j=i+1; j<100; j++) tmp[j]=' '; break; } } ptr = strchr(tmp,':'); /*Seach for a label*/ if (ptr!=NULL){ /*Have a label, copy it to lbl string*/ first = strchr(tmp,'"'); if (first == NULL || ptr%s<=\n",tmp);*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) opcode[j++] = tmp[i++]; opcode[j] = '\0'; j=0; while (tmp[i]==' ' && i<99) i++; /*set to next non blank char*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) p1[j++] = tmp[i++]; p1[j] = '\0'; j=0; while (tmp[i]==' ' && i<99) i++; /*set to next non blank char*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) p2[j++] = tmp[i++]; p2[j] = '\0'; j=0; while (tmp[i]==' ' && i<99) i++; /*set to next non blank char*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) p3[j++] = tmp[i++]; p3[j] = '\0'; j=0; while (tmp[i]==' ' && i<99) i++; /*set to next non blank char*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) p4[j++] = tmp[i++]; p4[j] = '\0'; j=0; while (tmp[i]==' ' && i<99) i++; /*set to next non blank char*/ while (!isspace(tmp[i]) && tmp[i]!='\0' && i<99) p5[j++] = tmp[i++]; p5[j] = '\0'; } /************************************************/ /* */ /* Decodes the opcode and jumps to the */ /* proper routine. */ /* */ /************************************************/ void jump_table(){ if (opcode[0]=='L'){ /*Copies literal code to output file*/ if (p1[0]=='j'){ p1[1]='\0'; printf("%s\t\t\t%s %s\n",opcode,p1,p2); /*print literal string*/ } else printf("%s\t\t\t%s \n",opcode,p1); /*print literal string*/ } if (found_lbl){ found_lbl=0; printf("%s\t\t nop\n",lbl); } /*printf("jumptable 1 \n"); */ if (Debug) printf("# Debug Code ## =>%s<= =>%s<= =>%s<= =>%s<= =>%s<=\n",opcode, p1, p2, p3, p4); /*Must be a marcro so expand it*/ if (strcmp(opcode,"mth") && in_data){ /*Generates the .text if we generate a .data with cls*/ in_data=0; printf("\t\t\t.text\n"); } if (!strcmp(opcode,"ntr")) ntr(p1,p2); if (!strcmp(opcode,"rtn")) rtn(p1,p2); if (!strcmp(opcode,"cal")) cal(p1,p2); if (!strcmp(opcode,"var")) var(p1,p2,p3); if (!strcmp(opcode,"alc")) alc(p1,p2); if (!strcmp(opcode,"cls")) cls(p1,p2); if (!strcmp(opcode,"mth")) mth(p1); if (!strcmp(opcode,"cst")) cst(p1,p2); if (!strcmp(opcode,"cstf")) cstf(p1,p2); if (!strcmp(opcode,"sto")) sto(p1,p2); if (!strcmp(opcode,"val")) val(p1); if (!strcmp(opcode,"valf")) valf(p1,p2); if (!strcmp(opcode,"add")) add(p1,p2); if (!strcmp(opcode,"addf")) addf(p1,p2); if (!strcmp(opcode,"sub")) sub(p1,p2); if (!strcmp(opcode,"subf")) subf(p1,p2); if (!strcmp(opcode,"mul")) mul(p1,p2); if (!strcmp(opcode,"mulf")) mulf(p1,p2); if (!strcmp(opcode,"div")) div1(p1,p2); if (!strcmp(opcode,"divf")) div1f(p1,p2); if (!strcmp(opcode,"rem")) rem(p1,p2); if (!strcmp(opcode,"end")) end1(p1,p2,p3); if (!strcmp(opcode,"dbg")) dbg(p1); /*Specialized mnumonic for debugging*/ if (!strcmp(opcode,"mov")) mov(p1,p2); if (!strcmp(opcode,"gint")) gint(p1); if (!strcmp(opcode,"pint")) pint(p1); if (!strcmp(opcode,"pflt")) pflt(p1); if (!strcmp(opcode,"gflt")) gflt(p1); if (!strcmp(opcode,"pbln")) pbln(p1); /*Boolean i/o is mapped to int i/o*/ if (!strcmp(opcode,"gbln")) gbln(p1); if (!strcmp(opcode,"gchr")) gchr(p1); if (!strcmp(opcode,"pchr")) pchr(p1); if (!strcmp(opcode,"pln")) pln(); if (!strcmp(opcode,"pstr")) pstr(p1); if (!strcmp(opcode,"gstr")) gstr(p1,p2); if (!strcmp(opcode,"tfl")) tfl(p1); if (!strcmp(opcode,"neg")) neg(p1); if (!strcmp(opcode,"negf")) negf(p1); if (!strcmp(opcode,"and")) and1(p1,p2); if (!strcmp(opcode,"or")) or1(p1,p2); if (!strcmp(opcode,"not")) not1(p1); if (!strcmp(opcode,"ltn")) ltn(p1,p2); if (!strcmp(opcode,"ltnf")) ltnf(p1,p2); if (!strcmp(opcode,"leq")) leq(p1,p2); if (!strcmp(opcode,"leqf")) leqf(p1,p2); if (!strcmp(opcode,"gtr")) gtr(p1,p2); if (!strcmp(opcode,"gtrf")) gtrf(p1,p2); if (!strcmp(opcode,"geq")) geq(p1,p2); if (!strcmp(opcode,"geqf")) geqf(p1,p2); if (!strcmp(opcode,"eql")) eql(p1,p2); if (!strcmp(opcode,"eqlf")) eql(p1,p2); /*Same a eql, no differnce*/ if (!strcmp(opcode,"neq")) neq(p1,p2); if (!strcmp(opcode,"neqf")) neq(p1,p2); /*Same as neq, no differnce*/ if (!strcmp(opcode,"bra")) bra(p1); if (!strcmp(opcode,"brf")) brf(p1,p2); if (!strcmp(opcode,"psh")) psh(p1); if (!strcmp(opcode,"pshf")) pshf(p1); if (!strcmp(opcode,"ndx")) ndx(p1,p2,p3,p4); if (!strcmp(opcode,"sel")) sel(p1,p2); if (!strcmp(opcode,"str")) str1(p1,p2); /*if (!strcmp(opcode,"mov")) mov(p1,p2,p3); */ /*printf("jumptable 2 \n");*/ } void clear_string(char p1[]){ int i; for (i=0; i<100; i++) p1[i]=' '; } /************************************************/ /* */ /* Reads the input file. A test funciton. */ /* */ /************************************************/ void read_ip(int header){ char tmp[100]; if (!header) gen_header(); do { fgets(tmp,100,ip); tokonize(tmp); jump_table(); clear_string(tmp); /*fgets(tmp,100,ip); */ } while (!feof(ip)); } /******************** Main ********************/ int main(argc, argv) int argc; char *argv[]; { int i; if (argc < 2){ CopyWrite(); Usage(); exit(1); } else { for (i=1; i<= (argc-1); i++){ /*printf("argv[1] is >%s<\n",argv[1]);*/ open_ip(argv[i]); read_ip(i-1); /*Only generate the header for the first file*/ fclose(ip); } } /*printf("End of program\n");*/ }