/* * ROM based 4x4-bit processor. * * Written 2011/10/28 by Alexis Kotlowy. * * Instruction Set: * ADC - Add [X]-[X+3] to A as a binary number with carry. * ADD - Add [X]-[X+3] to A as a binary number, ignoring carry. * COM - Complement the accumulator with 1's complement. * JMP - Load the immediate word into the PC if the Skip flag is clear. * LDX - Load the immediate word into the X register. * STC - Store A to [X]-[X+3] and clear A. * CLC - Clear the carry flag * FNZ - Flag skip if A is non-zero. Else clear it. * CLS - Clear Skip Flag (unconditional JMP) * SET - Set the carry flag * AND - Logical AND with [X]-[X+3] and A * HLT - Halt execution. */ #include #include #include #include #define ADC 0 #define COM 1 #define JMP 2 #define LDX 3 #define STC 4 #define CLC 5 #define FNZ 6 #define CLS 7 #define SET 8 #define AND 9 #define HLT 15 #define MEMSIZE 65536 int main (int argc, char *argv[]) { struct stat st; // For file status int mem_file; uint8_t state = 0; // Current machine state uint8_t shift_c; // Shift count uint8_t carry = 0; // Carry flag uint8_t skip = 0; // Skip flag uint16_t pc = 0; uint16_t ix = 0; uint16_t ld_tmp = 0; uint8_t acc [4] = { 0,0,0,0 }; uint8_t acc_tmp; uint8_t oper_count; uint8_t col_count = 0; uint8_t zflag = !0; uint8_t i; uint8_t print_out [16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; uint8_t memory[MEMSIZE]; if (argc != 2) { fprintf(stderr, "Please specify a memory image\n"); return (1); } mem_file = open(argv[1], O_RDONLY); if ( !mem_file ) { fprintf(stderr, "Error opening file %s\n", argv[1]); return (1); } stat(argv[1], &st); if ( st.st_size > MEMSIZE) { fprintf(stderr, "File too large!\n"); return (1); } lseek(mem_file, 0, SEEK_SET); read(mem_file, (void *) memory, st.st_size); close(mem_file); while (state != 1) { fprintf(stderr, "A = %X,%X%X%X%X\tPC = %X{%X}\tIX = %X{%X}\tSTATE = %d\n", \ carry,acc[3],acc[2],acc[1],acc[0], pc, memory[pc], ix, memory[ix], state); switch (state) { case 0: // Instruction Fetch oper_count = 0; switch (memory[pc++]) { case ADC: if (carry) state = 15; else state = 14; break; case COM: state = 2; break; case JMP: state = 3; break; case LDX: state = 5; break; case STC: state = 7; break; case CLC: state = 8; break; case FNZ: state = 9; break; case CLS: state = 11; break; case SET: state = 12; break; case AND: state = 13; break; case HLT: state = 1; break; } break; case 1: // Halt state break; case 2: //1's complement negate acc_tmp = (~acc[0])&0x0F; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3]=acc_tmp; if (oper_count > 3) state = 0; break; case 3: //Load PC from immeediate if skip = 0 ld_tmp = (ld_tmp>>4)|(memory[pc++]<<12); if (oper_count > 3) state = 4; break; case 4: // Load ld_tmp into PC if (skip == 0) pc = ld_tmp; state = 0; break; case 5: //Load Index ld_tmp = (ld_tmp>>4)|(memory[pc++]<<12); if (oper_count > 3) state = 6; break; case 6: // Load ld_tmp itno IX ix = ld_tmp; state = 0; break; case 7: //Store and Clear if ((ix & 0xE000) == 0xE000) { // Emulate printer if (acc[0] == 15) { for(i=16; i!=0;) { printf("%X",print_out[--i]); print_out[i] = 0; } printf("\n"); col_count = 0; } else print_out[col_count++] = acc[0]; } memory[ix++] = acc[0]; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3] = 0; if (oper_count > 3) state = 0; break; case 8: // Clear Carry carry = 0; state = 0; break; case 9: // Determine if Acc == 0 skip = 0; if (oper_count > 4) state = 0; else { acc_tmp = acc[0]; if (acc_tmp != 0) state = 10; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3] = acc_tmp; } break; case 10: // Non-zero, finish oper_count // and set skip flag. skip = !0; if (oper_count > 4) state = 0; else { acc_tmp = acc[0]; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3] = acc_tmp; } break; case 11: // Clear skip flag. skip = 0; state = 0; break; case 12: // Set carry flag carry = !0; state = 0; break; case 13: // Logical AND if(oper_count > 3) state = 0; acc_tmp = memory[ix++] & acc[0] & 0x0F; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3]=acc_tmp; break; case 14: // Add Binary without carry carry = 0; acc_tmp = memory[ix++] + acc[0]; if (acc_tmp > 15) { carry = !0; state = 15; } acc_tmp &= 0x0F; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3] = acc_tmp; if (oper_count > 3) state = 0; break; case 15: // Add binary with carry. carry = !0; acc_tmp = memory[ix++] + acc[0] + 1; if (acc_tmp > 15) acc_tmp = (acc_tmp - 16) & 0x0F; else { carry = 0; state = 14; } acc_tmp &= 0x0F; for (shift_c=0; shift_c<3; shift_c++) acc[shift_c] = acc[shift_c+1]; acc[3] = acc_tmp; if (oper_count > 3) state = 0; break; } oper_count++; } printf("Execution halted. Processor status:\n"); printf("A = %X%X%X%X PC = %d{%d} IX = %d{%d} STATE = %d\n", \ acc[3],acc[2],acc[1],acc[0], pc, memory[pc], ix, memory[ix], state); return 0; }