diff --git a/Makefile b/Makefile
index ed9fdc1..f83193b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ GENERATED = build dist *.egg-info
 
 all : test lint pep257 dist
 
-twine :
+twine : dist
 	twine upload dist/*
 
 clean :
diff --git a/README.md b/README.md
index 0c15024..5460313 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,16 @@
 # modelmachine
 Model machine emulator
 
-[![Build Status](https://travis-ci.org/cmc-python/modelmachine.svg?branch=master)](https://travis-ci.org/cmc-python/modelmachine)
+[![Build Status](https://travis-ci.org/vslutov/modelmachine.svg?branch=master)](https://travis-ci.org/vslutov/modelmachine)
 
 ## TODO
 
-* УМ-Р (регистровая)
-* УМ с модификацией адресов ???
-
-* Изменить базовую концепцию memory->integer и переписать модули
-* Добавить test.alu.swap
+* Проверить test.alu.swap
 * Работа с плавающей запятой
 * Подумать еще о mock в тестах
-* Подумать о команде остановки halt
 * Переделать документацию модулей
 * Исправить опечатки в документации
 * Расширить howto
-* ГУИ
 
 ## Модельная машина
 
@@ -91,8 +85,8 @@ Model machine emulator
 * `numeric.py` - целочисленная арифметика с фиксированным числом
   двоичных знаков
 * `alu.py` - арифметико-логическое устройство, работает с четко
-  специализированными регистрами: `R1`, `R2`, `S`, `FLAGS` и `IP`.
-* `cu.py` *в процессе реализации* - контролирующее устройство, выполняющее
+  специализированными регистрами: `R1`, `R2`, `S`, `FLAGS` и `PC`.
+* `cu.py` - контролирующее устройство, выполняющее
   считывание команд из памяти и запускающее необходимые методы в
   арифметико-логическом устройстве
 * `io.py` - устройство ввода-вывода
@@ -131,7 +125,7 @@ Model machine emulator
 
 * `R1`, `R2`, `S` для арифметических операций.
 * `FLAGS` для хранения флагов состояния.
-* `IP` *только* для пересылки туда адреса из регистра `R1` при условных
+* `PC` *только* для пересылки туда адреса из регистра `R1` при условных
   переходах.
 
 Схема работы:
@@ -148,7 +142,7 @@ Model machine emulator
   остатком. `S := R1 / R2; R1 := R1 % R2`.
 * Команда пересылки `move`: `S := R1`.
 * Команды безусловного перехода `jump` и условного перехода `cond_jump`
-  работают по схеме `IP := R1`, режим работы `cond_jump` зависит от того,
+  работают по схеме `PC := R1`, режим работы `cond_jump` зависит от того,
   какие дополнительные аргументы будут переданы.
 * Команда останова `halt` просто выставляет флаг остановки HALT в
   регистре флагов
@@ -163,8 +157,8 @@ Model machine emulator
 
 1. `fetch_and_decode` - загрузка и расшифровка очередной команды.
    Содержимое ячейки оперативной памяти с адресом записанным
-   в регистре `IP` загружается в регистр `IR`, затем из него извлекается
-   код операции и адреса операндов, затем счетчик `IP` увеличивается на
+   в регистре `PC` загружается в регистр `RI`, затем из него извлекается
+   код операции и адреса операндов, затем счетчик `PC` увеличивается на
    длину только что считанной команды.
 2. `load` - данные по только что считанным адресам загружаются в регистры
    процессора `R1` и `R2`
@@ -225,9 +219,9 @@ Model machine emulator
 
 ### Таблица команд модельных машин
 
-|OPCODE|mm-3 |mm-2 |mm-v |mm-1 |mm-st |
+|OPCODE|mm-3 |mm-2 |mm-v |mm-1 |mm-m  |
 |:-----|:---:|:---:|:---:|:---:|:----:|
-|0x00  |move |move |move |load |      |
+|0x00  |move |move |move |load | load |
 |0x01  | add | add | add | add | add  |
 |0x02  | sub | sub | sub | sub | sub  |
 |0x03  |smul |smul |smul |smul | smul |
@@ -235,12 +229,15 @@ Model machine emulator
 |0x05  |     |comp |comp |comp | comp |
 |0x13  |umul |umul |umul |umul | umul |
 |0x14  |udiv |udiv |udiv |udiv | udiv |
-|0x10  |     |     |     |store|      |
-|0x20  |     |     |     |swap |      |
-|0x5A  |     |     |     |     |stpush|
-|0x5B  |     |     |     |     |stpop |
-|0x5C  |     |     |     |     |stdup |
-|0x5D  |     |     |     |     |stswap|
+|0x10  |     |     |     |store|store |
+|0x20  |     |     |     |swap | move |
+|0x21  |     |     |     |     | radd |
+|0x22  |     |     |     |     | rsub |
+|0x23  |     |     |     |     |rsmul |
+|0x24  |     |     |     |     |rsdiv |
+|0x25  |     |     |     |     |rcomp |
+|0x33  |     |     |     |     |rumul |
+|0x34  |     |     |     |     |rudiv |
 |0x80  |jump |jump |jump |jump | jump |
 |0x81  | jeq | jeq | jeq | jeq | jeq  |
 |0x82  |jneq |jneq |jneq |jneq | jneq |
@@ -273,7 +270,7 @@ Model machine emulator
 |ujleq            |     <= u       |unsigned jump if less or equal   |
 |ujg              |     >  u       |unsigned jump if greater         |
 
-### mm3
+### mm-3
 
 Архитектура трехадресной модельной машины.
 
@@ -281,15 +278,15 @@ Model machine emulator
 * Размер адреса: 2 байта.
 * Арифметические вычисления производятся с одной ячейкой оперативной памяти.
 * Код команды помещается в одну ячейку оперативной памяти `КОП А1 А2 А3`.
-* Регистры: `S`, `R1`, `R2`, `FLAGS`, `IP`, `IR`, `ADDR`.
+* Регистры: `S`, `R1`, `R2`, `FLAGS`, `PC`, `RI`, `ADDR`.
 
 Назначение регистров:
 
 * `S` - регистр сумматор, в него записывается результат арифметической операции.
 * `R1`, `R2` - регистры операндов арифметических операций.
 * `FLAGS` - регистр флагов.
-* `IP` - регистр указатель инструкции.
-* `IR` - регистр для хранения инструкции.
+* `PC` - регистр указатель инструкции.
+* `RI` - регистр для хранения инструкции.
 * `ADDR` - регистр для хранения адреса для инструкции перехода.
 
 Действия процессора для арифметических инструкций (`add`, `sub`,
@@ -306,12 +303,12 @@ Model machine emulator
    два результата: частное – в ячейку с адресом `А3`, остаток – в следующую
    ячейку, по адресу `(А3+1) mod 16^4`.
 
-* `jump A1 A2 A3`: `IP := A3`
+* `jump A1 A2 A3`: `PC := A3`
 * Условные переходы: сравниваются `R1` и `R2`, в зависимости от результата
-  происходит `IP := A3`.
+  происходит `PC := A3`.
 * Команда пересылки `move`: [A3] := R1.
 
-### mm2
+### mm-2
 
 Архитектура двухадресной модельной машины.
 
@@ -319,7 +316,7 @@ Model machine emulator
 * Размер адреса: 2 байта.
 * Арифметические вычисления производятся с одной ячейкой оперативной памяти.
 * Код команды помещается в одну ячейку оперативной памяти `КОП А1 А2`.
-* Регистры: `R1`, `R2`, `FLAGS`, `IP`, `IR`, `ADDR`.
+* Регистры: `R1`, `R2`, `FLAGS`, `PC`, `RI`, `ADDR`.
 
 Действия для арифметических команд `add`, `sub`, `smul`, `sdiv`, `umul`,
 `udiv`:
@@ -333,12 +330,12 @@ Model machine emulator
 1. `R1 := [A1], R2 := [A2]`
 2. Запустить в АЛУ схему `sub`, выставить регистр `FLAGS`
 
-* `jump A1 A2`: `IP := A2`
+* `jump A1 A2`: `PC := A2`
 * Условные переходы делаются исходя из регистра `FLAGS`
 * `move A1 A2`: `[A1] := [A2]`
 * Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
 
-### mmv
+### mm-v
 
 Архитектура модельной машины с переменным (variable) фарматом команд.
 
@@ -348,7 +345,7 @@ Model machine emulator
   памяти.
 * Код команды занимает разное количество ячеек в зависимости от выполняемой
   операции.
-* Регистры: `R1`, `R2`, `FLAGS`, `IP`, `IR`, `ADDR`.
+* Регистры: `R1`, `R2`, `FLAGS`, `PC`, `RI`, `ADDR`.
 
 Таблица кодов команд:
 
@@ -387,12 +384,12 @@ Model machine emulator
 1. `R1 := [A1], R2 := [A2]`
 2. Запустить в АЛУ схему `sub`, выставить регистр `FLAGS`
 
-* `jump A1`: `IP := A1`
+* `jump A1`: `PC := A1`
 * Условные переходы делаются исходя из регистра `FLAGS`
 * `move A1 A2`: `[A1] := [A2]`
 * Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
 
-### mm1
+### mm-1
 
 Архитектура одноадресной модельной машины.
 
@@ -400,7 +397,7 @@ Model machine emulator
 * Размер адреса: 2 байта.
 * Арифметические вычисления производятся с одной ячейкой оперативной памяти.
 * Код команды помещается в одну ячейку оперативной памяти `КОП А`.
-* Регистры: `S`, `R`, `S1`, `FLAGS`, `IP`, `IR`.
+* Регистры: `S`, `R`, `S1`, `FLAGS`, `PC`, `RI`.
 
 Регистры `S` и `S1` хранят информацию постоянно, а не затираются при
 выполнении очередной команды, как было раньше. В регистр `R` закгружается
@@ -422,108 +419,123 @@ Model machine emulator
 1. `R := [A]`
 2. Запустить в АЛУ схему `sub`, выставить регистр `FLAGS`
 
-* `jump A`: `IP := A`
+* `jump A`: `PC := A`
 * Условные переходы делаются исходя из регистра `FLAGS`
 * `load A`: `S := [A]`
 * `store A`: `[A] := S`
 * `swap`: `S, S1 := S1, S`
 * Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
 
-### mmst
+### mm-m
 
-Архитектура стековой (stack) модельной машины.
+Архитектура модельной машины с модификацией адресов (modification).
 
-* Размер ячейки оперативной памяти: 1 байт.
+* Размер ячейки оперативной памяти: 2 байта.
 * Размер адреса: 2 байта.
-* Арифметические вычисления производятся со словом в 3 байта.
+* Арифметические вычисления производятся со словом в 4 байта.
 * Код команды занимает разное количество ячеек в зависимости от выполняемой
-  операции. Большинство команд безадресные, имеют формат `КОП` и занимают
-  1 байт. Некоторые команды работы со стеком и команды перехода имеют
-  один операнд, формат `КОП А` и занимают 3 байта.
-* Регистры: `R1`, `R2`, `FLAGS`, `IP`, `IR`, `SP`.
-
-Регистр `SP` - указатель стека (stack pointer) указывает на вершину стека.
+  операции. Арифметические команды имеют формы регистр-регистр и регистр-память.
+  Команды регистр-регистр имеют формат `КОП RA1 RA2` и занимают 2 байта.
+  Команды регистр-память имеют формат `КОП R M A` и занимают 4 байта.
+  Команды перехода имеют формат `КОП 0 0 A` и занимают 4 байта.
+* Регистры: `R0-RF`, `S`, `RZ`, `FLAGS`, `PC`, `RI`.
+
+Основное отличие этой машины от предыдущих - наличие адресуемых регистров
+общего назначения `R0-RF`, используемых для арифметических
+вычислений и адресации памяти. `S`, `RZ` - неадресуемые регистры для работы
+АЛУ.
+
+Также адресация данных теперь производится таким алгоритмом:
+
+1. Возьмем содержимое адресуемого регистра с номером `M` (от 0x0 до 0xF): `[M]`.
+   Если номер регистра `M` равен нулю, значение `[M]` также равно нулю вне
+   зависимости от содержимого регистра `R0`.
+2. Добавим к нему адрес `A` (от 0x0000 до 0xFFFF): `[M] + A`.
+3. Возьмем остаток от деления этого адреса на 2^16: `([M] + A) % 2^16`.
+4. Возьмем из ОЗУ данные по полученному адресу: `[[M] + A]`.
 
 Таблица кодов команд:
 
-|Код команды|Мнемоник|Формат   |Длина (в байтах)|
-|:----------|:------:|:--------|---------------:|
-|0x01       |add     |add      |               1|
-|0x02       |sub     |sub      |               1|
-|0x03       |smul    |smul     |               1|
-|0x04       |sdiv    |sdiv     |               1|
-|0x05       |comp    |comp     |               1|
-|0x13       |umul    |umul     |               1|
-|0x14       |udiv    |udiv     |               1|
-|0x5A       |stpush  |stpush A |               3|
-|0x5B       |stpop   |stpop  A |               3|
-|0x5C       |stdup   |stdup    |               1|
-|0x5D       |stswap  |stswap   |               1|
-|0x80       |jump    |jump  A  |               3|
-|0x81       |jeq     |jeq   A  |               3|
-|0x82       |jneq    |jneq  A  |               3|
-|0x83       |sjl     |sjl   A  |               3|
-|0x84       |sjgeq   |sjgeq A  |               3|
-|0x85       |sjleq   |sjleq A  |               3|
-|0x86       |sjg     |sjg   A  |               3|
-|0x93       |ujl     |ujl   A  |               3|
-|0x94       |ujgeq   |ujgeq A  |               3|
-|0x95       |ujleq   |ujleq A  |               3|
-|0x96       |ujg     |ujg   A  |               3|
-|0x99       |halt    |halt     |               1|
-
-Как действует метод `push(value)`:
-
-1. `SP -= value_size`
-2. `[SP] := value`
-
-Как действует метод `pop()`:
-
-1. `value := [SP]`
-2. `SP += value_size`
-2. `return value`
-
-Принцип работы стековых команд:
-
-В стек `stpush A`:
-
-1. `R1 := [A]`
-2. `push(R1)`
-
-Из стека `stpop A`:
-
-1. `R1 := pop()`
-2. `[A] := R1`
-
-Дублирование `stdup`:
-
-1. `R1 := pop()`
-2. `push(R1); push(R1)`
-
-Обмен `stswap`:
-
-1. `R1 := pop(); R2 := pop()`
-2. `push(R1); push(R2)`
-
-Действия для арифметических команд (исключая деление) `add`, `sub`, `smul`,
-`umul`:
-
-1. `R2 := pop(); R1 := pop()`
-2. `R1 := R1 op R2`
-3. `push(R1)`
-
-Действия для команд деления `sdivmod` и `udivmod`:
-
-1. `R2 := pop(); R1 := pop()`
-2. `R1, R2 := R1 / R2, R1 % R2`
-3. `push(R1); push(R2)`
-
-Действия для команды сравнения `cmp`:
-
-1. `R2 := pop(), R1 := pop()`
-2. Запустить в АЛУ схему `sub`, выставить регистр `FLAGS`
-
-* `jump A1`: `IP := A1`
+|Код команды|Мнемоник|Формат     |Длина (в байтах)|
+|:----------|:------:|:----------|---------------:|
+|0x00       |load    |load R M A |               4|
+|0x01       |add     |add R M A  |               4|
+|0x02       |sub     |sub R M A  |               4|
+|0x03       |smul    |smul R M A |               4|
+|0x04       |sdiv    |sdiv R M A |               4|
+|0x05       |comp    |comp R M A |               4|
+|0x13       |umul    |umul R M A |               4|
+|0x14       |udiv    |udiv R M A |               4|
+|0x10       |store   |store R M A|               4|
+|0x20       |rmove   |rmove RX RY|               2|
+|0x21       |radd    |radd RX RY |               2|
+|0x22       |rsub    |rsub RX RY |               2|
+|0x23       |rsmul   |rsmul RX RY|               2|
+|0x24       |rsdiv   |rsdiv RX RY|               2|
+|0x25       |rcomp   |rcomp RX RY|               2|
+|0x33       |rumul   |rumul RX RY|               2|
+|0x34       |rudiv   |rudiv RX RY|               2|
+|0x80       |jump    |jump 0 M A |               4|
+|0x81       |jeq     |jeq 0 M A  |               4|
+|0x82       |jneq    |jneq 0 M A |               4|
+|0x83       |sjl     |sjl 0 M A  |               4|
+|0x84       |sjgeq   |sjgeq 0 M A|               4|
+|0x85       |sjleq   |sjleq 0 M A|               4|
+|0x86       |sjg     |sjg 0 M A  |               4|
+|0x93       |ujl     |ujl 0 M A  |               4|
+|0x94       |ujgeq   |ujgeq 0 M A|               4|
+|0x95       |ujleq   |ujleq 0 M A|               4|
+|0x96       |ujg     |ujg 0 M A  |               4|
+|0x99       |halt    |halt 00    |               2|
+
+Действия для арифметических команд регистр-память (исключая деление) `add`,
+`sub`, `smul`, `umul` (формат `op R M A`):
+
+1. `S, RZ := R, [[M] + A]`
+2. `S := S op RZ`
+3. `R := S`
+
+Действия для команд деления регистр-память `sdivmod` и `udivmod`
+(формат `op R M A`, `R_next` - регистр, следующий за регистром `R`):
+
+1. `S, RZ := S, [[M] + A]`
+2. `S, RZ := S / RZ, S % RZ`
+3. `R, R_next := S, RZ`
+
+Действия для команды сравнения `comp R M A`:
+
+1. `S, RZ := S, [[M] + A]`
+2. Запустить в АЛУ схему `sub S RZ`, выставить регистр `FLAGS`
+
+Действия для команды загрузки `load R M A`:
+
+1. `R := [[M] + A]`
+
+Действия для команды выгрузки `store R M A`:
+
+1. `[[M] + A] := R`
+
+Действия для арифметических команд регистр-регистр (исключая деление) `radd`,
+`rsub`, `rsmul`, `rumul` (формат `op RX RY`):
+
+1. `S, RZ := RX, RY`
+2. `S := S op RZ`
+3. `RX := S`
+
+Действия для команд деления регистр-регистр `rsdiv` и `rudiv`
+(формат - `op RX RY`; `RX_next` - регистр, следующий за регистром `RX`, если
+`RX = RF`, то `RX_next = R0`):
+
+1. `S, RZ := RX, RY`
+2. `S, RZ := S / RZ, S % RZ`
+3. `RX, RX_next := S, RZ`
+
+Действия для команды сравнения `rcomp RX RY`:
+
+1. `S, RZ := RX, RY`
+2. Запустить в АЛУ схему `sub S RZ`, выставить регистр `FLAGS`
+
+* `jump 00 A`: `PC := A`
 * Условные переходы делаются исходя из регистра `FLAGS`
 * Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
 
diff --git a/modelmachine/__main__.py b/modelmachine/__main__.py
index 852943e..ffaaf6a 100644
--- a/modelmachine/__main__.py
+++ b/modelmachine/__main__.py
@@ -5,7 +5,7 @@
 from modelmachine.ide import get_program, get_cpu, debug
 import pytest, os, sys, argparse
 
-VERSION = "0.0.6" # Don't forget fix in setup.py
+VERSION = "0.1.0" # Don't forget fix in setup.py
 
 def run_program(args):
     cpu = get_program(args.filename, args.protect_memory)
@@ -32,7 +32,7 @@ def main(argv, stdout):
                        help='print version and exit')
 
     parser.add_argument('-m', '--protect_memory', action='store_true', default=False,
-                        help='raise an error if try to read dirty memory')
+                        help='raise an error, if program tries read dirty memory')
     subparsers = parser.add_subparsers(title='commands',
                                        help='commands for model machine emulator')
 
diff --git a/modelmachine/cpu.py b/modelmachine/cpu.py
index 6eaec7e..6be0540 100644
--- a/modelmachine/cpu.py
+++ b/modelmachine/cpu.py
@@ -16,7 +16,7 @@ from modelmachine.cu import ControlUnit3 as BCU3
 from modelmachine.cu import ControlUnit2 as BCU2
 from modelmachine.cu import ControlUnitV as BCUV
 from modelmachine.cu import ControlUnit1 as BCU1
-from modelmachine.cu import ControlUnitS as BCUS
+from modelmachine.cu import ControlUnitM as BCUM
 from modelmachine.alu import ArithmeticLogicUnit
 from modelmachine.io import InputOutputUnit
 
@@ -107,7 +107,7 @@ class CPUMM3(AbstractCPU):
                                        register_names=self.register_names,
                                        operand_size=word_size,
                                        address_size=address_size)
-        self.control_unit = BCU3(instruction_size=word_size,
+        self.control_unit = BCU3(ir_size=word_size,
                                  registers=self.registers,
                                  ram=self.ram,
                                  alu=self.alu,
@@ -136,7 +136,7 @@ class CPUMM2(AbstractCPU):
                                        register_names=self.register_names,
                                        operand_size=word_size,
                                        address_size=address_size)
-        self.control_unit = BCU2(instruction_size=word_size,
+        self.control_unit = BCU2(ir_size=word_size,
                                  registers=self.registers,
                                  ram=self.ram,
                                  alu=self.alu,
@@ -195,7 +195,7 @@ class CPUMM1(AbstractCPU):
                                        register_names=self.register_names,
                                        operand_size=word_size,
                                        address_size=address_size)
-        self.control_unit = BCU1(instruction_size=word_size,
+        self.control_unit = BCU1(ir_size=word_size,
                                  registers=self.registers,
                                  ram=self.ram,
                                  alu=self.alu,
@@ -206,39 +206,39 @@ class CPUMM1(AbstractCPU):
                                        word_size=word_size)
 
 
-class CPUMMS(AbstractCPU):
+class CPUMMM(AbstractCPU):
 
-    """CPU stack model machine."""
+    """CPU address modification model machine."""
 
     def __init__(self, protect_memory):
         """See help(type(x))."""
         byte_size = 8
-        word_size = 3 * byte_size
-        address_size = 2 * byte_size
+        address_size = word_size = 2 * byte_size
+        operand_size = ir_size = 4 * byte_size
         memory_size = 2 ** address_size
-        self.ram = RandomAccessMemory(word_size=byte_size,
+        self.ram = RandomAccessMemory(word_size=word_size,
                                       memory_size=memory_size,
                                       endianess='big', # Unused
                                       is_protected=protect_memory)
         self.registers = RegisterMemory()
-        self.register_names = BCUS.register_names
+        self.register_names = BCUM.register_names
         self.alu = ArithmeticLogicUnit(registers=self.registers,
                                        register_names=self.register_names,
-                                       operand_size=word_size,
+                                       operand_size=operand_size,
                                        address_size=address_size)
-        self.control_unit = BCUS(ir_size=word_size,
+        self.control_unit = BCUM(ir_size=ir_size,
                                  registers=self.registers,
                                  ram=self.ram,
                                  alu=self.alu,
-                                 operand_size=word_size,
+                                 operand_size=operand_size,
                                  address_size=address_size)
         self.io_unit = InputOutputUnit(ram=self.ram,
                                        start_address=0,
-                                       word_size=word_size)
+                                       word_size=operand_size)
 
 
 CPU_LIST = {'mm3': CPUMM3,
             'mm2': CPUMM2,
             'mmv': CPUMMV,
             'mm1': CPUMM1,
-            'mms': CPUMMS}
+            'mmm': CPUMMM}
diff --git a/modelmachine/cu.py b/modelmachine/cu.py
index 33ae4dc..86ee0c7 100644
--- a/modelmachine/cu.py
+++ b/modelmachine/cu.py
@@ -3,6 +3,7 @@
 """Control unit parse instruction and give the commands to another part of computer."""
 
 from modelmachine.alu import HALT, LESS, GREATER, EQUAL
+from modelmachine.numeric import Integer
 
 RUNNING = 1
 HALTED = 2
@@ -80,6 +81,15 @@ class ControlUnit(AbstractControlUnit):
         "udivmod": 0x14,
 
         "swap": 0x20,
+        "rmove": 0x20,
+
+        "radd": 0x21,
+        "rsub": 0x22,
+        "rsmul": 0x23,
+        "rsdivmod": 0x24,
+        "rcomp": 0x25,
+        "rumul": 0x33,
+        "rudivmod": 0x34,
 
         "stpush": 0x5A,
         "stpop": 0x5B,
@@ -119,7 +129,6 @@ class ControlUnit(AbstractControlUnit):
                      OPCODES["stdup"], OPCODES["stswap"]}
 
     BINAR_OPCODES = ARITHMETIC_OPCODES | {OPCODES["comp"]}
-    MONAR_OPCODES = {OPCODES["halt"]}
 
     register_names = {"PC": "PC", "ADDR": "ADDR", "RI": "RI"}
     opcode = 0
@@ -231,10 +240,11 @@ class ControlUnit3(ControlUnit):
                       "R1": "R1", "R2": "R2", "S": "S", "RES": "R1",
                       "FLAGS": "FLAGS"}
 
-    def __init__(self, instruction_size, *vargs, **kvargs):
+    def __init__(self, ir_size, *vargs, **kvargs):
         """See help(type(x))."""
-        super().__init__(instruction_size, *vargs, **kvargs)
-        self.instruction_size = instruction_size
+        super().__init__(ir_size, *vargs, **kvargs)
+
+        self.instruction_size = ir_size
         self.opcodes = (self.ARITHMETIC_OPCODES | self.JUMP_OPCODES |
                         {self.OPCODES["move"],
                          self.OPCODES["halt"]})
@@ -309,12 +319,11 @@ class ControlUnit2(ControlUnit):
                       "R1": "R1", "R2": "R2", "S": "R1", "RES": "R2",
                       "FLAGS": "FLAGS"}
 
-    def __init__(self, instruction_size, *vargs, **kvargs):
+    def __init__(self, ir_size, *vargs, **kvargs):
         """See help(type(x))."""
-        super().__init__(instruction_size, *vargs, **kvargs)
-        self.instruction_size = instruction_size
+        super().__init__(ir_size, *vargs, **kvargs)
 
-        self.instruction_size = instruction_size
+        self.instruction_size = ir_size
         self.opcodes = (self.ARITHMETIC_OPCODES | self.JUMP_OPCODES |
                         {self.OPCODES["move"],
                          self.OPCODES["halt"],
@@ -473,12 +482,11 @@ class ControlUnit1(ControlUnit):
                       "R1": "S", "R2": "R", "S": "S", "RES": "S1",
                       "FLAGS": "FLAGS"}
 
-    def __init__(self, instruction_size, *vargs, **kvargs):
+    def __init__(self, ir_size, *vargs, **kvargs):
         """See help(type(x))."""
-        super().__init__(instruction_size, *vargs, **kvargs)
-        self.instruction_size = instruction_size
+        super().__init__(ir_size, *vargs, **kvargs)
 
-        self.instruction_size = instruction_size
+        self.instruction_size = ir_size
         self.opcodes = (self.ARITHMETIC_OPCODES | self.JUMP_OPCODES |
                         {self.OPCODES["load"],
                          self.OPCODES["store"],
@@ -537,137 +545,153 @@ class ControlUnit1(ControlUnit):
                                          self.operand_size)
             self.ram.put(self.address, value, self.operand_size)
 
-class ControlUnitS(ControlUnit):
+class ControlUnitM(ControlUnit):
 
-    """Control unit for stack model machine."""
+    """Control unit for address modification model machine."""
 
-    address = None
+    address = 0
+    register1 = ''
+    register2 = ''
 
-    register_names = {"PC": "PC", "ADDR": "ADDR", "RI": "RI", "SP": "SP",
-                      "R1": "R1", "R2": "R2", "S": "R1", "RES": "R2",
+    register_names = {"PC": "PC", "ADDR": "ADDR", "RI": "RI",
+                      "R1": "S", "R2": "RZ", "S": "S", "RES": "RZ",
                       "FLAGS": "FLAGS"}
 
+
+    REGISTER_OPCODES = {ControlUnit.OPCODES["radd"],
+                        ControlUnit.OPCODES["rsub"],
+                        ControlUnit.OPCODES["rsmul"],
+                        ControlUnit.OPCODES["rsdivmod"],
+                        ControlUnit.OPCODES["rumul"],
+                        ControlUnit.OPCODES["rudivmod"],
+                        ControlUnit.OPCODES["rmove"],
+                        ControlUnit.OPCODES["rcomp"]}
+
+    ARITHMETIC_OPCODES = (ControlUnit.ARITHMETIC_OPCODES
+                          | {ControlUnit.OPCODES["radd"],
+                             ControlUnit.OPCODES["rsub"],
+                             ControlUnit.OPCODES["rsmul"],
+                             ControlUnit.OPCODES["rsdivmod"],
+                             ControlUnit.OPCODES["rumul"],
+                             ControlUnit.OPCODES["rudivmod"]})
+
     def __init__(self, ir_size, *vargs, **kvargs):
         """See help(type(x))."""
         # dynamic instruction size
         super().__init__(ir_size, *vargs, **kvargs)
 
-        self.opcodes = (self.ARITHMETIC_OPCODES | self.JUMP_OPCODES |
-                        {self.OPCODES["stpush"], self.OPCODES["stpop"],
-                         self.OPCODES["stdup"], self.OPCODES["stswap"],
-                         self.OPCODES["halt"],
-                         self.OPCODES["comp"]})
+        self.reg_addr_size = 4
 
-        for reg in {"R1", "R2", "FLAGS"}:
+        self.opcodes = (self.ARITHMETIC_OPCODES
+                        | self.JUMP_OPCODES
+                        | self.REGISTER_OPCODES
+                        | {self.OPCODES["load"],
+                           self.OPCODES["store"],
+                           self.OPCODES["halt"],
+                           self.OPCODES["comp"]})
+
+        for reg in {"S", "RZ", "FLAGS", "R0", "R1", "R2", "R3", "R4",
+                    "R5", "R6", "R7", "R8", "R9", "RA", "RB", "RC",
+                    "RD", "RE", "RF"}:
             self.registers.add_register(reg, self.operand_size)
-        for reg in {"SP"}:
-            self.registers.add_register(reg, self.address_size)
-        self.registers.put("SP", 0, self.address_size)
-
-    def push(self, value):
-        """Push value to stack."""
-        stack_pointer = self.registers.fetch(self.register_names["SP"],
-                                             self.address_size)
-        stack_pointer -= self.operand_size // self.ram.word_size
-        stack_pointer %= self.ram.memory_size
-        self.registers.put(self.register_names["SP"],
-                           stack_pointer,
-                           self.address_size)
-        self.ram.put(stack_pointer, value, self.operand_size)
-
-    def pop(self):
-        """Pop value from the stack."""
-        stack_pointer = self.registers.fetch(self.register_names["SP"],
-                                             self.address_size)
-        value = self.ram.fetch(stack_pointer, self.operand_size)
-        stack_pointer += self.operand_size // self.ram.word_size
-        stack_pointer %= self.ram.memory_size
-        self.registers.put(self.register_names["SP"],
-                           stack_pointer,
-                           self.address_size)
-        return value
 
     def fetch_and_decode(self):
         """Fetch 3 addresses."""
-        mask = 2 ** self.address_size - 1
-        one_operand = self.JUMP_OPCODES | {self.OPCODES["stpush"],
-                                           self.OPCODES["stpop"]}
+        addr_mask = 2 ** self.address_size - 1
+        reg_mask = 2 ** self.reg_addr_size - 1
 
         instruction_pointer = self.registers.fetch(self.register_names["PC"],
                                                    self.address_size)
-        self.opcode = self.ram.fetch(instruction_pointer, self.OPCODE_SIZE)
 
-        if self.opcode in one_operand:
-            instruction_size = self.OPCODE_SIZE + self.address_size
+        batch_size = max(self.ram.word_size, self.OPCODE_SIZE)
+        self.opcode = self.ram.fetch(instruction_pointer, batch_size)
+        space_size = batch_size - self.OPCODE_SIZE
+        self.opcode = Integer(self.opcode, batch_size, False)[space_size:].get_value()
+
+        if self.opcode in self.opcodes - (self.REGISTER_OPCODES | {self.OPCODES["halt"]}):
+            instruction_size = self.OPCODE_SIZE + 2 * self.reg_addr_size + self.address_size
         else:
-            instruction_size = self.OPCODE_SIZE
+            instruction_size = self.OPCODE_SIZE + 2 * self.reg_addr_size
 
         instruction = self.fetch_instruction(instruction_size)
 
-        if self.opcode in one_operand:
-            self.address = instruction & mask
+        if self.opcode in self.REGISTER_OPCODES:
+            r_x = (instruction >> self.reg_addr_size) & reg_mask
+            self.register1 = "R" + hex(r_x).upper()[2:]
+
+            r_y = instruction & reg_mask
+            self.register2 = "R" + hex(r_y).upper()[2:]
+        elif self.opcode != self.OPCODES["halt"]:
+            r_x = (instruction >> (self.reg_addr_size + self.address_size)) & reg_mask
+            self.register1 = "R" + hex(r_x).upper()[2:]
+
+            modificator = "R" + hex((instruction >> self.address_size) & reg_mask).upper()[2:]
+            if modificator != "R0":
+                modificator = self.registers.fetch(modificator, self.operand_size)
+            else:
+                modificator = 0
+            self.address = (instruction + modificator) & addr_mask
 
     def load(self):
         """Load registers R1 and R2."""
-        if self.opcode in self.BINAR_OPCODES | {self.OPCODES["stswap"]}:
-            operand2 = self.pop()
-            self.registers.put(self.register_names["R2"],
-                               operand2,
-                               self.operand_size)
-            operand1 = self.pop()
+        if self.opcode == self.OPCODES["store"]:
+            operand1 = self.registers.fetch(self.register1, self.operand_size)
             self.registers.put(self.register_names["R1"],
                                operand1,
                                self.operand_size)
-
-        elif self.opcode == self.OPCODES["stpush"]:
-            operand = self.ram.fetch(self.address, self.operand_size)
+        elif self.opcode in self.REGISTER_OPCODES:
+            operand1 = self.registers.fetch(self.register1, self.operand_size)
             self.registers.put(self.register_names["R1"],
-                               operand,
+                               operand1,
                                self.operand_size)
-        elif self.opcode in {self.OPCODES["stdup"], self.OPCODES["stpop"]}:
-            operand = self.pop()
+            operand2 = self.registers.fetch(self.register2, self.operand_size)
+            self.registers.put(self.register_names["R2"],
+                               operand2,
+                               self.operand_size)
+        elif self.opcode in (self.ARITHMETIC_OPCODES |
+                             {self.OPCODES["comp"], self.OPCODES["load"]}):
+            operand1 = self.registers.fetch(self.register1, self.operand_size)
             self.registers.put(self.register_names["R1"],
-                               operand,
+                               operand1,
+                               self.operand_size)
+            operand2 = self.ram.fetch(self.address, self.operand_size)
+            self.registers.put(self.register_names["R2"],
+                               operand2,
                                self.operand_size)
         elif self.opcode in self.JUMP_OPCODES:
             self.registers.put(self.register_names["ADDR"],
                                self.address,
                                self.address_size)
 
+        if self.opcode in self.REGISTER_OPCODES:
+            self.opcode ^= 0x20
+
     def execute(self):
         """Add specific commands: conditional jumps and cmp."""
         if self.opcode == self.OPCODES["comp"]:
             self.alu.sub()
+        elif self.opcode == self.OPCODES["load"]:
+            self.alu.move("R2", "S")
+        elif self.opcode == self.OPCODES["store"]:
+            self.alu.move("R1", "S")
         elif self.opcode in self.JUMP_OPCODES:
             self.execute_jump()
-        elif self.opcode == self.OPCODES["stswap"]:
-            self.alu.swap()
-        elif self.opcode == self.OPCODES["stdup"]:
-            self.alu.move(source="R1", dest="R2")
-        elif self.opcode in self.STACK_OPCODES:
-            pass
-        elif self.opcode == self.OPCODES["move"]:
-            raise ValueError('Invalid opcode `{opcode}`'
-                             .format(opcode=hex(self.opcode)))
         else:
             super().execute()
 
     def write_back(self):
         """Write result back."""
-        if self.opcode in self.ARITHMETIC_OPCODES | {self.OPCODES["stpush"],
-                                                     self.OPCODES["stswap"],
-                                                     self.OPCODES["stdup"]}:
+        if self.opcode in self.ARITHMETIC_OPCODES | {self.OPCODES["load"]}:
             value = self.registers.fetch(self.register_names["S"],
                                          self.operand_size)
-            self.push(value)
-            if self.opcode in self.DIVMOD_OPCODES | {self.OPCODES["stswap"],
-                                                     self.OPCODES["stdup"]}:
+            self.registers.put(self.register1, value, self.operand_size)
+            if self.opcode in self.DIVMOD_OPCODES:
+                next_register = (int(self.register1[1:], 0x10) + 1) % 0x10
+                next_register = "R" + hex(next_register).upper()[2:]
                 value = self.registers.fetch(self.register_names["RES"],
                                              self.operand_size)
-                self.push(value)
-        elif self.opcode == self.OPCODES["stpop"]:
-            value = self.registers.fetch(self.register_names["R1"],
+                self.registers.put(next_register, value, self.operand_size)
+        elif self.opcode == self.OPCODES["store"]:
+            value = self.registers.fetch(self.register_names["S"],
                                          self.operand_size)
             self.ram.put(self.address, value, self.operand_size)
-
-
diff --git a/modelmachine/ide.py b/modelmachine/ide.py
index a10f040..a3fddad 100644
--- a/modelmachine/ide.py
+++ b/modelmachine/ide.py
@@ -136,6 +136,7 @@ def exec_continue(cpu, step):
 def exec_print(cpu, step):
     """Print contents of registers."""
 
+    print("RAM access count:", cpu.ram.access_count)
     print("Register states:")
     registers = {cpu.register_names[name]  for name in cpu.register_names}
     for reg in sorted(list(registers)):
diff --git a/modelmachine/io.py b/modelmachine/io.py
index 3328907..0367def 100644
--- a/modelmachine/io.py
+++ b/modelmachine/io.py
@@ -44,11 +44,11 @@ class InputOutputUnit:
 
     def store_hex(self, start, size):
         """Save data to string."""
-        if size % self.word_size != 0:
+        if size % self.ram.word_size != 0:
             raise KeyError('Cannot save {size} bits, word size is {word_size}'
-                           .format(size=size, word_size=self.word_size))
+                           .format(size=size, word_size=self.ram.word_size))
         result = []
-        block_size = self.word_size
+        block_size = self.ram.word_size
         size //= block_size
         for i in range(start, start + size):
             data = self.ram.fetch(i, block_size)
diff --git a/modelmachine/memory.py b/modelmachine/memory.py
index c0ec03a..4fe3c7d 100644
--- a/modelmachine/memory.py
+++ b/modelmachine/memory.py
@@ -58,6 +58,7 @@ class AbstractMemory(dict):
 
         super().__init__(addresses)
         self.word_size = word_size
+        self.access_count = 0
 
         if endianess == "big":
             self.decode, self.encode = big_endian_decode, big_endian_encode
@@ -106,6 +107,8 @@ class AbstractMemory(dict):
         self.check_address(address)
         self.check_bits_count(address, bits)
 
+        self.access_count += 1
+
         size = bits // self.word_size
         if size == 1: # Address not always is integer, sometimes string
             return self[address]
@@ -123,6 +126,8 @@ class AbstractMemory(dict):
 
         enc_value = self.encode(value, self.word_size, bits)
 
+        self.access_count += 1
+
         size = bits // self.word_size
         if size == 1: # Address not always is integer, sometimes string
             self[address] = value
diff --git a/modelmachine/numeric.py b/modelmachine/numeric.py
index 62058b1..54c2c7b 100644
--- a/modelmachine/numeric.py
+++ b/modelmachine/numeric.py
@@ -87,3 +87,20 @@ class Integer(Number):
         """Test if two integer is equal."""
         self.check_compability(other)
         return self.get_value() == other.get_value()
+
+    def __getitem__(self, key):
+        """Get bits of unsigned representation.
+
+        Zero-indexed bit is minor.
+        """
+        representation = [(self.value >> i) & 1 for i in range(self.size)]
+        representation = representation[key]
+        if isinstance(representation, int):
+            return Integer(representation, 1, False)
+        elif isinstance(representation, list):
+            value = 0
+            for i in range(len(representation)):
+                value += representation[i] << i
+            return Integer(value, len(representation), False)
+        else:
+            raise TypeError("Integer indeces must be integers")
diff --git a/samples/mmm_sample.mmach b/samples/mmm_sample.mmach
new file mode 100644
index 0000000..26516ea
--- /dev/null
+++ b/samples/mmm_sample.mmach
@@ -0,0 +1,21 @@
+mmm
+
+[config]
+input = 0x100,0x102
+output = 0x104
+
+[code]
+; x = ((a * -21) % 50 - b) ** 2 == 178929
+00 0 0 0100 ; R0 := a
+03 0 0 000C ; R0 := a * -21
+04 0 0 000E ; R0 := (a * -21) / 50, R1 := x = (a * -21) % 50
+02 1 0 0102 ; R1 := x - b
+23 1 1 ; R1 := (x - b) ** 2
+10 1 0 0104 ; [0104] := R1
+99 0 0 ; halt
+; ---------------------
+FFFFFFEB ; -21
+00000032 ; 50
+
+[input]
+-123 456
diff --git a/setup.py b/setup.py
index 069ec0b..abf27a9 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ Read the doc: <https://github.com/vslutov/modelmachine>
 
 from setuptools import setup, find_packages
 
-VERSION = "0.0.6" # Don't forget fix in __main__.py
+VERSION = "0.1.0" # Don't forget fix in __main__.py
 
 setup(name='modelmachine',
       version=VERSION,

Регистровая машина
diff --git a/modelmachine/tests/test_cpu.py b/modelmachine/tests/test_cpu.py
index 6976f72..b6cee81 100644
--- a/modelmachine/tests/test_cpu.py
+++ b/modelmachine/tests/test_cpu.py
@@ -5,7 +5,7 @@
 from modelmachine.cpu import AbstractCPU
 from modelmachine.cpu import CPUMM3, CPUMM2
 from modelmachine.cpu import CPUMMV, CPUMM1
-from modelmachine.cpu import CPUMMS
+from modelmachine.cpu import CPUMMM
 
 from modelmachine.memory import RandomAccessMemory, RegisterMemory
 
@@ -236,35 +236,30 @@ class TestCPUMM1:
 
         assert out.read() == "298\n"
 
+class TestCPUMMM:
 
-class TestCPUMMS:
-
-    """Smoke test for mm-s."""
+    """Smoke test for mm-m."""
 
     cpu = None
     source = None
 
     def setup(self):
         """Init state."""
-        self.cpu = CPUMMS(protect_memory=False)
+        self.cpu = CPUMMM(protect_memory=False)
         self.source = ("[config]\n" +
-                       "input=0x100,0x103\n" +
-                       "output=0x106\n" +
+                       "input=0x100,0x102\n" +
+                       "output=0x104\n" +
                        "[code]\n" +
-                       "5A 0100\n" +
-                       "5A 0103\n" +
-                       "01\n" +
-                       "5C\n" +
-                       "5A 0103\n" +
-                       "05\n" +
-                       "86 0011\n" +
-                       "5C\n" +
-                       "02 ; never be used\n" +
-                       "5A 001b\n" +
-                       "02\n" +
-                       "5B 0106\n" +
-                       "99 0000\n" +
-                       "000002\n" +
+                       "00 0 0 0100\n" +
+                       "03 0 0 000C\n" +
+                       "04 0 0 000E\n" +
+                       "02 1 0 0102\n" +
+                       "23 1 1; coment never be used\n" +
+                       "10 1 0 0104\n" +
+                       "99 0 0\n" +
+                       "; -----------\n"
+                       "ffffffeb\n" +
+                       "00000032\n" +
                        "[input]\n" +
                        "100 200\n")
 
@@ -276,5 +271,5 @@ class TestCPUMMS:
         with open(str(out), 'w') as output:
             self.cpu.run_file(str(source), output=output)
 
-        assert out.read() == "298\n"
+        assert out.read() == "40000\n"
 
diff --git a/modelmachine/tests/test_cu_abstract.py b/modelmachine/tests/test_cu_abstract.py
index 3abb258..6169d0e 100644
--- a/modelmachine/tests/test_cu_abstract.py
+++ b/modelmachine/tests/test_cu_abstract.py
@@ -21,6 +21,11 @@ OP_COMP = 0x05
 OP_STORE = 0x10
 OP_UMUL, OP_UDIVMOD = 0x13, 0x14
 OP_SWAP = 0x20
+OP_RMOVE = 0x20
+OP_RADD, OP_RSUB = 0x21, 0x22
+OP_RSMUL, OP_RSDIVMOD = 0x23, 0x24
+OP_RCOMP = 0x25
+OP_RUMUL, OP_RUDIVMOD = 0x33, 0x34
 OP_STPUSH, OP_STPOP, OP_STDUP, OP_STSWAP = 0x5A, 0x5B, 0x5C, 0x5D
 OP_JUMP = 0x80
 OP_JEQ, OP_JNEQ = 0x81, 0x82
@@ -32,33 +37,9 @@ ARITHMETIC_OPCODES = {OP_ADD, OP_SUB, OP_SMUL, OP_SDIVMOD, OP_UMUL, OP_UDIVMOD}
 CONDJUMP_OPCODES = {OP_JEQ, OP_JNEQ,
                     OP_SJL, OP_SJGEQ, OP_SJLEQ, OP_SJG,
                     OP_UJL, OP_UJGEQ, OP_UJLEQ, OP_UJG}
-
-def run_fetch(test_case, value, opcode, instruction_size, and_decode=True):
-    """Run one fetch test."""
-    address = 10
-    test_case.ram.put(address, value, instruction_size)
-    increment = instruction_size // test_case.ram.word_size
-
-    test_case.registers.fetch.reset_mock()
-    test_case.registers.put.reset_mock()
-
-    def get_register(name, size):
-        """Get PC."""
-        assert name == "PC"
-        assert size == BYTE_SIZE
-        return address
-    test_case.registers.fetch.side_effect = get_register
-
-    if and_decode:
-        test_case.control_unit.fetch_and_decode()
-    else:
-        test_case.control_unit.fetch_instruction(instruction_size)
-    test_case.registers.fetch.assert_any_call("PC", BYTE_SIZE)
-    test_case.registers.put.assert_has_calls([call("RI", value, WORD_SIZE),
-                                              call("PC", address + increment,
-                                                   BYTE_SIZE)])
-    assert test_case.control_unit.opcode == opcode
-
+JUMP_OPCODES = CONDJUMP_OPCODES | {OP_JUMP}
+REGISTER_OPCODES = {OP_RMOVE, OP_RADD, OP_RSUB, OP_RSMUL,
+                    OP_RSDIVMOD, OP_RCOMP, OP_RUMUL, OP_RUDIVMOD}
 
 class TestAbstractControlUnit:
 
@@ -137,6 +118,10 @@ class TestControlUnit:
     arithmetic_opcodes = None
     condjump_opcodes = None
 
+    ir_size = 32
+    operand_size = WORD_SIZE
+    address_size = BYTE_SIZE
+
     def setup(self):
         """Init state."""
         self.ram = RandomAccessMemory(WORD_SIZE, 256, 'big')
@@ -154,9 +139,9 @@ class TestControlUnit:
         """Test internal constants."""
         assert isinstance(self.control_unit, AbstractControlUnit)
         assert isinstance(self.control_unit, ControlUnit)
-        assert self.control_unit.ir_size == 32
-        assert self.control_unit.operand_size == WORD_SIZE
-        assert self.control_unit.address_size == BYTE_SIZE
+        assert self.control_unit.ir_size == self.ir_size
+        assert self.control_unit.operand_size == self.operand_size
+        assert self.control_unit.address_size == self.address_size
         assert self.control_unit.OPCODE_SIZE == BYTE_SIZE
         assert self.control_unit.OPCODES["move"] == OP_MOVE
         assert self.control_unit.OPCODES["load"] == OP_LOAD
@@ -201,9 +186,36 @@ class TestControlUnit:
         with raises(NotImplementedError):
             self.control_unit.write_back()
 
+    def run_fetch(self, value, opcode, instruction_size, and_decode=True,
+                  address_size=BYTE_SIZE, ir_size=WORD_SIZE):
+        """Run one fetch test."""
+        address = 10
+        self.ram.put(address, value, instruction_size)
+        increment = instruction_size // self.ram.word_size
+
+        self.registers.fetch.reset_mock()
+        self.registers.put.reset_mock()
+
+        def get_register(name, size):
+            """Get PC."""
+            assert name == "PC"
+            assert size == self.control_unit.address_size
+            return address
+        self.registers.fetch.side_effect = get_register
+
+        if and_decode:
+            self.control_unit.fetch_and_decode()
+        else:
+            self.control_unit.fetch_instruction(instruction_size)
+        self.registers.fetch.assert_any_call("PC", address_size)
+        self.registers.put.assert_has_calls([call("RI", value, ir_size),
+                                                  call("PC", address + increment,
+                                                       address_size)])
+        assert self.control_unit.opcode == opcode
+
     def test_fetch_instruction(self):
         """Right fetch and decode is a half of business."""
-        run_fetch(self, 0x01020304, 0x01, WORD_SIZE, False)
+        self.run_fetch(0x01020304, 0x01, WORD_SIZE, False)
 
     def test_basic_execute(self, should_move=True):
         """Test basic operations."""
diff --git a/modelmachine/tests/test_cu_fixed.py b/modelmachine/tests/test_cu_fixed.py
index 7e4ace0..ba59481 100644
--- a/modelmachine/tests/test_cu_fixed.py
+++ b/modelmachine/tests/test_cu_fixed.py
@@ -17,7 +17,7 @@ from .test_cu_abstract import (BYTE_SIZE, WORD_SIZE, OP_MOVE, OP_SDIVMOD,
                                OP_LOAD, OP_STORE, OP_SWAP,
                                OP_JNEQ, OP_SJL, OP_SJGEQ, OP_SJLEQ, OP_SJG,
                                OP_UJL, OP_UJGEQ, OP_UJLEQ, OP_UJG, OP_HALT,
-                               ARITHMETIC_OPCODES, CONDJUMP_OPCODES, run_fetch)
+                               ARITHMETIC_OPCODES, CONDJUMP_OPCODES)
 from .test_cu_abstract import TestControlUnit as TBCU
 
 class TestControlUnit3(TBCU):
@@ -45,13 +45,13 @@ class TestControlUnit3(TBCU):
         """Right fetch and decode is a half of business."""
         for opcode in self.control_unit.opcodes:
             self.control_unit.address1, self.control_unit.address2 = None, None
-            run_fetch(self, opcode << 24 | 0x020304, opcode, WORD_SIZE)
+            self.run_fetch(opcode << 24 | 0x020304, opcode, WORD_SIZE)
             assert self.control_unit.address1 == 0x02
             assert self.control_unit.address2 == 0x03
             assert self.control_unit.address3 == 0x04
         for opcode in set(range(2 ** BYTE_SIZE)) - self.control_unit.opcodes:
             with raises(ValueError):
-                run_fetch(self, opcode << 24 | 0x020304, opcode, WORD_SIZE)
+                self.run_fetch(opcode << 24 | 0x020304, opcode, WORD_SIZE)
 
     def test_load(self):
         """R1 := [A1], R2 := [A2]."""
@@ -131,14 +131,14 @@ class TestControlUnit3(TBCU):
         self.run_cond_jump(OP_UJLEQ, False, LESS, True)
         self.run_cond_jump(OP_UJG, False, GREATER, False)
 
-    def test_jump_halt(self):
+    def test_execute_jump_halt(self):
         """Test for jump and halt."""
         self.alu.cond_jump.reset_mock()
         self.alu.sub.reset_mock()
         self.registers.put.reset_mock()
+
         self.control_unit.opcode = OP_JUMP
         self.control_unit.execute()
-
         assert not self.alu.sub.called
         assert not self.registers.put.called
         self.alu.jump.assert_called_once_with()
@@ -264,12 +264,12 @@ class TestControlUnit2(TestControlUnit3):
         """Right fetch and decode is a half of business."""
         for opcode in self.control_unit.opcodes:
             self.control_unit.address1, self.control_unit.address2 = None, None
-            run_fetch(self, opcode << 24 | 0x0203, opcode, WORD_SIZE)
+            self.run_fetch(opcode << 24 | 0x0203, opcode, WORD_SIZE)
             assert self.control_unit.address1 == 0x02
             assert self.control_unit.address2 == 0x03
         for opcode in set(range(2 ** BYTE_SIZE)) - self.control_unit.opcodes:
             with raises(ValueError):
-                run_fetch(self, opcode << 24 | 0x0203, opcode, WORD_SIZE)
+                self.run_fetch(opcode << 24 | 0x0203, opcode, WORD_SIZE)
 
     def test_load(self):
         """R1 := [A1], R2 := [A2]."""
@@ -319,24 +319,6 @@ class TestControlUnit2(TestControlUnit3):
         assert not self.registers.put.called
         self.alu.cond_jump.assert_called_once_with(signed, mol, equal)
 
-    def test_execute_jump_halt(self):
-        """Test for jump and halt."""
-        self.alu.cond_jump.reset_mock()
-        self.alu.sub.reset_mock()
-        self.registers.put.reset_mock()
-
-        self.control_unit.opcode = OP_JUMP
-        self.control_unit.execute()
-        assert not self.alu.sub.called
-        assert not self.registers.put.called
-        self.alu.jump.assert_called_once_with()
-
-        self.control_unit.opcode = OP_HALT
-        self.control_unit.execute()
-        assert not self.alu.sub.called
-        assert not self.registers.put.called
-        self.alu.halt.assert_called_once_with()
-
     def test_execute_comp(self):
         """Test for comp."""
         self.alu.cond_jump.reset_mock()
@@ -472,11 +454,11 @@ class TestControlUnit1(TestControlUnit2):
         """Right fetch and decode is a half of business."""
         for opcode in set(range(2 ** BYTE_SIZE)) - self.control_unit.opcodes:
             with raises(ValueError):
-                run_fetch(self, opcode << 24, opcode, WORD_SIZE)
+                self.run_fetch(opcode << 24, opcode, WORD_SIZE)
 
         for opcode in self.control_unit.opcodes:
             self.control_unit.address = None
-            run_fetch(self, opcode << 24 | 0x02, opcode, WORD_SIZE)
+            self.run_fetch(opcode << 24 | 0x02, opcode, WORD_SIZE)
             assert self.control_unit.address == 0x02
 
     def test_load(self):
diff --git a/modelmachine/tests/test_cu_variable.py b/modelmachine/tests/test_cu_variable.py
index f06a70c..4b500ca 100644
--- a/modelmachine/tests/test_cu_variable.py
+++ b/modelmachine/tests/test_cu_variable.py
@@ -4,7 +4,7 @@
 
 from modelmachine.cu import RUNNING, HALTED
 from modelmachine.cu import ControlUnitV
-from modelmachine.cu import ControlUnitS
+from modelmachine.cu import ControlUnitM
 from modelmachine.memory import RegisterMemory, RandomAccessMemory
 from modelmachine.alu import ArithmeticLogicUnit
 
@@ -14,9 +14,14 @@ from pytest import raises
 from .test_cu_abstract import (BYTE_SIZE, WORD_SIZE, OP_MOVE, OP_COMP,
                                OP_SDIVMOD, OP_UDIVMOD,
                                OP_STPUSH, OP_STPOP,
+                               OP_LOAD, OP_STORE, OP_RMOVE,
+                               OP_RADD, OP_RSUB, OP_RSMUL, OP_RSDIVMOD,
+                               OP_RCOMP, OP_RUMUL, OP_RUDIVMOD,
                                OP_STDUP, OP_STSWAP, OP_JUMP, OP_HALT,
-                               ARITHMETIC_OPCODES, CONDJUMP_OPCODES, run_fetch)
+                               ARITHMETIC_OPCODES, CONDJUMP_OPCODES,
+                               JUMP_OPCODES, REGISTER_OPCODES)
 from .test_cu_fixed import TestControlUnit2 as TBCU2
+from .test_cu_abstract import TestControlUnit as TBCU
 
 
 class TestControlUnitV(TBCU2):
@@ -45,23 +50,23 @@ class TestControlUnitV(TBCU2):
         """Right fetch and decode is a half of business."""
         for opcode in set(range(2 ** BYTE_SIZE)) - self.control_unit.opcodes:
             with raises(ValueError):
-                run_fetch(self, opcode, opcode, BYTE_SIZE)
+                self.run_fetch(opcode, opcode, BYTE_SIZE)
 
         for opcode in ARITHMETIC_OPCODES | {OP_COMP, OP_MOVE}:
             self.control_unit.address1, self.control_unit.address2 = None, None
-            run_fetch(self, opcode << 16 | 0x0203, opcode, 24)
+            self.run_fetch(opcode << 16 | 0x0203, opcode, 24)
             assert self.control_unit.address1 == 0x02
             assert self.control_unit.address2 == 0x03
 
         for opcode in CONDJUMP_OPCODES | {OP_JUMP}:
             self.control_unit.address1, self.control_unit.address2 = None, None
-            run_fetch(self, opcode << 8 | 0x02, opcode, 16)
+            self.run_fetch(opcode << 8 | 0x02, opcode, 16)
             assert self.control_unit.address1 == 0x02
             assert self.control_unit.address2 == None
 
         for opcode in {OP_HALT}:
             self.control_unit.address1, self.control_unit.address2 = None, None
-            run_fetch(self, opcode, opcode, 8)
+            self.run_fetch(opcode, opcode, 8)
             assert self.control_unit.address1 == None
             assert self.control_unit.address2 == None
 
@@ -175,322 +180,387 @@ class TestControlUnitV(TBCU2):
         assert self.registers.fetch("PC", BYTE_SIZE) == 0x01
         assert self.control_unit.get_status() == HALTED
 
+class TestControlUnitM(TBCU2):
 
-class TestControlUnitS(TBCU2):
-
-    """Test case for  Stack Model Machine Control Unit."""
+    """Test case for Address Modification Model Machine Control Unit."""
 
     def setup(self):
         """Init state."""
         super().setup()
-        self.ram = RandomAccessMemory(BYTE_SIZE, 256, 'big', is_protected=True)
-        self.control_unit = ControlUnitS(WORD_SIZE,
-                                         BYTE_SIZE,
+        self.ram = RandomAccessMemory(2 * BYTE_SIZE, 2 ** WORD_SIZE, 'big', is_protected=True)
+        self.control_unit = ControlUnitM(WORD_SIZE,
+                                         2 * BYTE_SIZE,
                                          self.registers,
                                          self.ram,
                                          self.alu,
                                          WORD_SIZE)
-        assert self.control_unit.opcodes == {0x01, 0x02, 0x03, 0x04,
-                                             0x13, 0x14,
-                                             0x05,
-                                             0x5A, 0x5B, 0x5C, 0x5D,
+        self.operand_size = WORD_SIZE
+        self.address_size = 2 * BYTE_SIZE
+        assert self.control_unit.opcodes == {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+                                             0x10, 0x13, 0x14,
+                                             0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+                                             0x33, 0x34,
                                              0x80, 0x81, 0x82,
                                              0x83, 0x84, 0x85, 0x86,
                                              0x93, 0x94, 0x95, 0x96,
                                              0x99}
 
+    def test_const(self):
+        super().test_const()
+        assert self.control_unit.OPCODES["rmove"] == OP_RMOVE
+        assert self.control_unit.OPCODES["radd"] == OP_RADD
+        assert self.control_unit.OPCODES["rsub"] == OP_RSUB
+        assert self.control_unit.OPCODES["rsmul"] == OP_RSMUL
+        assert self.control_unit.OPCODES["rsdivmod"] == OP_RSDIVMOD
+        assert self.control_unit.OPCODES["rcomp"] == OP_RCOMP
+        assert self.control_unit.OPCODES["rumul"] == OP_RUMUL
+        assert self.control_unit.OPCODES["rudivmod"] == OP_RUDIVMOD
+
+    def run_fetch(self, value, opcode, instruction_size, r2=True):
+        """Run one fetch test."""
+        address1 = 10
+        address2=42
+        self.ram.put(address1, value, instruction_size)
+        increment = instruction_size // self.ram.word_size
+
+        self.registers.fetch.reset_mock()
+        self.registers.put.reset_mock()
+
+        def get_register(name, size):
+            """Get PC."""
+            if name == "PC":
+                assert size == 2 * BYTE_SIZE
+                return address1
+            elif name=="R2":
+                assert size == WORD_SIZE
+                return address2
+            else:
+                raise KeyError()
+
+        self.registers.fetch.side_effect = get_register
+
+        self.control_unit.fetch_and_decode()
+        if r2:
+            self.registers.fetch.assert_has_calls([call("PC", 2 * BYTE_SIZE),
+                                                   call("R2", WORD_SIZE)])
+        else:
+            self.registers.fetch.assert_any_call("PC", 2 * BYTE_SIZE)
+        self.registers.put.assert_has_calls([call("RI", value, WORD_SIZE),
+                                                  call("PC", address1 + increment,
+                                                       2 * BYTE_SIZE)])
+        assert self.control_unit.opcode == opcode
+
     def test_fetch_and_decode(self):
         """Right fetch and decode is a half of business."""
         for opcode in set(range(2 ** BYTE_SIZE)) - self.control_unit.opcodes:
             with raises(ValueError):
-                run_fetch(self, opcode, opcode, BYTE_SIZE)
+                self.run_fetch(opcode << BYTE_SIZE, opcode, 2 * BYTE_SIZE)
 
-        for opcode in ARITHMETIC_OPCODES | {OP_COMP, OP_STDUP, OP_STSWAP,
-                                            OP_HALT}:
+        for opcode in ARITHMETIC_OPCODES | JUMP_OPCODES | {OP_COMP, OP_LOAD, OP_STORE}:
+            self.control_unit.register1 = None
+            self.control_unit.register2 = None
+            self.control_unit.address = None
 
+            self.run_fetch(opcode << 24 | 0x120014, opcode, 32)
+
+            assert self.control_unit.register1 == 'R1'
+            assert self.control_unit.register2 is None
+            assert self.control_unit.address == 0x14 + 42
+
+        for opcode in REGISTER_OPCODES:
+            self.control_unit.register1 = None
+            self.control_unit.register2 = None
             self.control_unit.address = None
-            run_fetch(self, opcode, opcode, BYTE_SIZE)
-            assert self.control_unit.address == None
 
-        for opcode in CONDJUMP_OPCODES | {OP_STPUSH, OP_STPOP, OP_JUMP}:
+            self.run_fetch(opcode << 8 | 0x12, opcode, 16, r2=False)
+
+            assert self.control_unit.register1 == 'R1'
+            assert self.control_unit.register2 == 'R2'
+            assert self.control_unit.address is None
+
+        for opcode in {OP_HALT}:
+            self.control_unit.register1 = None
+            self.control_unit.register2 = None
             self.control_unit.address = None
-            run_fetch(self, opcode << 8 | 0x02, opcode, 16)
-            assert self.control_unit.address == 0x02
 
-    def test_push(self):
-        """Test basic stack operation."""
-        self.registers.put.reset_mock()
-        self.registers.fetch.reset_mock()
-        address, value, size = 10, 123, WORD_SIZE // self.ram.word_size
-        self.registers.fetch.return_value = address
-        self.control_unit.push(value)
-        assert self.ram.fetch(address - size, WORD_SIZE) == value
-        self.registers.fetch.assert_called_once_with("SP", BYTE_SIZE)
-        self.registers.put.assert_called_once_with("SP",
-                                                   address - size,
-                                                   BYTE_SIZE)
-
-    def test_pop(self):
-        """Test basic stack operation."""
-        self.registers.put.reset_mock()
-        self.registers.fetch.reset_mock()
-        address, value, size = 10, 123, WORD_SIZE // self.ram.word_size
-        self.ram.put(address, value, WORD_SIZE)
-        self.registers.fetch.return_value = address
-        assert self.control_unit.pop() == value
-        self.registers.fetch.assert_called_once_with("SP", BYTE_SIZE)
-        self.registers.put.assert_called_once_with("SP",
-                                                   address + size,
-                                                   BYTE_SIZE)
+            self.run_fetch(opcode << 8 | 0x12, opcode, 16, r2=False)
+
+
+            assert self.control_unit.register1 is None
+            assert self.control_unit.register2 is None
+            assert self.control_unit.address is None
 
     def test_load(self):
         """R1 := [A1], R2 := [A2]."""
-        address, val1, val2, val3 = 10, 1, 2, 3
-        stack = []
-        def pop():
-            """Pop mock."""
-            return stack.pop()
-        self.control_unit.pop = create_autospec(self.control_unit.pop)
-        self.control_unit.pop.side_effect = pop
+        register1, val1 = 'R3', 123456
+        register2, val2 = 'R4', 654321
+        address, val3 = 10, 111111
+
+        def get_register(name, size):
+            """Get PC."""
+            assert size == WORD_SIZE
+            if name == register1:
+                return val1
+            elif name == register2:
+                return val2
+            else:
+                raise KeyError()
+
+        self.registers.fetch.side_effect = get_register
         self.control_unit.address = address
+        self.control_unit.register1 = register1
+        self.control_unit.register2 = register2
         self.ram.put(address, val3, WORD_SIZE)
 
-        for opcode in ARITHMETIC_OPCODES | {OP_COMP, OP_STSWAP}:
+        for opcode in ARITHMETIC_OPCODES | {OP_LOAD, OP_COMP}:
+            self.registers.fetch.reset_mock()
             self.registers.put.reset_mock()
-            self.control_unit.pop.reset_mock()
-            stack = [val1, val2]
+
             self.control_unit.opcode = opcode
             self.control_unit.load()
-            self.control_unit.pop.assert_has_calls([call(), call()])
-            self.registers.put.assert_has_calls([call("R1", val1, WORD_SIZE),
-                                                 call("R2", val2, WORD_SIZE)],
-                                                True)
+            self.registers.fetch.assert_called_once_with(register1, WORD_SIZE)
+            self.registers.put.assert_has_calls([call("S", val1, WORD_SIZE),
+                                                 call("RZ", val3, WORD_SIZE)])
 
-        for opcode in {OP_STPOP, OP_STDUP}:
+        for opcode in {OP_STORE}:
+            self.registers.fetch.reset_mock()
             self.registers.put.reset_mock()
-            self.control_unit.pop.reset_mock()
-            stack = [val1]
+
             self.control_unit.opcode = opcode
             self.control_unit.load()
-            self.control_unit.pop.assert_called_once_with()
-            self.registers.put.assert_called_once_with("R1", val1, WORD_SIZE)
+            self.registers.fetch.assert_called_once_with(register1, WORD_SIZE)
+            self.registers.put.assert_called_once_with("S", val1, WORD_SIZE)
 
-        for opcode in CONDJUMP_OPCODES | {OP_JUMP}:
+        for opcode in REGISTER_OPCODES:
+            self.registers.fetch.reset_mock()
             self.registers.put.reset_mock()
-            self.control_unit.pop.reset_mock()
+
             self.control_unit.opcode = opcode
             self.control_unit.load()
-            assert not self.control_unit.pop.called
-            self.registers.put.assert_called_once_with("ADDR", address, BYTE_SIZE)
+            self.registers.fetch.assert_has_calls([call(register1, WORD_SIZE),
+                                                   call(register2, WORD_SIZE)])
+            self.registers.put.assert_has_calls([call("S", val1, WORD_SIZE),
+                                                 call("RZ", val2, WORD_SIZE)])
 
-        for opcode in {OP_STPUSH}:
+        for opcode in CONDJUMP_OPCODES | {OP_JUMP}:
+            self.registers.fetch.reset_mock()
             self.registers.put.reset_mock()
-            self.control_unit.pop.reset_mock()
+
             self.control_unit.opcode = opcode
             self.control_unit.load()
-            assert not self.control_unit.pop.called
-            self.registers.put.assert_called_once_with("R1", val3, WORD_SIZE)
+
+            assert not self.registers.fetch.called
+            self.registers.put.assert_called_once_with("ADDR", address, 2 * BYTE_SIZE)
 
         for opcode in {OP_HALT}:
+            self.registers.fetch.reset_mock()
             self.registers.put.reset_mock()
-            self.control_unit.pop.reset_mock()
+
             self.control_unit.opcode = opcode
+
             self.control_unit.load()
-            assert not self.control_unit.pop.called
+            assert not self.registers.fetch.called
             assert not self.registers.put.called
 
     def test_basic_execute(self, should_move=None):
         """Test basic operations."""
-        super().test_basic_execute(should_move)
+        super().test_basic_execute(should_move=should_move)
 
-    def test_execute_stack(self):
-        """stpush, stpop, stdup and stswap."""
-        self.alu.cond_jump.reset_mock()
-        self.alu.sub.reset_mock()
-        self.registers.put.reset_mock()
-
-        self.control_unit.opcode = OP_STPUSH
-        self.control_unit.execute()
-        self.control_unit.opcode = OP_STPOP
-        self.control_unit.execute()
-        assert not self.alu.move.called
-        assert not self.alu.swap.called
-
-        self.control_unit.opcode = OP_STDUP
-        self.control_unit.execute()
-        self.alu.move.assert_called_once_with(source="R1", dest="R2")
+        self.control_unit.opcode = OP_MOVE
         self.alu.move.reset_mock()
-        assert not self.alu.swap.called
-
-        self.control_unit.opcode = OP_STSWAP
         self.control_unit.execute()
-        self.alu.swap.assert_called_once_with()
-        assert not self.alu.move.called
-
-        assert not self.alu.sub.called
-        assert not self.registers.put.called
+        self.alu.move.assert_called_once_with('R2', 'S')
 
 
     def run_write_back(self, should, opcode):
         """Run write back method for specific opcode."""
-        first, second, third, address = 11111111, 22222222, 3333333, 10
+
+        print(hex(opcode))
+
+        register1, next_register1, register2 = 'R5', 'R6', 'R8'
+        res_register1, val1 = 'S', 123456
+        res_register2, val2 = 'RZ', 654321
+        address, canary = 10, 0
+
         def get_register(name, size):
-            """Get result."""
-            assert name in {"R1", "R2"}
-            assert size == WORD_SIZE
-            if name == "R1":
-                return second
-            elif name == "R2":
-                return third
+            """Get PC."""
+            assert size == self.operand_size
+            if name == res_register1:
+                return val1
+            elif name == res_register2:
+                return val2
+            else:
+                raise KeyError()
+
         self.registers.fetch.side_effect = get_register
-        self.registers.fetch.reset_mock()
-        self.ram.put(address, first, WORD_SIZE)
         self.control_unit.address = address
-        self.control_unit.push.reset_mock()
+        self.control_unit.register1 = register1
+        self.control_unit.register2 = register2
+        self.ram.put(address, canary, self.operand_size)
+
+        self.registers.fetch.reset_mock()
+        self.registers.put.reset_mock()
 
         self.control_unit.opcode = opcode
         self.control_unit.write_back()
 
-        if should:
-            if opcode == OP_STPOP:
-                assert self.ram.fetch(address, WORD_SIZE) == second
-            elif opcode in {OP_SDIVMOD, OP_UDIVMOD, OP_STSWAP, OP_STDUP}:
-                self.control_unit.push.assert_has_calls([call(second),
-                                                         call(third)])
-                self.registers.fetch.assert_has_calls([call("R1", WORD_SIZE),
-                                                       call("R2", WORD_SIZE)])
-                assert self.ram.fetch(address, WORD_SIZE) == first
-            else:
-                self.control_unit.push.assert_called_once_with(second)
-                self.registers.fetch.assert_called_once_with("R1", WORD_SIZE)
-                assert self.ram.fetch(address, WORD_SIZE) == first
+        if should == 'two_registers':
+            self.registers.fetch.assert_has_calls([call(res_register1, self.operand_size),
+                                                   call(res_register2, self.operand_size)])
+            self.registers.put.assert_has_calls([call(register1, val1, self.operand_size),
+                                                 call(next_register1, val2, self.operand_size)])
+            assert self.ram.fetch(address, self.operand_size) == canary
+
+        elif should == 'register':
+            self.registers.fetch.assert_called_once_with(res_register1, self.operand_size)
+            self.registers.put.assert_called_once_with(register1, val1, self.operand_size)
+            assert self.ram.fetch(address, self.operand_size) == canary
+
+        elif should == 'memory':
+            self.registers.fetch.assert_called_once_with(res_register1, self.operand_size)
+            assert not self.registers.put.called
+            assert self.ram.fetch(address, self.operand_size) == val1
+
         else:
-            assert not self.control_unit.push.called
             assert not self.registers.fetch.called
-            assert self.ram.fetch(address, WORD_SIZE) == first
+            assert not self.registers.put.called
+            assert self.ram.fetch(address, self.operand_size) == canary
 
     def test_write_back(self):
         """Test write back result to the memory."""
-        self.control_unit.push = create_autospec(self.control_unit.push)
-        for opcode in ARITHMETIC_OPCODES | {OP_STPOP, OP_STPUSH, OP_STSWAP,
-                                            OP_STDUP,}:
-            self.run_write_back(True, opcode)
+        for opcode in {OP_SDIVMOD, OP_UDIVMOD}:
+            self.run_write_back('two_registers', opcode)
+
+        for opcode in (ARITHMETIC_OPCODES | {OP_LOAD}) - {OP_SDIVMOD, OP_UDIVMOD}:
+            self.run_write_back('register', opcode)
+
+        for opcode in {OP_STORE}:
+            self.run_write_back('memory', opcode)
 
         for opcode in (CONDJUMP_OPCODES |
-                       {OP_HALT,
-                        OP_JUMP,
-                        OP_COMP}):
-            self.run_write_back(False, opcode)
+                       {OP_HALT, OP_JUMP, OP_COMP}):
+            self.run_write_back('nothing', opcode)
 
     def test_step(self):
         """Test step cycle."""
-        size = WORD_SIZE // 8
-
         self.control_unit.registers = self.registers = RegisterMemory()
-        self.registers.add_register("RI", WORD_SIZE)
-        self.registers.add_register("SP", BYTE_SIZE)
-        self.registers.put("SP", 0, BYTE_SIZE)
+        for register in {'RI', 'RZ', 'S', 'R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9', 'RA', 'RB', 'RC', 'RD', 'RE', 'RF'}:
+            self.registers.add_register(register, self.operand_size)
         self.alu = ArithmeticLogicUnit(self.registers,
                                        self.control_unit.register_names,
-                                       WORD_SIZE,
-                                       BYTE_SIZE)
+                                       self.operand_size,
+                                       self.address_size)
         self.control_unit.alu = self.alu
 
-        self.ram.put(0x00, 0x5a0b, 2 * BYTE_SIZE)
-        self.ram.put(0x02, 0x5a0f, 2 * BYTE_SIZE)
-        self.ram.put(0x04, 0x01, 1 * BYTE_SIZE)
-        self.ram.put(0x05, 0x5c, 1 * BYTE_SIZE)
-        self.ram.put(0x06, 0x5a13, 2 * BYTE_SIZE)
-        self.ram.put(0x08, 0x05, 1 * BYTE_SIZE)
-        self.ram.put(0x09, 0x8617, 2 * BYTE_SIZE)
-        self.ram.put(0x0b, 12, WORD_SIZE)
-        self.ram.put(0x0f, 10, WORD_SIZE)
-        self.ram.put(0x13, 20, WORD_SIZE)
-        self.ram.put(0x17, 0x5b0b, 2 * BYTE_SIZE)
-        self.ram.put(0x19, 0x99, BYTE_SIZE)
-        self.registers.put("PC", 0, BYTE_SIZE)
+        canary = 0
+        self.ram.put(0x0000, 0x00000100, WORD_SIZE)
+        self.ram.put(0x0002, 0x0300000C, WORD_SIZE)
+        self.ram.put(0x0004, 0x0400000E, WORD_SIZE)
+        self.ram.put(0x0006, 0x02100102, WORD_SIZE)
+        self.ram.put(0x0008, 0x2311, 2 * BYTE_SIZE)
+        self.ram.put(0x0009, 0x10100104, WORD_SIZE)
+        self.ram.put(0x000B, 0x9900, 2 * BYTE_SIZE)
+        self.ram.put(0x000C, 0xffffffeb, WORD_SIZE)
+        self.ram.put(0x000E, 0x00000032, WORD_SIZE)
+        self.ram.put(0x0100, -123 % 2 ** WORD_SIZE, WORD_SIZE)
+        self.ram.put(0x0102, 456, WORD_SIZE)
+        self.ram.put(0x0104, canary, WORD_SIZE)
+        self.registers.put("PC", 0, 2 * BYTE_SIZE)
 
         self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x02
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - size
-        self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x04
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - 2 * size
-        self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x05
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - size
+        assert self.registers.fetch("R0", WORD_SIZE) == -123 % 2 ** WORD_SIZE
+        assert self.registers.fetch("R1", WORD_SIZE) == 0
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x02
+        assert self.ram.fetch(0x0104, WORD_SIZE) == canary
+        assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x06
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - 2 * size
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123)
+        assert self.registers.fetch("R1", WORD_SIZE) == 0
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x04
+        assert self.ram.fetch(0x0104, WORD_SIZE) == canary
+        assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x08
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - 3 * size
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123) // 50
+        x = 21 * 123 % 50
+        assert self.registers.fetch("R1", WORD_SIZE) == x
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x06
+        assert self.ram.fetch(0x0104, WORD_SIZE) == canary
+        assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x09
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - size
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123) // 50
+        assert self.registers.fetch("R1", WORD_SIZE) == (x - 456) % 2 ** WORD_SIZE
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x08
+        assert self.ram.fetch(0x0104, WORD_SIZE) == canary
+        assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.ram.fetch(0x0b, WORD_SIZE) == 12
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x17
-        assert self.registers.fetch("SP", BYTE_SIZE) == 2 ** BYTE_SIZE - size
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123) // 50
+        assert self.registers.fetch("R1", WORD_SIZE) == (x - 456) ** 2
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x09
+        assert self.ram.fetch(0x0104, WORD_SIZE) == canary
+        assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.ram.fetch(0x0b, WORD_SIZE) == 22
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x19
-        assert self.registers.fetch("SP", BYTE_SIZE) == 0
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123) // 50
+        assert self.registers.fetch("R1", WORD_SIZE) == (x - 456) ** 2
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x0b
+        assert self.ram.fetch(0x0104, WORD_SIZE) == (x - 456) ** 2
         assert self.control_unit.get_status() == RUNNING
+
         self.control_unit.step()
-        assert self.ram.fetch(0x0b, WORD_SIZE) == 22
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x1a
-        assert self.registers.fetch("SP", BYTE_SIZE) == 0
+        assert self.registers.fetch("R0", WORD_SIZE) == (21 * 123) // 50
+        assert self.registers.fetch("R1", WORD_SIZE) == (x - 456) ** 2
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x0C
         assert self.control_unit.get_status() == HALTED
 
     def test_run(self):
         """Very simple program."""
         self.control_unit.registers = self.registers = RegisterMemory()
-        self.registers.add_register("RI", WORD_SIZE)
-        self.registers.add_register("SP", BYTE_SIZE)
-        self.registers.put("SP", 0, BYTE_SIZE)
+        for register in {'RI', 'RZ', 'S', 'R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9', 'RA', 'RB', 'RC', 'RD', 'RE', 'RF'}:
+            self.registers.add_register(register, self.operand_size)
+
         self.alu = ArithmeticLogicUnit(self.registers,
                                        self.control_unit.register_names,
-                                       WORD_SIZE,
-                                       BYTE_SIZE)
+                                       self.operand_size,
+                                       self.address_size)
         self.control_unit.alu = self.alu
 
-        self.ram.put(0x00, 0x5a0b, 2 * BYTE_SIZE)
-        self.ram.put(0x02, 0x5a0f, 2 * BYTE_SIZE)
-        self.ram.put(0x04, 0x01, 1 * BYTE_SIZE)
-        self.ram.put(0x05, 0x5c, 1 * BYTE_SIZE)
-        self.ram.put(0x06, 0x5a13, 2 * BYTE_SIZE)
-        self.ram.put(0x08, 0x05, 1 * BYTE_SIZE)
-        self.ram.put(0x09, 0x8617, 2 * BYTE_SIZE)
-        self.ram.put(0x0b, 12, WORD_SIZE)
-        self.ram.put(0x0f, 10, WORD_SIZE)
-        self.ram.put(0x13, 20, WORD_SIZE)
-        self.ram.put(0x17, 0x5b0b, 2 * BYTE_SIZE)
-        self.ram.put(0x19, 0x99, BYTE_SIZE)
-        self.registers.put("PC", 0, BYTE_SIZE)
+        self.ram.put(0x0000, 0x00000100, WORD_SIZE)
+        self.ram.put(0x0002, 0x0300000C, WORD_SIZE)
+        self.ram.put(0x0004, 0x0400000E, WORD_SIZE)
+        self.ram.put(0x0006, 0x02100102, WORD_SIZE)
+        self.ram.put(0x0008, 0x2311, 2 * BYTE_SIZE)
+        self.ram.put(0x0009, 0x10100104, WORD_SIZE)
+        self.ram.put(0x000B, 0x9900, 2 * BYTE_SIZE)
+        self.ram.put(0x000C, 0xffffffeb, WORD_SIZE)
+        self.ram.put(0x000E, 0x00000032, WORD_SIZE)
+        self.ram.put(0x0100, 0xffffff85, WORD_SIZE)
+        self.ram.put(0x0102, 0x000001c8, WORD_SIZE)
+        self.registers.put("PC", 0, 2 * BYTE_SIZE)
 
         self.control_unit.run()
-        assert self.ram.fetch(0x0b, WORD_SIZE) == 22
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x1a
-        assert self.registers.fetch("SP", BYTE_SIZE) == 0
+        assert self.ram.fetch(0x0104, WORD_SIZE) == 178929
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x000C
         assert self.control_unit.get_status() == HALTED
 
     def test_minimal_run(self):
-        """Very simple program."""
+        """Minimal program."""
         self.control_unit.registers = self.registers = RegisterMemory()
-        self.registers.add_register("RI", WORD_SIZE)
-        self.registers.add_register("SP", BYTE_SIZE)
-        self.registers.put("SP", 0, BYTE_SIZE)
+        self.registers.add_register('RI', self.operand_size)
+
         self.alu = ArithmeticLogicUnit(self.registers,
                                        self.control_unit.register_names,
-                                       WORD_SIZE,
-                                       BYTE_SIZE)
+                                       self.operand_size,
+                                       self.address_size)
         self.control_unit.alu = self.alu
 
-        self.ram.put(0x00, 0x99, BYTE_SIZE)
-        self.registers.put("PC", 0, BYTE_SIZE)
+        self.ram.put(0x00, 0x9900, 2 * BYTE_SIZE)
+        self.registers.put("PC", 0, 2 * BYTE_SIZE)
 
         self.control_unit.run()
-        assert self.registers.fetch("PC", BYTE_SIZE) == 0x01
-        assert self.registers.fetch("SP", BYTE_SIZE) == 0
+        assert self.registers.fetch("PC", 2 * BYTE_SIZE) == 0x01
         assert self.control_unit.get_status() == HALTED
+
diff --git a/modelmachine/tests/test_numeric.py b/modelmachine/tests/test_numeric.py
index df42766..b96f034 100644
--- a/modelmachine/tests/test_numeric.py
+++ b/modelmachine/tests/test_numeric.py
@@ -211,3 +211,21 @@ class TestNumeric:
         assert dic[self.first] == 10
         assert dic[self.second] == 11
         assert dic[third] == 10
+
+    def test_getitem(self):
+        """Test if we can get Integer bits."""
+        assert self.first[0] == Integer(0, 1, False)
+        assert self.first[1] == Integer(1, 1, False)
+        assert self.first[2] == Integer(0, 1, False)
+        assert self.first[3] == Integer(1, 1, False)
+        assert self.first[4] == Integer(0, 1, False)
+        assert self.first[5] == Integer(0, 1, False)
+        assert self.second[0] == Integer(0, 1, False)
+        assert self.second[1] == Integer(0, 1, False)
+        assert self.second[2] == Integer(1, 1, False)
+        assert self.second[3] == Integer(1, 1, False)
+        assert self.second[4] == Integer(0, 1, False)
+        assert self.second[5] == Integer(0, 1, False)
+        assert self.first[0:6] == Integer(10, 6, False)
+        assert self.first[:6] == Integer(10, 6, False)
+        assert self.first[3:] == Integer(1, 32 - 3, False)

pip install -e .
parse_log_pytest
requirements.txt
pytest
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
iniconfig==2.1.0
-e git+https://github.com/cmc-python/modelmachine.git@fa9275d64498c7cbe24f02357bbb1bc971670756#egg=modelmachine
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
tomli==2.2.1

name: modelmachine
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - tomli==2.2.1
prefix: /opt/conda/envs/modelmachine

modelmachine/tests/test_numeric.py::TestNumeric::test_index
modelmachine/tests/test_cpu.py::TestAbstractCPU::test_load_program modelmachine/tests/test_cpu.py::TestAbstractCPU::test_print_result modelmachine/tests/test_cpu.py::TestAbstractCPU::test_run_file modelmachine/tests/test_cpu.py::TestCPUMM3::test_smoke modelmachine/tests/test_cpu.py::TestCPUMM2::test_smoke modelmachine/tests/test_cpu.py::TestCPUMMV::test_smoke modelmachine/tests/test_cpu.py::TestCPUMM1::test_smoke modelmachine/tests/test_cpu.py::TestCPUMMM::test_smoke modelmachine/tests/test_cu_abstract.py::TestAbstractControlUnit::test_get_status modelmachine/tests/test_cu_abstract.py::TestAbstractControlUnit::test_abstract_methods modelmachine/tests/test_cu_abstract.py::TestAbstractControlUnit::test_step_and_run modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_const modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_fetch_and_decode modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_load modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_write_back modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_fetch_instruction modelmachine/tests/test_cu_abstract.py::TestControlUnit::test_basic_execute modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_const modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_fetch_instruction modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_fetch_and_decode modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_load modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_basic_execute modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_execute_cond_jumps modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_execute_jump_halt modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_write_back modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_step modelmachine/tests/test_cu_fixed.py::TestControlUnit3::test_run modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_const modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_fetch_instruction modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_basic_execute modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_execute_cond_jumps modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_execute_jump_halt modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_fetch_and_decode modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_load modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_execute_comp modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_write_back modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_step modelmachine/tests/test_cu_fixed.py::TestControlUnit2::test_run modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_const modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_fetch_instruction modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_execute_cond_jumps modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_execute_jump_halt modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_fetch_and_decode modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_load modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_basic_execute modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_execute_comp modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_execute_load_store_swap modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_write_back modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_step modelmachine/tests/test_cu_fixed.py::TestControlUnit1::test_run modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_const modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_fetch_instruction modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_basic_execute modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_execute_cond_jumps modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_execute_jump_halt modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_execute_comp modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_write_back modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_fetch_and_decode modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_load modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_step modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_run modelmachine/tests/test_cu_variable.py::TestControlUnitV::test_minimal_run modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_fetch_instruction modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_execute_cond_jumps modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_execute_jump_halt modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_execute_comp modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_const modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_fetch_and_decode modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_load modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_basic_execute modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_write_back modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_step modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_run modelmachine/tests/test_cu_variable.py::TestControlUnitM::test_minimal_run modelmachine/tests/test_numeric.py::TestNumeric::test_init modelmachine/tests/test_numeric.py::TestNumeric::test_check_compability modelmachine/tests/test_numeric.py::TestNumeric::test_get_value modelmachine/tests/test_numeric.py::TestNumeric::test_add modelmachine/tests/test_numeric.py::TestNumeric::test_mul modelmachine/tests/test_numeric.py::TestNumeric::test_sub modelmachine/tests/test_numeric.py::TestNumeric::test_eq modelmachine/tests/test_numeric.py::TestNumeric::test_divmod modelmachine/tests/test_numeric.py::TestNumeric::test_get_data modelmachine/tests/test_numeric.py::TestNumeric::test_hash modelmachine/tests/test_numeric.py::TestNumeric::test_getitem
Makefile modelmachine/__main__.py setup.py samples/mmm_sample.mmach modelmachine/ide.py README.md modelmachine/cu.py modelmachine/memory.py modelmachine/numeric.py modelmachine/io.py modelmachine/cpu.py
Makefile modelmachine/__main__.py setup.py samples/mmm_sample.mmach modelmachine/ide.py README.md modelmachine/cu.py modelmachine/memory.py modelmachine/numeric.py modelmachine/io.py modelmachine/cpu.py