#include #include 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; const int REGSIZE = 256; unsigned char memory[MEMSIZE]; unsigned short 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; } 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; int flag = 1; while(flag && 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]] = (unsigned char)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]; reg[memory[ip] & LOW] %= REGSIZE; 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 short temp = (reg[memory[ip] & LOW] << (16 - (memory[ip + 1] & LOW))) & 0xF; 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: flag = 0; break; case IO: switch(memory[ip] & LOW){ case 0: /*get character to R0*/ { char temp[58]; 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] = 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] = (unsigned char)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]] = (unsigned char)reg[15]; break; case 2: /*CALL*/ stack[sp ++] = ip; ip = memory[(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[(memory[ip] & 0xC << 6) + memory[ip + 1]] - 2; break; case 2: /*JEQ*/ if(cmpstatus == CMPEQ) ip = memory[(memory[ip] & 0xC << 6) + memory[ip + 1]] - 2; break; case 3: /*JGT*/ if(cmpstatus == CMPGT) ip = memory[(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:%03X ", i, reg[i]); if(i % 8 == 7) printf("\n"); } printf("IP = %03X", ip); printf(" Compare status:"); if(cmpstatus == CMPEQ){ printf("EQ\n"); } else if(cmpstatus == CMPLT){ printf("LT\n"); } else printf("GT\n"); printf("%04X: %02X%02X\n\n", ip, memory[ip], memory[ip + 1]); } 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("t : Trace the program stored in memory."); puts(" usage : t [start address]"); 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.0 by mousep\nThanks for your using!\n"); return; } if(strcmp(cmd, "d") == 0){ int startaddr = ip, length = proglen; 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); ip = DEFIP; continue; } if(strcmp(cmd, "h") == 0){ DisplayHelp(); continue; } if(strcmp(cmd, "l") == 0){ char filename[20] = {0}; char temp[58]; 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){ DisplayRegister(); continue; } if(strcmp(cmd, "t") == 0){ int startaddr = ip; sscanf(strptr, "%x", &startaddr); ip = startaddr; DisplayRegister(); RunProgram(startaddr, 1); continue; } puts("Unknown command!\n"); } } int main(void) { Command(); return 0; }