#include "language.h" #include #define PC memory.sys_start[0] #define SP memory.sys_start[1] #define RSP memory.sys_start[2] #define JUMP_OFF memory.sys_start[3] int stack_frames[256]; int stack_frame_sizes[256]; int stack_frames_index = 0; //this stores free regions as start, end, size int heap_list[2048][3]; int heap_length = 1; double total_time = 0.0; int number_of_steps = 0; struct Memory { short *memory; short *sys_start; short *rom_start; short *stack_start; short *return_stack_start; short *heap_start; }; int find_available_heap(int size) { for(int x = 0; x < 2048; x++) { if( heap_list[x][2] > size ) { int found = heap_list[x][0]; heap_list[x][0] = heap_list[x][0] + size; heap_list[x][2] = heap_list[x][2] - size; return found; } } } void free_heap(int start, int size) { heap_list[++heap_length][0] = start; heap_list[heap_length][1] = start + size; heap_list[heap_length][2] = size; for(int x = 0; x < heap_length - 1; x++) { if((heap_list[x][0] == (heap_list[heap_length][1]))) { heap_list[x][0] -= size; heap_list[x][2] += size; heap_length--; } else if(heap_list[x][1] == (heap_list[heap_length][0])) { heap_list[x][1] += size; heap_list[x][2] += size; heap_length--; } } } int POP_S(int amount, struct Memory* memory) { int data = memory->stack_start[memory->sys_start[1]-1]; memory->sys_start[1] -= amount; if(memory->sys_start[1] < 0) memory->sys_start[1] = 0; return data; } void Q_POP_S(int amount, struct Memory* memory) { memory->sys_start[1] -= amount; if(memory->sys_start[1] < 0) memory->sys_start[1] = 0; } void out_char(int output_format, int output_value) { if(output_format == 'I') printf("%i",output_value); if(output_format == 'C') printf("%c",output_value); if(output_format == 'X') printf("%x",output_value); if(output_format == 'B'){ while (output_value){ if (output_value & 1) printf("1"); else printf("0"); output_value >>= 1; } } } void main(int argc, char *argv[]) { struct Memory memory; memory.memory = malloc(256*256*sizeof(short)); memory.sys_start = &memory.memory[0]; memory.rom_start = &memory.memory[255]; memory.stack_start = &memory.memory[256*5-1]; memory.heap_start = &memory.memory[256*6-1]; memory.return_stack_start = &memory.memory[256*6-1]; heap_list[0][0] = 256*7-1; heap_list[0][1] = 256*256; heap_list[0][2] = 256*256 - 256*7-1; stack_frames[0] = RSP + 256*6-1; PC = 255; JUMP_OFF = 0; int requested_number_of_steps = 100000000; if( argc > 2) requested_number_of_steps = atoi(argv[2]); if( argc > 3) memory.sys_start[4] = (short) atoi(argv[3]); if( argc > 4) memory.sys_start[5] = (short) atoi(argv[4]); FILE *fp = fopen(argv[1], "r"); if (fp == NULL) printf("ROM could not be loaded\n"); fread(memory.rom_start, sizeof(short)*256*4, 1, fp); fclose(fp); int running = 1; while(running){ int redraw = 0; short datum = memory.memory[PC]; memcpy(memory.stack_start+SP, memory.memory+PC, sizeof(short)); int address; int output_length, output_address, output_mode, output_format, output_value; int compare_mode; short load_value; switch( datum ){ case LIT: PC++;memory.stack_start[SP] = memory.memory[PC];SP++;break; case DUP: memory.stack_start[SP] = memory.stack_start[SP - 1];SP++; break; case POP: Q_POP_S(1, &memory); break; case FHA: output_length = POP_S(1, &memory); output_address = POP_S(1, &memory); free_heap(output_address, output_length); break; case NFH: output_length = POP_S(1, &memory); output_address = find_available_heap(output_length); memory.stack_start[SP] = output_address; SP++; break; case STA: address = POP_S(1, &memory);memory.memory[address] = POP_S(1, &memory); break; case LFA: address = POP_S(1, &memory);memory.stack_start[SP] = memory.memory[address];SP++; break; case JMP: PC = POP_S(1, &memory) - 1 + JUMP_OFF; break; case JMR: memory.return_stack_start[++RSP] = PC; PC = POP_S(1, &memory) - 1 + JUMP_OFF; stack_frames_index++; stack_frame_sizes[stack_frames_index] = 1; stack_frames[stack_frames_index] = RSP + 256*6-1; break; case JCC: RSP -= stack_frame_sizes[stack_frames_index]-1; PC = memory.return_stack_start[RSP--]; stack_frames_index--; break; case JEQ: if( memory.stack_start[SP-2] == memory.stack_start[SP-3]){ PC = POP_S(3, &memory) - 1 + JUMP_OFF; } else Q_POP_S(3, &memory); break; case JNE: if( memory.stack_start[SP-2] != memory.stack_start[SP-3]){ PC = POP_S(3, &memory) - 1 + JUMP_OFF; } else Q_POP_S(3, &memory); break; case JER: if( memory.stack_start[SP-2] == memory.stack_start[SP-3]){ memory.return_stack_start[++RSP] = PC; PC = POP_S(3, &memory) - 1 + JUMP_OFF; stack_frames_index++; stack_frame_sizes[stack_frames_index] = 1; stack_frames[stack_frames_index] = RSP + 256*6-1; } else Q_POP_S(3, &memory); break; case JNR: if( memory.stack_start[SP-2] != memory.stack_start[SP-3]){ memory.return_stack_start[++RSP] = PC; PC = POP_S(3, &memory) - 1 + JUMP_OFF; stack_frames_index++; stack_frame_sizes[stack_frames_index] = 1; stack_frames[stack_frames_index] = RSP + 256*6-1; } else Q_POP_S(3, &memory); break; case SWP: memory.stack_start[SP] = memory.stack_start[SP-2];memory.stack_start[SP-2] = memory.stack_ start[SP-1];memory.stack_start[SP-1] = memory.stack_start[SP]; break; case OVR: memory.stack_start[SP] = memory.stack_start[SP-2];SP++; break; //case DIV: memory.stack_start[SP-2] = floor(memory.stack_start[SP-2] / memory.stack_start[SP-1]);Q_ POP_S(1, &memory); break; case MUL: memory.stack_start[SP-2] = memory.stack_start[SP-2] * memory.stack_start[SP-1];Q_POP_S(1, &memory); break; case SUB: memory.stack_start[SP-2] = memory.stack_start[SP-2] - memory.stack_start[SP-1];Q_POP_S(1, &memory); break; case ADD: memory.stack_start[SP-2] = memory.stack_start[SP-2] + memory.stack_start[SP-1];Q_POP_S(1, &memory); break; case LSL: memory.stack_start[SP-1] = (memory.stack_start[SP-1] << 1) | (memory.stack_start[SP-1] >> (15)) & (0x7F >> (15)); break; case AND: memory.stack_start[SP-2] = memory.stack_start[SP-2] & memory.stack_start[SP-1]; Q_POP_S(1, &memory); break; case LOR: memory.stack_start[SP-2] = memory.stack_start[SP-2] | memory.stack_start[SP-1];Q_POP_S(1, &memory); break; case CMP: compare_mode = memory.stack_start[SP-1]; switch (compare_mode){ case 0: memory.stack_start[SP-3] = memory.stack_start[SP-3] < memory.stack_start[SP-2];Q_POP _S(2, &memory); break; case 1: memory.stack_start[SP-3] = memory.stack_start[SP-3] > memory.stack_start[SP-2];Q_POP _S(2, &memory); break; case 2: memory.stack_start[SP-3] = memory.stack_start[SP-3] <= memory.stack_start[SP-2];Q_PO P_S(2, &memory); break; case 3: memory.stack_start[SP-3] = memory.stack_start[SP-3] >= memory.stack_start[SP-2];Q_PO P_S(2, &memory); break; case 4: memory.stack_start[SP-3] = memory.stack_start[SP-3] == memory.stack_start[SP-2];Q_PO P_S(2, &memory); break; case 5: memory.stack_start[SP-3] = memory.stack_start[SP-3] != memory.stack_start[SP-2];Q_PO P_S(2, &memory); break; case 6: memory.stack_start[SP-2] = memory.stack_start[SP-2] > 0;Q_POP_S(1, &memory); break; case 7: memory.stack_start[SP-2] = memory.stack_start[SP-2] < 0;Q_POP_S(1, &memory); break; } break; case OUT: output_format = POP_S(1, &memory); output_length = POP_S(1, &memory); output_mode = POP_S(1, &memory); if(output_mode == 0) output_address = POP_S(1, &memory); if(output_length == ((short)555)) output_length = 60000; for(int x=0; x < output_length; x++){ if(output_mode == 0){ output_value = memory.memory[output_address+x]; out_char(output_format,output_value); } else{ memory.memory[5000-x] = memory.stack_start[SP-1]; output_value = POP_S(1, &memory); } if((output_value == 0) && (output_length == 60000)){ output_length = x; break; } } if(output_mode == 1){ for(int x=1; x <= output_length; x++){ out_char(output_format, memory.memory[5000-output_length+x]); } } break; case LFR: load_value = stack_frames[stack_frames_index]+POP_S(1, &memory); memory.stack_start[SP++] = load_value; break; case PRS: memory.return_stack_start[++RSP] = POP_S(1, &memory); stack_frame_sizes[stack_frames_index]++; break; case STV: output_length = POP_S(1, &memory); output_address = POP_S(1, &memory); for(int x=1; x < output_length; x++){ memory.memory[output_address+output_length-x-1] = POP_S(1, &memory); } memory.memory[output_address+output_length-1] = POP_S(1, &memory); break; case STZ: output_length = POP_S(1, &memory); output_address = POP_S(1, &memory); for(int x=0; x < output_length; x++){ memory.memory[output_address+x] = 0; } break; case RIN: output_length = POP_S(1, &memory); output_address = POP_S(1, &memory); char format[24]; sprintf(format, " %%n%%%i[^\n]%%n", output_length); int n1, n2; char test[255]; scanf(format, &n1, &test, &n2); memory.memory[16] = (short)n2-n1; for(int x=0; x < n2-n1; x++){ memory.memory[output_address+x] = (short)test[x]; } break; case END: running = 0; break; default: break; } if( memory.sys_start[48] > 0 ){ char path[255]; short path_address = memory.sys_start[49]; short path_len = memory.sys_start[50]; short result_address = memory.sys_start[51]; short request_options = memory.sys_start[52]; if((request_options & ((short)-32768)) == ((short)-32768));//local path for(int p = 0; p < path_len; p++){ printf("%c",memory.memory[path_address+p]); path[p] = memory.memory[path_address+p]; } printf("\n"); path[path_len] = '\0'; short last_len = 0; if((request_options & ((short)2048)) == ((short)2048)){ //list struct dirent *directory; DIR *dr = opendir(path); if (dr == NULL){ memory.sys_start[48] = 0; printf("Could not open current directory\n"); break; } while ((directory = readdir(dr)) != NULL){ short p[255]; for(int i=0;id_name);i++){ p[i] = directory->d_name[i]; } p[strlen(directory->d_name)] = 10; memcpy(&memory.memory[result_address + last_len], p, 2*strlen(directory->d_name)+1); last_len += strlen(directory->d_name)+1; } memory.memory[result_address + last_len] = 3; memory.sys_start[53] = last_len; closedir(dr); } if((request_options & ((short)16384)) == ((short)16384)){ //read FILE *file_fp = fopen(path, "r"); if (file_fp == NULL) printf("ROM could not be loaded\n"); fread(&memory.memory[result_address], sizeof(short)*256*4, 1, file_fp); memory.sys_start[53] = 256; fclose(file_fp); } if((request_options & ((short)8192)) == ((short)8192));//write if((request_options & ((short)4096)) == ((short)4096));//execute memory.sys_start[48] = 0; } PC++; number_of_steps++; if (number_of_steps >= requested_number_of_steps){ int scanned = 0; while(scanned != 1){ scanf("%d", &scanned); if(scanned == 2){ printf("SYS:\n"); for(int x = 0; x < 255*6; x++){ if(x%30==0) printf("\n"); printf(" %04x", memory.sys_start[x]); } printf("\n"); } } } } }