├── .gitignore ├── .travis.yml ├── COPYRIGHT.md ├── LICENSE ├── README.md ├── cpu60.c ├── makefile └── tests ├── prog.0.o └── prog.0.t /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - clang 4 | - gcc 5 | script: 6 | - make 7 | - make test 8 | -------------------------------------------------------------------------------- /COPYRIGHT.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Wojciech Adam Koszek 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 | SUCH DAMAGE. 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Wojciech A. Koszek 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple CPU model written in 60 lines of code 2 | 3 | [![Build Status](https://travis-ci.org/wkoszek/cpu60.svg)](https://travis-ci.org/wkoszek/cpu60) 4 | 5 | CPU60 is a simple CPU model written in 60 lines of C code. 6 | 7 | It supports 8 registers and several simple instructions: `mov`, `add`, 8 | `addi`, `sub`, `subi`, `and`, `andi`, `or`, `ori` instructions. Following 9 | each instruction is the CPU register dump. By default input is read from the 10 | standard input. 11 | 12 | Flag `-r` might be passed to simulate the proper reset of the CPU. Upon 13 | reset, all registers are filled with 0's. Without `-r`, the values of the 14 | registers are undefined, and your program instructions can't depend on 15 | register's content. 16 | 17 | # How to build 18 | 19 | To build: 20 | 21 | make 22 | 23 | # How to run 24 | 25 | Either manually: 26 | 27 | % ./cpu60 28 | reg0=a7 reg1=f1 reg2=d9 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe 29 | sub r0,r0,r0 30 | reg0=00 reg1=f1 reg2=d9 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe sub r0,r0,r0 31 | sub r1,r1,r1 32 | reg0=00 reg1=00 reg2=d9 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe sub r1,r1,r1 33 | ori r0,r0,1 34 | reg0=01 reg1=00 reg2=d9 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe ori r0,r0,1 35 | ori r1,r1,2 36 | reg0=01 reg1=02 reg2=d9 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe ori r1,r1,2 37 | add r2,r0,r1 38 | reg0=01 reg1=02 reg2=03 reg3=2a reg4=82 reg5=c8 reg6=d8 reg7=fe add r2,r0,r1 39 | 40 | Or from file: 41 | 42 | % cpu60 < file 43 | 44 | Where file can have any valid opcodes. 45 | 46 | # How to test 47 | 48 | To unit test the model, hit: 49 | 50 | make test 51 | 52 | # Author 53 | 54 | - Wojciech Adam Koszek, [wojciech@koszek.com](mailto:wojciech@koszek.com) 55 | - [http://www.koszek.com](http://www.koszek.com) 56 | -------------------------------------------------------------------------------- /cpu60.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX(a, b) ((a) > (b)) ? (a) : (b) 8 | 9 | int 10 | main(int argc, char **argv) 11 | { 12 | uint32_t i, i0, i1, i2, v2, reset_perform; 13 | uint8_t regs[8]; 14 | char buf[1000]; 15 | 16 | reset_perform = 0; 17 | if (argc == 2 && (strcmp(argv[1], "-r") == 0)) { 18 | reset_perform++; 19 | } 20 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) { 21 | regs[i] = reset_perform ? 0 : rand(); 22 | } 23 | 24 | buf[0] = '\0'; 25 | do { 26 | if (sscanf(buf, "mov r%u,r%u", &i0, &i1) == 2) { 27 | regs[i0 % 8] = regs[i1 % 8]; 28 | } 29 | if (sscanf(buf, "add r%u,r%u,r%u", &i0, &i1, &i2) == 3) { 30 | regs[i0 % 8] = regs[i1 % 8] + regs[i2 % 8]; 31 | } 32 | if (sscanf(buf, "addi r%u,r%u,%u", &i0, &i1, &v2) == 3) { 33 | regs[i0 % 8] = regs[i1 % 8] + v2; 34 | } 35 | if (sscanf(buf, "sub r%u,r%u,r%u", &i0, &i1, &i2) == 3) { 36 | regs[i0 % 8] = regs[i1 % 8] - regs[i2 % 8]; 37 | } 38 | if (sscanf(buf, "subi r%u,r%u,%u", &i0, &i1, &v2) == 3) { 39 | regs[i0 % 8] = regs[i1 % 8] - v2; 40 | } 41 | if (sscanf(buf, "and r%u,r%u,r%u", &i0, &i1, &i2) == 3) { 42 | regs[i0 % 8] = regs[i1 % 8] & regs[i2 % 8]; 43 | } 44 | if (sscanf(buf, "andi r%u,r%u,%u", &i0, &i1, &v2) == 3) { 45 | regs[i0 % 8] = regs[i1 % 8] & v2; 46 | } 47 | if (sscanf(buf, "or r%u,r%u,r%u", &i0, &i1, &i2) == 3) { 48 | regs[i0 % 8] = regs[i1 % 8] | regs[i2 % 8]; 49 | } 50 | if (sscanf(buf, "ori r%u,r%u,%u", &i0, &i1, &v2) == 3) { 51 | regs[i0 % 8] = regs[i1 % 8] | v2; 52 | } 53 | buf[MAX(0, (int)(strlen(buf) - 1))] = 0; 54 | for (i = 0; i < 8; i++) { 55 | printf("reg%1d=%02x %s %s", i, regs[i], 56 | i == 7 ? buf : "", i == 7 ? "\n":" "); 57 | } 58 | } while (fgets(buf, sizeof(buf), stdin)); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: cpu60 2 | 3 | CFLAGS+= -Wall -pedantic -Wextra -Werror 4 | 5 | cpu60: cpu60.c 6 | $(CC) $(CFLAGS) $< -o $@ 7 | 8 | clean: 9 | rm -rf cpu60 10 | 11 | test: cpu60 12 | ./cpu60 -r < tests/prog.0.t > tests/prog.0.a 13 | diff -u tests/prog.0.o tests/prog.0.a 14 | -------------------------------------------------------------------------------- /tests/prog.0.o: -------------------------------------------------------------------------------- 1 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 2 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 sub r0,r0,r0 3 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r1,r0 4 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r2,r0 5 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r3,r0 6 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r4,r0 7 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r5,r0 8 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r6,r0 9 | reg0=00 reg1=00 reg2=00 reg3=00 reg4=00 reg5=00 reg6=00 reg7=00 mov r7,r0 10 | -------------------------------------------------------------------------------- /tests/prog.0.t: -------------------------------------------------------------------------------- 1 | sub r0,r0,r0 2 | mov r1,r0 3 | mov r2,r0 4 | mov r3,r0 5 | mov r4,r0 6 | mov r5,r0 7 | mov r6,r0 8 | mov r7,r0 9 | --------------------------------------------------------------------------------