/* Paul Cameron Smith CDA 3101 - Comp Org 2 MIPS Assembler */ #include #include #include #define MAX_SIZE 100 // maximum number of lines to parse/store int getOpcode(char instr[32]){ int opc; if (strcmp(instr, "add") == 0) opc = 0; else if (strcmp(instr, "addi") == 0) opc = 8; else if (strcmp(instr, "nor") == 0) opc = 0; else if (strcmp(instr, "ori") == 0) opc = 13; else if (strcmp(instr, "sll") == 0) opc = 0; else if (strcmp(instr, "lui") == 0) opc = 15; else if (strcmp(instr, "sw") == 0) opc = 43; else if (strcmp(instr, "lw") == 0) opc = 35; else if (strcmp(instr, "bne") == 0) opc = 5; else if (strcmp(instr, "j") == 0) opc = 2; return opc; } int getDecRep(char reg[2]){ int decrep; if (strcmp(reg, "0") == 0) decrep = 0; else if (strcmp(reg, "1") == 0) decrep = 1; else if (strcmp(reg, "t0") == 0) decrep = 8; else if (strcmp(reg, "t1") == 0) decrep = 9; else if (strcmp(reg, "t2") == 0) decrep = 10; else if (strcmp(reg, "t3") == 0) decrep = 11; else if (strcmp(reg, "t4") == 0) decrep = 12; else if (strcmp(reg, "t5") == 0) decrep = 13; else if (strcmp(reg, "t6") == 0) decrep = 14; else if (strcmp(reg, "t7") == 0) decrep = 15; else if (strcmp(reg, "s0") == 0) decrep = 16; else if (strcmp(reg, "s1") == 0) decrep = 17; else if (strcmp(reg, "s2") == 0) decrep = 18; else if (strcmp(reg, "s3") == 0) decrep = 19; else if (strcmp(reg, "s4") == 0) decrep = 20; else if (strcmp(reg, "s5") == 0) decrep = 21; else if (strcmp(reg, "s6") == 0) decrep = 22; else if (strcmp(reg, "s7") == 0) decrep = 23; return decrep; } int main(int argc, char **argv){ char cptr[100]; // where to store temp line char label[32], dir[32], instr[32], opands[32], extra[32]; int num = 0, dat = 0; // dat is a flag to know char labels[MAX_SIZE][32]; // labels int addresses[MAX_SIZE]; char* operations[100]; int i = 0, a = 0, pc = 0; for (i; i < MAX_SIZE; i++){ strcpy(labels[i], ""); addresses[i] = 0; } /* Pass #1, associate each symbolic label with an address, start @ 0 */ while (fgets(cptr, sizeof(cptr), stdin) != NULL){ // grabs line from input stream, stores in cptr i=0; // the number of characters in each line (cptr) while (cptr[i] != '\0'){ // cptr[i] == null at the end of a line i++; // parse through each character } // cptr should now be one complete line (includes \n at the end) // DO STUFF WITH CPTR if ( sscanf( cptr, "%[^:]:\t%s\t%s", label, instr, opands) == 3 && dat == 0){ // only do this before data (dat = 0) //printf("%#010X: ", pc); //print 0x 8-digit hex line#: strcpy(labels[a], label); // store label in labels[a] addresses[a] = pc; // store pc into addresses[a] if ( strcmp(instr, "la") == 0) pc+=4; //printf(cptr); //print line contents } else if (sscanf( cptr, "%[^:]:\t%s\t%d", label, dir, &num) == 3 && dat == 1){ // do this AFTER data (dat = 1) //printf("%#010X: ", pc); //print 0x 8-digit hex line#: strcpy(labels[a], label); // store label in labels[a] addresses[a] = pc; // store pc into addresses[a] if (strcmp(dir,".space") == 0) pc += (num - 4); //printf(cptr); //print line contents } else if (sscanf( cptr, "\t%s\t%s", instr, opands) == 2){ //printf("%#010X: ", pc); //print 0x 8-digit hex line#: if ( strcmp(instr, "la") == 0) pc+=4; //printf(cptr); //print line contents } else if (sscanf( cptr, "\t%s", extra) == 1){ if (strcmp(extra, ".data") == 0){ dat = 1; pc -= 4; } else if (strcmp(extra, ".text") == 0) pc -= 4; } pc+=4; // move onto the lext adress a++; } rewind(stdin); // puts me back at the beginning of stdin /* Pass #2, translate instructions into corresponding machine code*/ i = 0, pc = 0, dat = 0; int op = 0, rs = 0, rt = 0, rd = 0, shamt = 0, funct = 0, immed = 0, targaddr = 0; char s[2], t[2], d[2]; int bin = 0; while (fgets(cptr, sizeof(cptr), stdin) != NULL) { //sscanf( cptr, "%[^:]: %s %s", label, instr, opands); //printf("%s %s %s ///", label, instr, opands); // we dont care about the labels anymore, thanks to the first loop // we only care about the instructions, and // depending on the instr, we do things with the operands. if (sscanf( cptr, "\t%s", extra) == 1){ if (strcmp(extra, ".data") == 0){ // if we hit data break; // leave the loop, we dont need anything else } else if (strcmp(extra, ".text") == 0) // we have all the labels we need from 1st loop continue; //ignore, do nothing first line // else // printf("You don't belong here..."); } bin = 0; if ( sscanf( cptr, "%[^:]:\t%s\t%s", label, instr, opands) == 3){ printf("0x%08X: ", pc); //print 0x 8-digit hex line#: } else if (sscanf( cptr, "\t%s\t%s", instr, opands) == 2){ printf("0x%08X: ", pc); //print 0x 8-digit hex line#: } if ( strcmp(instr, "la") == 0){ bin = 0; strcpy(instr, "lui"); // lui if( sscanf(opands, "$%[^,],%s", t, label) == 2){ op = getOpcode(instr); rt = getDecRep("1"); bin = (op << 5) | 0; bin = (bin << 5) | rt; // now get immed by grabbing top 16 bits from label for (i = 0; i < a; i++){ if (strcmp(labels[i], label) == 0){ immed = (addresses[i] >> 16); break; } } bin = (bin << 16) | immed; printf("0x%08X\n", bin); // split pc += 4; bin = 0; printf("0x%#08X: ", pc); //print 0x 8-digit hex line#: // do ori instr strcpy(instr, "ori"); // ori bin = 0; op = getOpcode(instr); rs = getDecRep("1"); // get rs rt = getDecRep(t); // get rt; bin = (bin&op); bin = (op << 5) | rs; bin = (bin << 5) | rt; for (i = 0; i < a; i++){ if (strcmp(labels[i], label) == 0){ immed = (addresses[i] & 65535); break; } } bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } //for every other instr (add, addi, nor, ori, sll, lui, sw, lw, bne, j else if ( strcmp(instr, "add") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],$%s", d, s, t) == 3){ op = getOpcode(instr); rs = getDecRep(s); // get rs; rt = getDecRep(t); // get rt; rd = getDecRep(d); // get rd; bin = (op << 10) | rs; bin = (bin << 5) | rt; bin = (bin << 5) | rd; bin = (bin << 5); // shamt is 0 for add, no need to or funct = 32; // get funct; bin = (bin << 6) | funct; printf("0x%08X\n", bin); //print line contents } } // 99% correct I think lol else if ( strcmp(instr, "addi") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],%d", t, s, &immed) == 3){ op = getOpcode(instr); rs = getDecRep(s); // get rs; rt = getDecRep(t); // get rt; bin = (op << 5) | rs; bin = (bin << 5) | rt; immed = (immed & 0x0000FFFF); immed = (immed | 0x0000); bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } // completed else if ( strcmp(instr, "nor") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],$%s", d, s, t) == 3){ op = getOpcode(instr); rs = getDecRep(s); // get rs; rt = getDecRep(t); // get rt; rd = getDecRep(d); // get rd; bin = (op << 5) | rs; bin = (bin << 5) | rt; bin = (bin << 5) | rd; bin = (bin << 5); // shamt is 0 for add, no need to or funct = 39; // get funct; bin = (bin << 6) | funct; printf("0x%08X\n", bin); //print line contents } } // nothin personal, kid else if ( strcmp(instr, "ori") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],%d", t, s, &immed) == 3) { bin = 63; op = getOpcode(instr); rs = getDecRep(s); // get rs rt = getDecRep(t); // get rt; bin = (bin&op); bin = (bin << 5) | rs; bin = (bin << 5) | rt; bin = (bin << 16) | immed; // get immed; printf("0x%08X\n", bin); //print line contents } } // annihilated else if ( strcmp(instr, "sll") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],%d", d, t, &shamt) == 3){ op = getOpcode(instr); rd = getDecRep(d); rt = getDecRep(t); bin = (op << 5) | 0; bin = (bin << 5) | rt; bin = (bin << 5) | rd; bin = (bin << 5) | shamt; bin = (bin << 6); printf("0x%08X\n", bin); } } // destroyed else if ( strcmp(instr, "lui") == 0){ if ( sscanf(opands, "$%[^,],%d", t, &immed) == 2){ op = getOpcode(instr); rt = getDecRep(t); bin = (op << 5) | 0; bin = (bin << 5) | rt; bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } // pwn'd else if ( strcmp(instr, "sw") == 0){ if ( sscanf(opands, "$%[^,],%d($%[^)]", t, &immed, s) == 3){ op = getOpcode(instr); rs = getDecRep(s); rt = getDecRep(t); bin = (op << 5) | rs; bin = (bin << 5) | rt; bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } // easy game else if ( strcmp(instr, "lw") == 0){ if ( sscanf(opands, "$%[^,],%d($%[^)]", t, &immed, s) == 3){ op = getOpcode(instr); rs = getDecRep(s); rt = getDecRep(t); bin = (op << 5) | rs; bin = (bin << 5) | rt; bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } // easy life else if ( strcmp(instr, "bne") == 0){ if ( sscanf(opands, "$%[^,],$%[^,],%s", s, t, label) == 3){ op = getOpcode(instr); rs = getDecRep(s); rt = getDecRep(t); bin = (op << 5) | rs; bin = (bin << 5) | rt; for (i = 0; i < a; i++) if (strcmp(labels[i], label) == 0){ immed = (addresses[i]-pc)/4; break; } immed = (immed & 0x0000FFFF); immed = (immed | 0x0000); bin = (bin << 16) | immed; printf("0x%08X\n", bin); //print line contents } } // i mean, it could be better else if ( strcmp(instr, "j") == 0){ if ( sscanf(opands, "%s", label) == 1){ op = getOpcode(instr); for (i = 0; i < a; i++) if (strcmp(labels[i], label) == 0) break; targaddr = addresses[i] >> 2; targaddr = (0x03FFFFFF & targaddr); bin = (op << 26) | targaddr; printf("0x%08X\n", bin); //print line contents } } // gg wp pc += 4; } /* Printing & error checking */ // printf("%i", pc); // for(i = 0; i < a; i++){ // parse lines // if( lines[i] != NULL) // if element has data // printf("\n%s:\t%d", labels[i], addresses[i]); // print the line // } return 0; }