/*sisc120.cpp*/ #include #include #ifdef __cplusplus const unsigned char NOP = 0x00; const unsigned char LOAD = 0x10; const unsigned char LDI = 0x20; const unsigned char STORE = 0x30; const unsigned char MOVE = 0x40; const unsigned char ADD = 0x50; const unsigned char FADD = 0x60; const unsigned char OR = 0x70; const unsigned char AND = 0x80; const unsigned char XOR = 0x90; const unsigned char ROTR = 0xA0; const unsigned char BR = 0xB0; const unsigned char HALT = 0xC0; const unsigned char IO = 0xD0; const unsigned char XTRA1 = 0xE0; const unsigned char XTRA2 = 0xF0; const unsigned char LOW = 0x0F; const unsigned char HIGH = 0xF0; const unsigned short CMPEQ = 0; const unsigned short CMPLT = 1; const unsigned short CMPGT = 2; const unsigned short DEFIP = 0; const unsigned short DEFSP = 0; const int MEMSIZE = 1024; const int STACKSIZE = 100; const int REGNUM = 16; #else #define NOP 0x00 #define LOAD 0x10 #define LDI 0x20 #define STORE 0x30 #define MOVE 0x40 #define ADD 0x50 #define FADD 0x60 #define OR 0x70 #define AND 0x80 #define XOR 0x90 #define ROTR 0xA0 #define BR 0xB0 #define HALT 0xC0 #define IO 0xD0 #define XTRA1 0xE0 #define XTRA2 0xF0 #define LOW 0x0F #define HIGH 0xF0 #define CMPEQ 0 #define CMPLT 1 #define CMPGT 2 #define DEFIP 0 #define DEFSP 0 #define MEMSIZE 1024 #define STACKSIZE 100 #define REGNUM 16 #endif char instruct[13][8] = {"NOP", "LOAD", "LDI", "STORE", "MOVE", "ADD", "FADD", "OR", "AND", "XOR", "ROTR", "BR", "HALT"}; unsigned char memory[MEMSIZE]; unsigned char reg[REGNUM]; unsigned short stack[STACKSIZE]; unsigned short cmpstatus = CMPEQ; unsigned short ip = DEFIP; unsigned short sp = DEFSP; unsigned short proglen = 0; char* strinput(char** strinp, char* strout) { while(**strinp == ' ' && **strinp != 0) (*strinp) ++; sscanf(*strinp, "%s", strout); (*strinp) += strlen(strout); return strout; } char* lowercase(char* input) { char*ptr = input; while(*ptr != 0){ if(*ptr >= 'A' && *ptr <= 'Z') (*ptr) += 'a' - 'A'; ptr ++; } return input; } void Unassemble(int startaddr, int len) { int cmd, i; for(i = 0; i < len; i += 2){ cmd = (memory[startaddr + i] & HIGH) >> 4; if(cmd <= 12) printf("%04X: %02X%02X %-8s", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], instruct[cmd]); cmd <<= 4; switch(cmd){ case NOP: case HALT: break; case LOAD: case LDI: case STORE: case BR: printf("R%1X, %02X", memory[startaddr + i] & LOW, memory[startaddr + i + 1]); break; case MOVE: printf("R%1X, R%1X", (memory[startaddr + i + 1] & HIGH) >> 4, memory[startaddr + i + 1] & LOW); break; case ADD: case FADD: case OR: case AND: case XOR: printf("R%1X, R%1X, R%1X", memory[startaddr + i] & LOW, (memory[startaddr + i + 1] & HIGH) >> 4, memory[startaddr + i + 1] & LOW); break; case ROTR: printf("R%1X, %1X", memory[startaddr + i] & LOW, memory[startaddr + i + 1] & LOW); break; case IO: switch(memory[startaddr + i] & LOW){ case 0: printf("%04X: %02X%02X %-8sR0", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "GETC"); break; case 1: printf("%04X: %02X%02X %-8sR0 ;(%c)", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "PUTC", reg[0]); break; case 2: printf("%04X: %02X%02X %-8sR0", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "GETI"); break; case 3: printf("%04X: %02X%02X %-8sR0 ;(%d)", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "OUTI", reg[0]); break; case 5: printf("%04X: %02X%02X %-8s%02X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "GETS", memory[startaddr + i + 1]); break; case 6: printf("%04X: %02X%02X %-8s%02X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "OUTS", memory[startaddr + i + 1]); break; default: printf("%04X: %02X%02X %-8s", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "???"); break; } break; case XTRA1: switch(memory[startaddr + i] & 0x3){ case 0: printf("%04X: %02X%02X %-8sRF, %03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "LOAD", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; case 1: printf("%04X: %02X%02X %-8sRF, %03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "STORE", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; case 2: printf("%04X: %02X%02X %-8s%03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "CALL", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; case 3: printf("%04X: %02X%02X %-8s", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "RET"); break; } break; case XTRA2: switch(memory[startaddr + i] & 0x3){ case 0: printf("%04X: %02X%02X %-8sR%1X, R%1X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "CMP", (memory[startaddr + i + 1] & HIGH) >> 4, memory[startaddr + i + 1] & LOW); break; case 1: printf("%04X: %02X%02X %-8sRF, %03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "JLT", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; case 2: printf("%04X: %02X%02X %-8sRF, %03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "JEQ", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; case 3: printf("%04X: %02X%02X %-8sRF, %03X", startaddr + i, memory[startaddr + i], memory[startaddr + i + 1], "JGT", ((memory[startaddr + i] & 0xC) << 6) + memory[startaddr + i + 1]); break; } break; } printf("\n"); } } unsigned short WriteMemory(int addr, FILE* src, int flag) { int chcount; int saddr = addr; char ch; while(addr < MEMSIZE){ chcount = 0; if(!flag) printf("%04X: ", addr); while(addr < MEMSIZE){ fscanf(src, "%c", &ch); if (ch == '\n' || feof(src)){ if (chcount == 0){ break; } } else if (ch == ';'){ do{ fscanf(src, "%c", &ch); } while(ch != '\n'); if (chcount == 0){ break; } } else if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F'){ char value; if (ch >= 'a') value = ch - 'a' + 10; else if (ch >= 'A') value = ch - 'A' + 10; else value = ch - '0'; if (chcount == 0){ memory[addr] = (unsigned char)(value << 4); chcount = 1; } else{ memory[addr] += (unsigned char)(value); addr ++; chcount = 0; } } } if(feof(src)) break; } return (unsigned short)(addr - saddr); } void DisplayMemory(int st, int len) { int i; for (i = 0; i < len && st + i < MEMSIZE; i ++){ if (i % 16 == 0) printf("\n%04X: ", st + i); printf("%02X ", memory[st + i]); } } void RunProgram(int addr, int stepflag) { ip = addr; while(ip < MEMSIZE){ switch(memory[ip] & HIGH){ case NOP: break; case LOAD: reg[memory[ip] & LOW] = memory[memory[ip + 1]]; break; case LDI: reg[memory[ip] & LOW] = memory[ip + 1]; break; case STORE: memory[memory[ip + 1]] = reg[memory[ip] & LOW]; break; case MOVE: reg[memory[ip + 1] & LOW] = reg[(memory[ip + 1] & HIGH) >> 4]; break; case ADD: reg[memory[ip] & LOW] = reg[(memory[ip + 1] & HIGH) >> 4] + reg[memory[ip + 1] & LOW]; break; case FADD: puts("FADD not implemented!"); break; case OR: reg[memory[ip] & LOW] = reg[(memory[ip + 1] & HIGH) >> 4] | reg[memory[ip + 1] & LOW]; break; case AND: reg[memory[ip] & LOW] = reg[(memory[ip + 1] & HIGH) >> 4] & reg[memory[ip + 1] & LOW]; break; case XOR: reg[memory[ip] & LOW] = reg[(memory[ip + 1] & HIGH) >> 4] ^ reg[memory[ip + 1] & LOW]; break; case ROTR: { unsigned char temp = (reg[memory[ip] & LOW] << (8 - (memory[ip + 1] & LOW))) & 0xFF; reg[memory[ip] & LOW] >>= (memory[ip + 1] & LOW); reg[memory[ip] & LOW] |= temp; } break; case BR: if(reg[0] == reg[memory[ip] & LOW]) ip = memory[ip + 1] - 2; break; case HALT: ip = DEFIP; return; case IO: switch(memory[ip] & LOW){ case 0: /*get character to R0*/ { char temp[20]; char ch; scanf("%c", &ch); reg[0] = ch; fgets(temp, sizeof(temp), stdin); } break; case 1: /*output character from R0*/ printf("%c", reg[0]); break; case 2: /*get integer to R0*/ { char temp[20]; int num; scanf("%d", &num); reg[0] = (unsigned char)num; fgets(temp, sizeof(temp), stdin); } break; case 3: /*output integer from R0*/ printf("%d", reg[0]); break; case 5: /*get string to memory*/ { char input[80]; int i; int start = memory[ip + 1]; fgets(input, sizeof(input), stdin); for (i = 0; input[i] != 0; i ++){ memory[start + i] = input[i]; } memory[start + i] = '$'; } break; case 6: /*output string from memory*/ { char output[80]; int i; int start = memory[ip + 1]; for (i = 0; memory[start + i] != '$'; i ++){ output[i] = memory[start + i]; } output[i] = 0; printf("%s", output); } break; } break; case XTRA1: switch(memory[ip] & 0x3){ case 0: /*LOAD*/ reg[15] = memory[((memory[ip] & 0xC) << 6) + memory[ip + 1]]; break; case 1: /*STORE*/ memory[((memory[ip] & 0xC) << 6) + memory[ip + 1]] = reg[15]; break; case 2: /*CALL*/ stack[sp ++] = ip; ip = ((memory[ip] & 0xC) << 6) + memory[ip + 1] - 2; break; case 3: /*RETURN*/ ip = stack[-- sp]; break; } break; case XTRA2: switch(memory[ip] & 0x3){ case 0: /*CMP*/ if(reg[(memory[ip + 1] & HIGH) >> 4] > reg[memory[ip + 1] & LOW]) cmpstatus = CMPGT; if(reg[(memory[ip + 1] & HIGH) >> 4] == reg[memory[ip + 1] & LOW]) cmpstatus = CMPEQ; if(reg[(memory[ip + 1] & HIGH) >> 4] < reg[memory[ip + 1] & LOW]) cmpstatus = CMPLT; break; case 1: /*JLT*/ if(cmpstatus == CMPLT) ip = ((memory[ip] & 0xC) << 6) + memory[ip + 1] - 2; break; case 2: /*JEQ*/ if(cmpstatus == CMPEQ) ip = ((memory[ip] & 0xC) << 6) + memory[ip + 1] - 2; break; case 3: /*JGT*/ if(cmpstatus == CMPGT) ip = ((memory[ip] & 0xC) << 6) + memory[ip + 1] - 2; break; } break; } ip += 2; if(stepflag) break; } if(ip > MEMSIZE) ip = DEFIP; } void DisplayRegister(void) { int i; for (i = 0; i < REGNUM; i ++){ printf("R%1X=%02X ", i, reg[i]); if(i % 8 == 7) printf("\n"); } printf("IP=%03X", ip); printf(" SP=%03X", sp); printf(" Compare status:"); if(cmpstatus == CMPEQ){ printf("EQ\n"); } else if(cmpstatus == CMPLT){ printf("LT\n"); } else printf("GT\n"); Unassemble(ip, 2); } void EditRegister(char *regname) { char temp[20]; int value; if(regname[0] == 'r'){ if(regname[1] >= '0' && regname[1] <= '9'){ printf("R%1X=%02X\n:", regname[1] - '0', reg[regname[1] - '0']); scanf("%X", &value); reg[regname[1] - '0'] = value; fgets(temp, sizeof(temp), stdin); } else if(regname[1] >= 'a' && regname[1] <= 'f'){ printf("R%1X=%02X\n:", regname[1] - 'a' + 10, reg[regname[1] - 'a' + 10]); scanf("%X", &value); reg[regname[1] - 'a' + 10] = value; fgets(temp, sizeof(temp), stdin); } else printf("Unknow register name!\n"); } else if(regname[0] == 'i' && regname[1] == 'p'){ printf("IP=%03X\n:", ip); scanf("%X", &value); ip = value; fgets(temp, sizeof(temp), stdin); } else if(regname[0] == 's' && regname[1] == 'p'){ printf("IP=%03X\n:", ip); scanf("%X", &value); sp = value; fgets(temp, sizeof(temp), stdin); } else printf("Unknow register name!\n"); } void DisplayHelp(void) { puts("d : Display contents of memory."); puts(" usage : d [start address] [length]"); puts("e : Enter program (hex mode) into memory."); puts(" usage : e [start address]"); puts("g : Run the program stored in memory."); puts(" usage : g [start address]"); puts("h : Display this help message."); puts("l : Load program from disk."); puts(" usage : l [filename]"); puts("r : Display Register."); puts(" usage : r [register]"); puts("t : Trace the program stored in memory."); puts(" usage : t [start address]"); puts("u : unassemble the program stored in memory."); puts(" usage : u [start address] [length]"); puts("q : Quit this program.\n"); } void Command(void) { char input[255]; char *strptr; char cmd[10]; while(1){ printf("- "); fgets(input, sizeof(input), stdin); lowercase(input); strptr = input; strinput(&strptr, cmd); if(strcmp(cmd, "q") == 0){ /*Quit Command*/ printf("SISC emulator ver 1.2 by mousep\n"); printf("Thanks for your using!\n"); printf("If you find any bugs, "); printf("please report to mousep@ms29.hinet.net\n"); return; } if(strcmp(cmd, "d") == 0){ int startaddr = ip, length = 64; sscanf(strptr, "%x %x", &startaddr, &length); DisplayMemory(startaddr, length); printf("\n%d bytes of memory is displayed.\n\n", length); continue; } if(strcmp(cmd, "e") == 0){ int startaddr = ip; sscanf(strptr, "%x", &startaddr); proglen = WriteMemory(startaddr, stdin, 0); printf("%d bytes of program is written.\n\n", proglen); continue; } if(strcmp(cmd, "g") == 0){ int startaddr = ip; sscanf(strptr, "%x", &startaddr); RunProgram(startaddr, 0); continue; } if(strcmp(cmd, "h") == 0){ DisplayHelp(); continue; } if(strcmp(cmd, "l") == 0){ char filename[20] = {0}; char temp[20]; FILE* finp; sscanf(strptr, "%s", filename); if(strlen(filename) == 0){ printf("Please input filename: "); scanf("%s", filename); fgets(temp, sizeof(temp), stdin); } finp = fopen(filename, "rt"); if(finp){ proglen = WriteMemory(ip, finp, 1); printf("%d bytes of program read into memory.\n\n", proglen); fclose(finp); } else puts("File does not exist!\n"); continue; } if(strcmp(cmd, "r") == 0){ char regname[10]; if(sscanf(strptr, "%s", regname) == 1) EditRegister(regname); else DisplayRegister(); continue; } if(strcmp(cmd, "t") == 0){ int startaddr = ip; sscanf(strptr, "%x", &startaddr); ip = startaddr; RunProgram(startaddr, 1); DisplayRegister(); continue; } if(strcmp(cmd, "u") == 0){ int startaddr = ip, length = 32; sscanf(strptr, "%x %x", &startaddr, &length); Unassemble(startaddr, length); printf("\n%d bytes of memory is unassembled.\n\n", length); continue; } puts("Unknown command! Type h for Help.\n"); } } int main(void) { Command(); return 0; }