├── LICENSE ├── README.md ├── screenshot.png └── src ├── компьютер 4 бита.CircuitProject └── эмулятор ├── memory.c ├── program.c ├── types.c └── эмуляция.c /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Этот процессор может быть выполнен на транзисторах в домашних условиях. Схема строится только на логических элементах **NOT**, **OR**, **AND**, **XOR**, **NOR**. Битность можно задать любую добавляя провода и логические элементы в соответствии со схемой. Здесь представлена схема минималистичного 4-х битного варианта на 155 логических элементов. 2 | 3 | Для просмотра схемы используйте Logic Circuit: https://www.logiccircuit.org/ 4 | 5 | **English.** This processor can be hand-made. The only logic gates the circuit uses are **NOT**, **OR**, **AND**, **XOR**, **NOR**. You can adjust the word size by adding more wires and logic gates in line with the circuit. The circuit provided here is a minimalistic 4-bit one with 155 logic components. 6 | 7 | Use Logic Circuit to view the circuit: https://www.logiccircuit.org/ 8 | 9 | ## Эмуляция 10 | В src находится эмулятор процессора, написанный на языке C, компилируется командой **gcc "эмуляция.c"**. Эмулятор имеет некоторый набор операций, который при необходимости нужно добавить в память схемы, так как представленная схема имеет только одну операцию - инкремент счётчика комманд. С помощью эмулятора можно задать битность процессора, написать для него программу и посмотреть на результат выполнения. 11 | 12 | ## Запуск схемы 13 | Для запуска схемы в LogicCircuit нужно 14 | - загрузить программу в ПЗУ, расположенном на схеме "Память" 15 | - включить питание схемы ctrl + W 16 | - выключить кнопку сброса на схеме. 17 | 18 | ## Цикл выполнения программы 19 | Программа состоит из последовательности **LOAD**/**STORE** операций между регистром-аккумулятором и ячейками RAM памяти. Выполнение одной операции занимает 2 такта генератора тактовой частоты. 20 | 21 | ## Формат команды 22 | - 0-й бит: команда, если 0, то команда записи из регистра-аккумулятора в адрес, заданный в битах 2...N, если 1 то чтение из адреса в регистр-аккумулятор 23 | - 1-й бит: условное выполнения, если значение 1 то текущая команда выполняется в любом случае, если 0 то выполнится только если в регистре-аккумуляторе не все нули 24 | - 2-N биты: адрес в little-endian 25 | 26 | ## Адресация 27 | Из-за особенностей представления кода 2 первых бита не используются в кодировании адреса, потому память для 4-х битного процессора адресуется 2-мя битами, т.е. всего 4 ячейки доступны, из них ячейка 00 отведена под 2-х битный program counter, 01 - RAM, 02, 03 - ПЗУ. Для адресации некоторого количества памяти нужно на 2 бита больше, например для адресации 64 КБ RAM памяти нужна разрядность процессора в 18 бит. 28 | 29 | ![screenshot](https://github.com/Alexey1994/simple-processor-circuit/blob/main/screenshot.png?raw=true) 30 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexey1994/simple-processor-circuit/cda47a18b3f3ccadc9b2e0d1cd0dff67542c9d5a/screenshot.png -------------------------------------------------------------------------------- /src/эмулятор/memory.c: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_INCLUDED 2 | #define MEMORY_INCLUDED 3 | 4 | 5 | #include "types.c" 6 | 7 | 8 | /*void print_bytes(Byte* bytes, Number size) 9 | { 10 | Number i; 11 | 12 | for(i = 0; i < size; ++i) { 13 | print("%x", bytes[i]); 14 | 15 | if(i != size - 1) 16 | print(", "); 17 | } 18 | 19 | print("\n"); 20 | }*/ 21 | 22 | 23 | void clean_bytes(Byte* bytes, Number size) 24 | { 25 | Number system_size; 26 | Number remind_size; 27 | 28 | system_size = size / sizeof(Number); 29 | remind_size = size % sizeof(Number); 30 | 31 | while(system_size) { 32 | *((Number*)bytes) = 0; 33 | 34 | --system_size; 35 | bytes += sizeof(Number); 36 | } 37 | 38 | while(remind_size) { 39 | *bytes = 0; 40 | 41 | --remind_size; 42 | ++bytes; 43 | } 44 | } 45 | 46 | 47 | void copy_bytes(Byte* destination, Byte* source, Number size) 48 | { 49 | Number system_size; 50 | Number remind; 51 | 52 | system_size = size / sizeof(Number); 53 | remind = size % sizeof(Number); 54 | 55 | while(system_size) { 56 | *((Number*)destination) = *((Number*)source); 57 | 58 | --system_size; 59 | destination += sizeof(Number); 60 | source += sizeof(Number); 61 | } 62 | 63 | while(remind) { 64 | *destination = *source; 65 | 66 | --remind; 67 | ++destination; 68 | ++source; 69 | } 70 | } 71 | 72 | 73 | void swap_bytes(Byte* bytes1, Byte* bytes2, Number size) 74 | { 75 | Number system_size; 76 | Number remind; 77 | Number system_temp; 78 | Byte temp; 79 | 80 | system_size = size / sizeof(Number); 81 | remind = size % sizeof(Number); 82 | 83 | while(system_size) { 84 | system_temp = *((Number*)bytes1); 85 | *((Number*)bytes1) = *((Number*)bytes2); 86 | *((Number*)bytes2) = system_temp; 87 | 88 | --system_size; 89 | bytes1 += sizeof(Number); 90 | bytes2 += sizeof(Number); 91 | } 92 | 93 | while(remind) { 94 | temp = *bytes1; 95 | *bytes1 = *bytes2; 96 | *bytes2 = temp; 97 | 98 | --remind; 99 | ++bytes1; 100 | ++bytes2; 101 | } 102 | } 103 | 104 | 105 | Integer_Number compare_bytes(Byte* bytes1, Number number_of_bytes1, Byte* bytes2, Number number_of_bytes2) 106 | { 107 | Integer_Number difference; 108 | 109 | while(number_of_bytes1 && number_of_bytes2) { 110 | difference = (Integer_Number)*bytes1 - (Integer_Number)*bytes2; 111 | 112 | if(difference) 113 | return difference; 114 | 115 | ++bytes1; 116 | ++bytes2; 117 | --number_of_bytes1; 118 | --number_of_bytes2; 119 | } 120 | 121 | return (Integer_Number)number_of_bytes1 - (Integer_Number)number_of_bytes2; 122 | } 123 | 124 | 125 | Integer_Number compare_null_terminated_bytes(Byte* bytes1, Byte* bytes2) 126 | { 127 | Integer_Number difference; 128 | 129 | while(*bytes1 && *bytes2) { 130 | difference = (Integer_Number)*bytes1 - (Integer_Number)*bytes2; 131 | 132 | if(difference) 133 | return difference; 134 | 135 | ++bytes1; 136 | ++bytes2; 137 | } 138 | 139 | return (Integer_Number)*bytes1 - (Integer_Number)*bytes2; 140 | } 141 | 142 | 143 | Integer_Number compare_null_terminated_words(Bit16* words1, Bit16* words2) 144 | { 145 | Integer_Number difference; 146 | 147 | while(*words1 && *words2) { 148 | difference = (Integer_Number)*words1 - (Integer_Number)*words2; 149 | 150 | if(difference) 151 | return difference; 152 | 153 | ++words1; 154 | ++words2; 155 | } 156 | 157 | return (Integer_Number)*words1 - (Integer_Number)*words2; 158 | } 159 | 160 | 161 | void revert_bytes_order(Byte* bytes, Number size) 162 | { 163 | Byte temp; 164 | Number i; 165 | 166 | for(i = 0; i < size / 2; ++i) { 167 | temp = bytes[i]; 168 | bytes[i] = bytes[size - i - 1]; 169 | bytes[size - i - 1] = temp; 170 | } 171 | } 172 | 173 | 174 | 175 | #endif//MEMORY_INCLUDED 176 | 177 | /* 178 | void main() 179 | { 180 | Number i; 181 | Byte bytes1[5] = {1, 2, 3, 4, 5}; 182 | Byte bytes2[5] = {}; 183 | 184 | if(0) { 185 | clean_bytes(bytes1, 5); 186 | print_bytes(bytes1, 5); 187 | } 188 | 189 | if(0) { 190 | copy_bytes(bytes2, bytes1, 5); 191 | print_bytes(bytes2, 5); 192 | } 193 | 194 | if(0) { 195 | swap_bytes(bytes1, bytes2, 5); 196 | print_bytes(bytes1, 5); 197 | print_bytes(bytes2, 5); 198 | } 199 | 200 | if(0) { 201 | revert_bytes_order(bytes1, 5); 202 | print_bytes(bytes1, 5); 203 | } 204 | }*/ -------------------------------------------------------------------------------- /src/эмулятор/program.c: -------------------------------------------------------------------------------- 1 | // inc a 2 | Number repeat = constant_value(0); 3 | Number next = constant_value(0); 4 | Number end = constant_value(0); 5 | 6 | Number zero = constant_value(0); 7 | Number one = constant_value(1); 8 | Number rezak_value = constant_value(0xFFFE); 9 | Number a = constant_value(15); 10 | 11 | Number shifter = variable(); 12 | Number l1 = variable(); 13 | Number rezak = variable(); 14 | Number a_copy = variable(); 15 | 16 | COPY(a, a_copy) 17 | COPY(one, shifter) 18 | COPY(rezak_value, rezak) 19 | 20 | LABEL("repeat") 21 | AND(a_copy, shifter, l1) 22 | IF(next) 23 | 24 | OR(a_copy, shifter, a_copy) 25 | JUMP(end) 26 | 27 | LABEL("next") { 28 | AND(a_copy, rezak, a_copy); 29 | SHIFT_LEFT(rezak, rezak) 30 | OR(rezak, one, rezak) 31 | SHIFT_LEFT(shifter, shifter) 32 | IF(repeat) 33 | } 34 | 35 | LABEL("end") 36 | 37 | 38 | memory[repeat] = find_label("repeat"); 39 | memory[next] = find_label("next"); 40 | memory[end] = find_label("end"); 41 | 42 | 43 | //AND(a, one, r); 44 | //r = a & b 45 | //c = a ? 0 : 1 46 | 47 | /* 48 | // a + b 49 | Number a; 50 | Number b; 51 | Number c; 52 | 53 | a = constant_value(12); 54 | b = constant_value(23); 55 | c = variable(); 56 | 57 | ADD(a, b, c) 58 | */ 59 | 60 | /* 61 | Number initial_index; 62 | Number one; 63 | Number index; 64 | Number cycle; 65 | 66 | initial_index = constant_value(DATA_MASK - 3); 67 | one = constant_value(1); 68 | index = variable(); 69 | cycle = constant_value(0); 70 | 71 | COPY(initial_index, index) 72 | LABEL("cycle") 73 | ADD(index, one, index) 74 | IF(cycle) 75 | 76 | memory[cycle] = find_label("cycle"); 77 | */ 78 | 79 | /* 80 | //SUB 81 | Number one; 82 | Number a; 83 | Number b; 84 | Number c; 85 | 86 | one = constant_value(1); 87 | a = constant_value(7); 88 | b = constant_value(3); 89 | c = variable(); 90 | 91 | NOT(b, c) 92 | ADD(c, one, c) 93 | ADD(c, a, c) 94 | */ 95 | 96 | /* 97 | //MUL 98 | Number zero; 99 | Number one; 100 | Number a; 101 | Number b; 102 | Number initial_index; 103 | Number c; 104 | Number index; 105 | Number a_copy; 106 | Number b_copy; 107 | Number b_copy2; 108 | Number repeat; 109 | Number add_a; 110 | Number skip_add_a; 111 | 112 | zero = constant_value(0); 113 | one = constant_value(1); 114 | a = constant_value(16); 115 | b = constant_value(31); 116 | initial_index = constant_value(DATA_MASK - BITNESS); 117 | 118 | c = variable(); 119 | index = variable(); 120 | a_copy = variable(); 121 | b_copy = variable(); 122 | b_copy2 = variable(); 123 | 124 | repeat = constant_value(0); 125 | add_a = constant_value(0); 126 | skip_add_a = constant_value(0); 127 | 128 | COPY(zero, c) // c = 0 129 | COPY(initial_index, index) // index = DATA_MASK - BITNESS 130 | COPY(a, a_copy) // a_copy = a 131 | COPY(b, b_copy) // b_copy = b 132 | LABEL("repeat") 133 | COPY(b_copy, b_copy2) // repeat: b_copy2 = b_copy 134 | AND(b_copy2, one, b_copy2) // b_copy2 &= 1 135 | IF(add_a) // b_copy2 => add_a 136 | JUMP(skip_add_a) // 1 => skip_add_a 137 | LABEL("add_a") 138 | ADD(c, a_copy, c) // add_a: c += a_copy 139 | LABEL("skip_add_a") 140 | SHIFT_LEFT(a_copy, a_copy) // skip_add_a: a_copy <<= 1 141 | SHIFT_RIGHT(b_copy, b_copy) // b_copy >>= 1 142 | ADD(index, one, index) // index += 1 143 | IF(repeat) // index => repeat 144 | 145 | memory[repeat] = find_label("repeat"); 146 | memory[add_a] = find_label("add_a"); 147 | memory[skip_add_a] = find_label("skip_add_a");*/ 148 | 149 | 150 | /* 151 | #define RETURN_ADDRESS 0 152 | #define RETURN {ADD(VARIABLE(RETURN_ADDRESS), CONSTANT(2), VARIABLE(RETURN_ADDRESS)); JUMP(VARIABLE(RETURN_ADDRESS));} 153 | #define CALL(address) {COPY(OPERATION_INDEX, VARIABLE(RETURN_ADDRESS)); JUMP(address);} 154 | 155 | 156 | CONSTANT_VALUE (0, 1) 157 | CONSTANT_VALUE (1, 1) 158 | CONSTANT_VALUE (2, 3) //добавка к return 159 | 160 | CONSTANT_VALUE (3, 15) 161 | CONSTANT_VALUE (4, 6) 162 | 163 | COPY(CONSTANT(3), VARIABLE(1)) 164 | COPY(CONSTANT(4), VARIABLE(2)) 165 | CALL(CONSTANT(6)) 166 | JUMP(CONSTANT(5)) 167 | 168 | LABEL("SUB") 169 | CONSTANT_VALUE (6, find_label("SUB")) 170 | NOT(VARIABLE(2), VARIABLE(2)) 171 | ADD(VARIABLE(2), CONSTANT(1), VARIABLE(2)) 172 | ADD(VARIABLE(1), VARIABLE(2), VARIABLE(1)) 173 | RETURN 174 | 175 | LABEL("MUL") 176 | CONSTANT_VALUE (7, find_label("MUL")) 177 | CONSTANT_VALUE (4, DATA_MASK - BITNESS) 178 | 179 | COPY (CONSTANT(0), VARIABLE(0)) // result = 0 180 | COPY (CONSTANT(4), VARIABLE(1)) // i = DATA_MASK - BITNESS 181 | COPY (CONSTANT(2), VARIABLE(2)) // a_copy = a 182 | COPY (CONSTANT(3), VARIABLE(3)) // b_copy = b 183 | LABEL("repeat") 184 | COPY (VARIABLE(3), VARIABLE(4)) // repeat: b_copy2 = b_copy 185 | AND (VARIABLE(4), CONSTANT(1), VARIABLE(4)) // b_copy2 &= 1 186 | IF (CONSTANT(6)) // b_copy2 => add_a 187 | JUMP (CONSTANT(7)) // 1 => skip_add_a 188 | LABEL("add_a") 189 | ADD (VARIABLE(0), VARIABLE(2), VARIABLE(0)) // add_a: result += a_copy 190 | LABEL("skip_add_a") 191 | SHIFT_LEFT(VARIABLE(2), VARIABLE(2)) // skip_add_a: a_copy <<= 1 192 | SHIFT_RIGHT(VARIABLE(3), VARIABLE(3)) // b_copy >>= 1 193 | ADD(VARIABLE(1), CONSTANT(1), VARIABLE(1)) // i += 1 194 | IF (CONSTANT(5)) // i => repeat 195 | 196 | CONSTANT_VALUE (5, find_label("repeat")) 197 | CONSTANT_VALUE (6, find_label("add_a")) 198 | CONSTANT_VALUE (7, find_label("skip_add_a")) 199 | RETURN 200 | 201 | 202 | LABEL("end") 203 | CONSTANT_VALUE (5, find_label("end"))*/ -------------------------------------------------------------------------------- /src/эмулятор/types.c: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_INCLUDED 2 | #define TYPES_INCLUDED 3 | 4 | 5 | typedef unsigned char Byte; 6 | typedef unsigned char Bit8; 7 | typedef unsigned short int Bit16; 8 | typedef unsigned long int Bit32; 9 | typedef unsigned long long int Bit64; 10 | 11 | typedef unsigned char Number8; 12 | typedef unsigned short int Number16; 13 | typedef unsigned long int Number32; 14 | typedef unsigned long long int Number64; 15 | typedef Number64 Number; 16 | 17 | typedef char Integer_Number8; 18 | typedef short int Integer_Number16; 19 | typedef long int Integer_Number32; 20 | typedef long long int Integer_Number64; 21 | typedef Integer_Number64 Integer_Number; 22 | 23 | typedef float Rational_Number32; 24 | typedef double Rational_Number64; 25 | typedef Rational_Number64 Rational_Number; 26 | 27 | typedef Number Boolean; 28 | 29 | 30 | #define stdcall __attribute__((__stdcall__)) 31 | #define cdecl __attribute__((__cdecl__)) 32 | #define import __attribute__((dllimport)) __attribute__((__stdcall__)) 33 | #define import_cdecl __attribute__((dllimport)) __attribute__((__cdecl__)) 34 | #define export __attribute__((dllexport)) __attribute__((__stdcall__)) 35 | #define export_cdecl __attribute__((dllexport)) __attribute__((__cdecl__)) 36 | 37 | 38 | #pragma pack(push, 1) //no align for structs 39 | 40 | 41 | //#include 42 | #define print(...) printf(__VA_ARGS__) 43 | 44 | 45 | #endif//TYPES_INCLUDED -------------------------------------------------------------------------------- /src/эмулятор/эмуляция.c: -------------------------------------------------------------------------------- 1 | #include "types.c" 2 | 3 | 4 | #define BITNESS 9 5 | #define DATA_MASK ((~(Number)0) >> (sizeof(Number) * 8 - BITNESS)) 6 | #define INDEX_MASK (DATA_MASK >> 2) 7 | #define PROGRAM_END (1 << (BITNESS - 2)) 8 | #define PROGRAM_START (PROGRAM_END / 2) 9 | 10 | 11 | typedef enum { 12 | LOAD_OPCODE = 0b00 << (BITNESS - 2), 13 | STORE_OPCODE = 0b01 << (BITNESS - 2), 14 | SKIP_IF_ZERO_OPCODE = 0b10 << (BITNESS - 2) 15 | } 16 | Opcode; 17 | 18 | 19 | #define OPERATION_INDEX 0 20 | 21 | #define OPERAND1_ADDRESS 1 22 | #define OPERAND2_ADDRESS 2 23 | 24 | #define SHIFT_LEFT_ADDRESS 3 25 | #define SHIFT_RIGHT_ADDRESS 4 26 | #define NOT_ADDRESS 5 27 | 28 | #define AND_ADDRESS 6 29 | #define OR_ADDRESS 7 30 | //#define ADD_ADDRESS 8 31 | 32 | 33 | // in_addr: OPERATION_INDEX, OPERATION 34 | // in_data: DATA 35 | // out_data: DATA, OPERATION 36 | 37 | 38 | Number program_end; 39 | 40 | 41 | void execute(Number memory[PROGRAM_END]) 42 | { 43 | Number previouse_load_address; 44 | 45 | Number operation; 46 | Number data_register; 47 | 48 | memory[OPERATION_INDEX] = PROGRAM_START; 49 | 50 | previouse_load_address = 0; 51 | 52 | while(memory[OPERATION_INDEX] != program_end) { 53 | memory[SHIFT_LEFT_ADDRESS] = (memory[OPERAND1_ADDRESS] << 1) & DATA_MASK; 54 | memory[SHIFT_RIGHT_ADDRESS] = (memory[OPERAND1_ADDRESS] >> 1) & DATA_MASK; 55 | memory[NOT_ADDRESS] = (~memory[OPERAND1_ADDRESS]) & DATA_MASK; 56 | 57 | memory[AND_ADDRESS] = ((memory[OPERAND1_ADDRESS] & DATA_MASK) & (memory[OPERAND2_ADDRESS] & DATA_MASK)) & DATA_MASK; 58 | memory[OR_ADDRESS] = ((memory[OPERAND1_ADDRESS] & DATA_MASK) | (memory[OPERAND2_ADDRESS] & DATA_MASK)) & DATA_MASK; 59 | //memory[ADD_ADDRESS] = ((memory[OPERAND1_ADDRESS] & DATA_MASK) + (memory[OPERAND2_ADDRESS] & DATA_MASK)) & DATA_MASK; 60 | 61 | operation = memory[memory[OPERATION_INDEX]] & DATA_MASK; 62 | 63 | if(!(operation & SKIP_IF_ZERO_OPCODE) || data_register) { 64 | if(operation & STORE_OPCODE) { 65 | if((operation & INDEX_MASK) >= PROGRAM_START) { 66 | print( 67 | "%x skip STORE in %x\n", 68 | memory[OPERATION_INDEX], 69 | operation & INDEX_MASK 70 | ); 71 | } 72 | else { 73 | print( 74 | "%x [%x] = [%x] = %x\n", 75 | memory[OPERATION_INDEX], 76 | operation & INDEX_MASK, 77 | previouse_load_address, 78 | data_register 79 | ); 80 | 81 | memory[operation & INDEX_MASK] = data_register; 82 | } 83 | } 84 | else { 85 | previouse_load_address = operation & INDEX_MASK; 86 | data_register = memory[operation & INDEX_MASK] & DATA_MASK; 87 | } 88 | } 89 | 90 | memory[OPERATION_INDEX] = (memory[OPERATION_INDEX] + 1) & DATA_MASK; 91 | } 92 | 93 | print("\n\n"); 94 | } 95 | 96 | 97 | #include "memory.c" 98 | 99 | 100 | #define LOAD(source) {memory[i] = LOAD_OPCODE | (source & INDEX_MASK); ++i;} 101 | #define STORE(target) {memory[i] = STORE_OPCODE | (target & INDEX_MASK); ++i;} 102 | #define LOAD_IF(source) {memory[i] = SKIP_IF_ZERO_OPCODE | LOAD_OPCODE | (source & INDEX_MASK); ++i;} 103 | #define STORE_IF(target) {memory[i] = SKIP_IF_ZERO_OPCODE | STORE_OPCODE | (target & INDEX_MASK); ++i;} 104 | 105 | #define IF(address_pointer) {LOAD_IF(address_pointer); STORE_IF(OPERATION_INDEX);} 106 | #define JUMP(address_pointer) {LOAD(address_pointer); STORE(OPERATION_INDEX);} 107 | 108 | #define COPY(source, target) {LOAD(source); STORE(target);} 109 | 110 | #define NOT(operand, target) {LOAD(operand); STORE(OPERAND1_ADDRESS); LOAD(NOT_ADDRESS); STORE(target);} 111 | #define SHIFT_LEFT(operand, target) {LOAD(operand); STORE(OPERAND1_ADDRESS); LOAD(SHIFT_LEFT_ADDRESS); STORE(target);} 112 | #define SHIFT_RIGHT(operand, target) {LOAD(operand); STORE(OPERAND1_ADDRESS); LOAD(SHIFT_RIGHT_ADDRESS); STORE(target);} 113 | 114 | #define AND(operand1, operand2, target) {LOAD(operand1); STORE(OPERAND1_ADDRESS); LOAD(operand2); STORE(OPERAND2_ADDRESS); LOAD(AND_ADDRESS); STORE(target);} 115 | #define OR(operand1, operand2, target) {LOAD(operand1); STORE(OPERAND1_ADDRESS); LOAD(operand2); STORE(OPERAND2_ADDRESS); LOAD(OR_ADDRESS); STORE(target);} 116 | //#define ADD(operand1, operand2, target) {LOAD(operand1); STORE(OPERAND1_ADDRESS); LOAD(operand2); STORE(OPERAND2_ADDRESS); LOAD(ADD_ADDRESS); STORE(target);} 117 | 118 | #define CONSTANT_VALUE(index, value) {memory[PROGRAM_END - 1 - index] = value;} 119 | 120 | #define VARIABLE(index) (8 + index) 121 | #define CONSTANT(index) (PROGRAM_END - 1 - index) 122 | 123 | 124 | Number memory[PROGRAM_END] = {0}; 125 | 126 | 127 | Number last_constant_index = 0; 128 | 129 | Number constant_value(Number value) 130 | { 131 | Number index; 132 | 133 | index = PROGRAM_END - 1 - last_constant_index; 134 | ++last_constant_index; 135 | 136 | memory[index] = value; 137 | 138 | return index; 139 | } 140 | 141 | 142 | Number last_variable_index = 0; 143 | 144 | Number variable() 145 | { 146 | Number index; 147 | 148 | index = VARIABLE(last_variable_index); 149 | ++last_variable_index; 150 | 151 | return index; 152 | } 153 | 154 | 155 | typedef struct { 156 | Byte name[12]; 157 | Number address; 158 | } 159 | Label; 160 | 161 | 162 | Label labels[128]; 163 | Number last_label_index = 0; 164 | 165 | 166 | #define LABEL(label_name) {copy_bytes(labels[last_label_index].name, label_name, 12); labels[last_label_index].address = i; ++last_label_index;} 167 | 168 | Number find_label(Byte* label_name) 169 | { 170 | Number i; 171 | 172 | for(i = 0; i < sizeof(labels) / sizeof(Label); ++i) { 173 | if(!compare_null_terminated_bytes(label_name, labels[i].name)) 174 | return labels[i].address - 1; 175 | } 176 | 177 | print("label %s not found\n", label_name); 178 | 179 | return 0; 180 | } 181 | 182 | 183 | Number main() 184 | { 185 | Number operation; 186 | Number i; 187 | 188 | clean_bytes(memory, PROGRAM_END * sizeof(Number)); 189 | i = PROGRAM_START; 190 | 191 | { 192 | #include "program.c" 193 | } 194 | 195 | program_end = i; 196 | execute(memory); 197 | 198 | for(i = PROGRAM_START; i < PROGRAM_END; ++i) { 199 | operation = memory[i]; 200 | 201 | if(i < program_end) { 202 | if(operation & SKIP_IF_ZERO_OPCODE) { 203 | if(operation & STORE_OPCODE) { 204 | if((operation & INDEX_MASK) >= PROGRAM_START) { 205 | print("error "); 206 | } 207 | 208 | print("%x STORE IF %x\n", i, operation & INDEX_MASK); 209 | } 210 | else { 211 | print("%x LOAD IF %x\n", i, operation & INDEX_MASK); 212 | } 213 | } 214 | else { 215 | if(operation & STORE_OPCODE) { 216 | if((operation & INDEX_MASK) >= PROGRAM_START) { 217 | print("error "); 218 | } 219 | 220 | print("%x STORE %x\n", i, operation & INDEX_MASK); 221 | } 222 | else { 223 | print("%x LOAD %x\n", i, operation & INDEX_MASK); 224 | } 225 | } 226 | } 227 | else 228 | print("%x %d\n", i, operation); 229 | } 230 | 231 | print("\n"); 232 | 233 | for(i = 8; i < PROGRAM_START; ++i) { 234 | print("%x %d\n", i, memory[i]); 235 | } 236 | } --------------------------------------------------------------------------------