lisp | acc | harv | hw | instr | binary | stream | mem | cstr | prob5
lisp
-- Язык программирования. Синтаксис -- синтаксис языка Lisp. S-exp.acc
-- Архитектура -- система команд должна быть выстроена вокруг аккумулятора.harv
-- Архитектура организации памяти -- Гарвардская архитектура.hw
-- Control Unit -- hardwired. Реализуется как часть модели.instr
-- Точность модели -- процессор необходимо моделировать с точностью до каждой инструкции (наблюдается состояние после каждой инструкции).binary
-- Представление машинного кода -- бинарное представление.stream
-- Ввод-вывод -- Ввод-вывод осуществляется как поток токеновmem
-- Ввод-вывод ISA -- memory-mapped (порты ввода-вывода отображаются в память и доступ к ним осуществляется штатными командами),cstr
-- Поддержка строк -- Null-terminated (C string)prob5
-- Алгоритм -- Smallest multiple. Project Euler. Problem 5
Форма Бэкуса-Наура:
<program> ::= <statement> | <statement> <program>
<statement> ::= <function_definition> | <common_statement>
<function_definition> ::= "(" <function_name> "(" <function_arguments> ")" <function_body> ")"
<function_name> ::= <identifier>
<function_arguments> ::= "" | <function_argument> | <function_argument> <function_arguments>
<function_argument> ::= <identifier>
<function_body> ::= <argument>
<common_statement> ::= "(" <statement_name> <arguments> ")"
<statement_name> ::= <boolean_operation> | <math_operation> | <identifier>
<boolean_operation> ::= "=" | ">="
<math_operation> ::= "+" | "-" | "*" | "/"
<arguments> ::= "" | <argument> | <argument> <arguments>
<argument> ::= <literal> | <variable> | <common_statement>
<literal> ::= <number> | <string>
<number> ::= [ "-" ] <unsigned_number>
<unsigned_number> ::= <digit> | <digit> <unsigned_number>
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<string> ::= '"' <string_letters> '"'
<string_letters> ::= "" | <string_letter> | <string_letter> <string_letters>
<string_letter> ::= <any symbol except: '"'>
<variable> ::= <identifier>
<identifier> ::= <identifier_letters>
<identifier_letters> ::= <identifier_letter> | <identifier_letter> <identifier_letters>
<identifier_letters> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I"
| "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g"
| "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s"
| "t" | "u" | "v" | "w" | "x" | "y" | "z" | "_"
Код состоит из последовательности выражений, заключенных в скобки. Выражение состоит из названия и агрументов, следующих друг за другом через пробел. В качестве аргументов могут выступать также выражения, переменные или числовые (123
) или строковые литералы ("str"
). Пробельные символы и переносы строк игнорируются.
Любое выражение/переменная/литерал имеют возвращаемое значение (кроме объявления функции).
Объявление функции выглядит, как обычное выражение, включающее название-аргументы-телою Тело функция - ровно одно выражение.
Типов данных два: 64-битное знаковое число, строка. Соответственно, каждое выражение возвращает значение одного из двух типов.
На уровне языка поддерживаются математические выражения +
- сложение, -
- вычитание, *
- умножение, /
- целочисленное деление, mod
- остаток от деления.
Поддерживаются операторы сравнения =
- равно, >
- больше, >=
- больше или равно. Возвращаемое значение 1 - истина, 0 - ложь.
Переменные можно определить при помощи функции set
((set <label> <val>)
). Возвращает установленное значение. Область видимости данных - глобальная.
Также поддерживается условная конструкция if
((if <cond> <opt1> <opt2>)
). Истина определяется по значению cond
, равно 0 - будет выполнен код opt2
, иначе opt1
.
Определены функции для работы с вводом выводом: printi
, print
, printline
, readline
. Функции вывода возвращают количество выведенных символов, а функция чтения - прочитанную строку.
Код выполняется последовательно сверху вниз. Внутри выражений код выполняется справа налево.
Примеры программ можно найти в директории examples (input содержит входные данные для программ).
Память разделена на память команд (инструкций) и память данных.
Память инструкций имеет примерно следующий вид:
+------------------------+
| Instruction memory |
+------------------------+
| 0: br n |
| 1: <func1 code> |
| ... |
| k: <func2 code> |
| ... |
| n: <main code> |
| ... |
| m: halt |
+------------------------+
Машинное слово - 32 бита (8 бит - код операции, 4 бит - тип адресации, 20 бит - значение для адресации).
Первая инструкция - переход к основной программе (которая была странслирована из исходного кода, написанного программистом). Далее хранятся друг за другом используемые программой функции. После всех функции расположены инструкции основной программы. Последняя инструкция - halt
.
Память данных имеет примерно следующий вид:
+------------------------+
| Data memory |
+------------------------+
| 0: const 1 |
| 1: const 2 |
| ... |
| v+0: variable 1 |
| v+1: variable 2 |
| ... |
| b+0: anon buffer 1 |
| b+1: anon buffer 2 |
| ... |
| ... |
| n: stack start |
+------------------------+
Машинное слово - 64 бита.
Сначала располагаются константы (числовые - 1 слово, строковые - количество символов + 1 слов). Далее находятся переменные (по 1 машинному слову). Далее выделены анонимные буферы для некоторых команд, которые представляют несколько размеченных друг за другом слов (например, read
выделяет буфер для чтения данных из ввода). Буферы всегда инициализируются 0. В конце памяти данных находится место для стека, он "растет" от конца памяти к началу.
Программист с регистрами и памятью напрямую не работает.
Строковые литералы всегда считаются константами и записываются в область констант. Числовые литералы считаются константой, если не влазят в 20 бит (то есть больше 2^19-1 или меньше -2^19). Остальные числа будут загружены в регистры при помощи непосредственной адресации.
Порядок расположения констант, переменных, буферов определяется порядком встречи в коде.
Во время трансляции исходной программы если заявляется необходимость выделения константы/переменной/буфера, то в машинном коде временно записывается символ (идентификатор) выделенной памяти. На конечном этапе трансляции происходит маппинг всех запрошенных констант/переменных/буферов на память, а все идентификаторы в машинном коде заменяются на непосредственный адрес.
В стек ничего не отображается.
Поскольку архитектура процессора - аккумуляторная, то все переменные отображаются в память, а при необходимости обращения в аккумулятор загружается их значение. При вызове функций первый аргумент (если есть) передается через аккумулятор, а последующие (если есть) передаются через стек.
Типов данных два: 64-битное знаковое число, строка. Внутри процессора число представляет собой свое значение, а строка - указатель по абсолютному адресу на первый символ.
Регистры:
Название | Разрядность | Описание |
---|---|---|
acr |
64 | аккумулятор |
ipr |
64 | указатель на адрес исполняемой инструкции |
inr |
32 | содержит текущую исполняемую инструкцию |
adr |
64 | регистр адреса, используется для чтения/записи |
dar |
64 | регистр данных, используется для чтения/записи |
spr |
64 | указатель на вершину стека |
flr |
4 | регистр флагов, содержит флаги по результатам операции (NZVC) |
Доступ к памяти данных осуществляется при помощи регистров adr
, dar
. Для чтения необходимо задать адрес ячейки для чтения. Для записи необходимо задать адрес и значение для записи.
Ввод/вывод отображается на память. Для вывода необходимо выполнить запись в ячейку памяти по определенному адресу. Для ввода необходимо выполнить чтение определенной (другой) ячейки памяти.
Имеется 5 типов адресации:
- непосредственная
- абсолютная
- относительная (
ipr
) - относительная (
spr
) - относительная косвенная (
spr
)
Инструкции делятся на 3 типа: без аргумента, адресные, по значению. Инструкции без аргумента не требуют адресации. Адресные используют аргумент адреса с которым будет выполнено действие. Инструкции по значению используют адресацию, для указания на адрес значения, с которым будет выполнено действие.
Набор инструкций:
Инструкция | Описание |
---|---|
noop |
ничего не выполняется |
halt |
останов |
ld <val> |
загрузка значения из памяти в аккумулятор |
st <addr> |
запись значения аккумулятора в память |
call <addr> |
вызвать функцию по адресу (адрес возврата положить на стек) |
ret |
возвращение из функции (адрес возврата снять со стека) |
push |
положить значение аккумулятора на стек |
pop |
снять значение со стека и записать в аккумулятор |
popn |
снять значение со стека без записи куда-либо (spr--) |
cmp <val> |
установить флаги по результату операции вычитания из аккумулятора |
bre <addr> |
переход по адресу если равно (Z == 1) |
brg <addr> |
переход по адресу если значение больше (N == V and Z == 0) |
brge <addr> |
переход по адресу если значение больше или равно (N == V or Z == 1) |
br <addr> |
безусловный переход по адресу |
inc <addr> |
инкремент значения по адресу (без изменения аккумулятора) |
dec <addr> |
декремент значения по адресу (без изменения аккумулятора) |
mod <val> |
деление по модулю аккумулятора и значения |
add <val> |
сложить значение с аккумулятором |
sub <val> |
вычесть из аккумулятора значение |
mul <val> |
умножить аккумулятор на значение |
div <val> |
поделить аккумулятор на значение (целочисленное деление) |
inv |
инвертировать значение аккумулятора |
где:
<val>
- аргумент будет интерпретирован как значение (значение по адресу), с которым необходимо выполнить операцию<addr>
- аргумент будет интерпретирован как адрес, с которым необходимо выполнить операцию
Поток управления:
- вызов
call
или возвратret
из функции - условные
bre
,brg
,brge
и безусловныеbr
переходы - инкремент
ipr
после любой другой инструкции
Машинный код сериализуется в список 32 битных слов. Одно слово - одна инструкция. Адресация инструкций с 0 по порядку.
Кодирование инструкций:
- 8 бит - код операции
- 4 бит - тип адресации (для команд с аргументом)
- 20 бит - значение для адресации (для команд с аргументом)
- (для команд без аргумента 24 младших бита равны 0)
Типы данных в модуле isa:
- Opcode - перечисление кодов операций
- AddressType - перечисление типов адресации
- Address - структура объединение типа адресации и значения
- Term - структура для описания одной инструкции
Стандартная библиотека реализована в модуле stdlib.
Интерфейс командной строки:
usage: translator.py [-h] [--output output_file] [--debug debug_file] [--verbose] [--optimize_math] [--optimize_pop_push] source_file
Translates lispfuck code into en executable file.
positional arguments:
source_file file with lispfuck code
options:
-h, --help show this help message and exit
--output output_file, -o output_file
file for storing a binary executable (default: output)
--debug debug_file, -d debug_file
file for storing a binary executable explanation info (default: debug.txt)
--verbose, -v print verbose information during conversion
--optimize_math optimize math operations (no guarantee of evaluation strategy)
--optimize_pop_push remove pop and push instructions placed next to each over
Реализовано в модуле: translator
Этапы трансляции:
- чтение исходного кода
- трансформация текста в последовательность токенов с тегами
- преобразование токенов в абстрактное дерево (выражение - вершина, литерал/идентификатор - лист)
- вычленение Statement на основе дерева и валидация и проверка корректности использования функций
- генерация машинного кода
- запись полученного кода в бинарный файл
- запись полученного кода в текстовый файл
Правила генерации машинного кода:
- каждый Statement должен к концу исполнения должен установить в аккумулятор возвращаемое значение, а также вернуть spr в то состояние, в котором он был в начале исполнения
- при вызове функции вызывающая сторона обязана установить все требуемые аргументы, а также после возврата снять со стека все положенные аргументы
- Statement содержащий переменную или литерал должен загрузить в аккумулятор нужное значение
- Statement с несколькими аргументами для вычисления производят генерацию кода вычисления с последнего к первому (справа налево)
- при необходимости выделения места в памяти под константу/литерал/буфер, происходит обращение в специальный класс, который запоминает все обращения и выдает идентификаторы для последующей генерации памяти данных и замены символов на непосредственные адреса
- при трансляции кода для функции каждый Statement должен учитывать то, где сейчас находятся (в аккумуляторе, в стеке) аргументы и помещать их на стек в случае необходимости, а также отслеживать их актуальное положение (смещение относительно spr)
- после завершения генерации кода, все символы в инструкциях заменяются на адреса в зависимости от их отображения в память
Интерфейс командной строки:
usage: machine.py [-h] [--input input_file] [--verbose] binary_file
Execute lispfuck binary executable file.
positional arguments:
binary_file binary executable file
options:
-h, --help show this help message and exit
--input input_file, -i input_file
file with input data for executable (default: empty file)
--verbose, -v print verbose information during execution
Реализовано в модуле: machine
latch --->+-------+ +-------+<--- latch
| acr |---------+ +---------| adr |
+----------->+-------+ | | +-------+<-----------+
| | | |
| latch --->+-------+ | | +-------+<--- latch |
| | ipr |-------+ | | +-------| dar | +-----+ |
+----------->+-------+ | | | | +-------+<--| MUX |--+
| | | | | sel --->+-----+ |
| +-------+ | | 0 0 | | +-------+<--- latch |
| | inr |-----+ | | | | | | +-----| spr | |
| +-------+ | | | | | | | | +-------+<-----------+
| v v v v v v v v |
| +---------+ +---------+ |
| sel --->| MUX | | MUX |<--- sel |
| +---------+ +---------+ |
| | | |
| v v |
latch | inv_left --->+---------+ +---------+<--- inv_right |
| | extend_20 --->| \_/ |<--- (+1) |
v | | | |
+-------+ | opcode --->| ALU | |
| flr |<----------------------------\ / |
+-------+ | +-------------------+ |
| | |
+------------------------------------+------------------------------------+
read write
| |
v v
+-------+ +------------+
| adr |--------->| |<------- input
+-------+ | |
| data |-------> output
| memory |
+-------+ | |
latch ---->| dar |--------->| |-------+
+-------+ +------------+ |
^ |
| +-----+ |
+---| MUX |------------------------+
+-----+
^
|
sel
Реализован в классе DataPath
.
Сигналы:
read_data_memory
- чтение данных по адресуadr
вdar
:- из памяти данных (
dar <- mem[adr]
) - из порта ввода
input
:- извлечь из входного буфера токен и подать его на выход
- если буфер пуст - исключение
- из памяти данных (
write_data_memory
- запись данныхdar
по адресуadr
:- в память данных (
mem[adr] <- dar
) - в порт вывода
output
:- записать значение
dar
в буфер вывода
- записать значение
- в память данных (
latch_acr
,latch_ipr
,latch_bur
,latch_adr
,latch_spr
- записать значение с выхода ALU в регистрsel_dar
- выбрать значение с выхода ALU или из памяти данных для записи вdar
latch_dar
- записать выставленное значение вdar
latch_flr
- записать значения флагов операции суммы из ALU вflr
sel_left
,sel_right
- выбрать значения для левого и правого входов ALUalu_opcode
- выбор операции для осуществления на ALU (sum, mul, div, mod)alu_inv_left
,alu_inv_right
- инвертировать левый вход, правый вход ALU соответственноalu_extend_20
- расширить знак 20 бит левого входа ALUalu_plus_1
- прибавить 1 к операции суммы ALU
+---------+
+-->| step |--+ input output
latch | | counter | | | ^
latch +--------------+ | | +---------+ v v |
| read --->| | v | +---------------+ signals +-----------+
v | instructuion | +-------+ +-----| instruction |----------->| DataPath* |
+-------+ | memory |------>| inr |--------->| decoder | +-----------+
+--->| ipr |--------->| | +-------+ +---------------+ | |
| +-------+ +--------------+ ^ | |
| | | |
| +-----------------+ |
| feedback_signals |
| |
+------------------------------------------------------------------------------------------------------+
Реализован в классе ControlUnit
.
Особенности:
- hardwired (реализован полностью на Python, для каждого типа инструкции можно однозначно определить сигналы и их порядок для каждого такта исполнения инструкции)
- step counter - необходим для много-тактовых инструкций
Сигналы:
read_instruction_memory
- чтение данных по адресуipr
вinr
(inr <- mem[ipr]
)latch_inr
- записать значение из памяти инструкций вinr
- signals - управляющие сигналы в DataPath
- feedback_signals - сигналы обратной связи (
flr
)
Шаг декодирования и исполнения одной инструкции выполняется в функции execute_next_instruction
. Во время шага в журнал моделирования записывается исполняемая инструкция и состояние модели на конец исполнения.
Цикл симуляции осуществляется в функции simulation.
Остановка моделирования осуществляется при превышении лимита количества выполняемых инструкций, при отсутствии данных для чтения из порта ввода, при выполнении инструкции halt.
Для тестирования выбраны 7 алгоритмов:
Golden-тесты реализованы в integration_test.py, конфигурация к ним находится в директории golden.
CI реализован через GitHub Actions:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Run tests and collect coverage
run: |
poetry run coverage run -m pytest .
poetry run coverage report -m
env:
CI: true
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Check code formatting with Ruff
run: poetry run ruff format --check .
- name: Run Ruff linters
run: poetry run ruff check .
где:
poetry
- управления зависимостями для языка программирования Python.coverage
- формирование отчёта об уровне покрытия исходного кода.pytest
- утилита для запуска тестов.ruff
- утилита для форматирования и проверки стиля кодирования.
Пример использования и журнал работы процессора на примере hello
:
% cat ./examples/hello
(print "Hello,\nworld!")
% cat ./examples/input/hello
% python translator.py ./examples/hello -v
INFO:root:LoC: 1 code byte: 202 code instr: 20 debug lines: 29
% cat debug.txt
##### Data memory #####
<address> <length> <data>
0x00000000 14 'Hello,\nworld!'
##### Instruction memory #####
<address> <hexcode> <mnemonica>
#:
0x00000000 0x0c200011 br *0x11 ('start' function)
print:
0x00000001 0x06000000 push
0x00000002 0x02100000 ld #0x0
0x00000003 0x06000000 push
0x00000004 0x02500001 ld **spr+0x1
0x00000005 0x09100000 cmp #0x0
0x00000006 0x0a300008 bre *ipr+0x8
0x00000007 0x032015b4 st *0x15b4
0x00000008 0x0d400001 inc *spr+0x1
0x00000009 0x0d400000 inc *spr
0x0000000a 0x02400000 ld *spr
0x0000000b 0x09100080 cmp #0x80
0x0000000c 0x0a300002 bre *ipr+0x2
0x0000000d 0x0c3ffff7 br *ipr-0x9
0x0000000e 0x07000000 pop
0x0000000f 0x08000000 popn
0x00000010 0x05000000 ret
start:
0x00000011 0x02100000 ld #0x0 ('Hello,\nworld!' const)
0x00000012 0x04200001 call *0x1 ('print' function)
0x00000013 0x01000000 halt
% python machine.py output -v
DEBUG:root:br *0x11 tick=1 acr=0x0 ipr=0x11 inr=0xc200011 adr=0x0 dar=0x0 spr=0x1fff flr=0x0 stack_top=?
DEBUG:root:ld #0x0 tick=3 acr=0x0 ipr=0x12 inr=0x2100000 adr=0x0 dar=0x0 spr=0x1fff flr=0x0 stack_top=?
DEBUG:root:call *0x1 tick=7 acr=0x0 ipr=0x1 inr=0x4200001 adr=0x1ffe dar=0x13 spr=0x1ffe flr=0x0 stack_top=0x13
DEBUG:root:push tick=10 acr=0x0 ipr=0x2 inr=0x6000000 adr=0x1ffd dar=0x0 spr=0x1ffd flr=0x0 stack_top=0x0
DEBUG:root:ld #0x0 tick=12 acr=0x0 ipr=0x3 inr=0x2100000 adr=0x1ffd dar=0x0 spr=0x1ffd flr=0x0 stack_top=0x0
DEBUG:root:push tick=15 acr=0x0 ipr=0x4 inr=0x6000000 adr=0x1ffc dar=0x0 spr=0x1ffc flr=0x0 stack_top=0x0
DEBUG:root:ld **spr+0x1 tick=20 acr=0x48 ipr=0x5 inr=0x2500001 adr=0x0 dar=0x48 spr=0x1ffc flr=0x0 stack_top=0x0
DEBUG:root:cmp #0x0 tick=22 acr=0x48 ipr=0x6 inr=0x9100000 adr=0x0 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x0
DEBUG:root:bre *ipr+0x8 tick=23 acr=0x48 ipr=0x7 inr=0xa300008 adr=0x0 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x0
DEBUG:root:output: '' <- 'H'
DEBUG:root:st *0x15b4 tick=26 acr=0x48 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x48 spr=0x1ffc flr=0x1 stack_top=0x0
DEBUG:root:inc *spr+0x1 tick=30 acr=0x48 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x1 spr=0x1ffc flr=0x1 stack_top=0x0
DEBUG:root:inc *spr tick=34 acr=0x48 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x1 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:ld *spr tick=37 acr=0x1 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x1 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:cmp #0x80 tick=39 acr=0x1 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x1
DEBUG:root:bre *ipr+0x2 tick=40 acr=0x1 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x1
DEBUG:root:br *ipr+0xffff7 tick=42 acr=0x1 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x1
DEBUG:root:ld **spr+0x1 tick=47 acr=0x65 ipr=0x5 inr=0x2500001 adr=0x1 dar=0x65 spr=0x1ffc flr=0x8 stack_top=0x1
DEBUG:root:cmp #0x0 tick=49 acr=0x65 ipr=0x6 inr=0x9100000 adr=0x1 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:bre *ipr+0x8 tick=50 acr=0x65 ipr=0x7 inr=0xa300008 adr=0x1 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:output: 'H' <- 'e'
DEBUG:root:st *0x15b4 tick=53 acr=0x65 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x65 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:inc *spr+0x1 tick=57 acr=0x65 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x2 spr=0x1ffc flr=0x1 stack_top=0x1
DEBUG:root:inc *spr tick=61 acr=0x65 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x2 spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:ld *spr tick=64 acr=0x2 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x2 spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:cmp #0x80 tick=66 acr=0x2 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x2
DEBUG:root:bre *ipr+0x2 tick=67 acr=0x2 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x2
DEBUG:root:br *ipr+0xffff7 tick=69 acr=0x2 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x2
DEBUG:root:ld **spr+0x1 tick=74 acr=0x6c ipr=0x5 inr=0x2500001 adr=0x2 dar=0x6c spr=0x1ffc flr=0x8 stack_top=0x2
DEBUG:root:cmp #0x0 tick=76 acr=0x6c ipr=0x6 inr=0x9100000 adr=0x2 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:bre *ipr+0x8 tick=77 acr=0x6c ipr=0x7 inr=0xa300008 adr=0x2 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:output: 'He' <- 'l'
DEBUG:root:st *0x15b4 tick=80 acr=0x6c ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x6c spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:inc *spr+0x1 tick=84 acr=0x6c ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x3 spr=0x1ffc flr=0x1 stack_top=0x2
DEBUG:root:inc *spr tick=88 acr=0x6c ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x3 spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:ld *spr tick=91 acr=0x3 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x3 spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:cmp #0x80 tick=93 acr=0x3 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x3
DEBUG:root:bre *ipr+0x2 tick=94 acr=0x3 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x3
DEBUG:root:br *ipr+0xffff7 tick=96 acr=0x3 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x3
DEBUG:root:ld **spr+0x1 tick=101 acr=0x6c ipr=0x5 inr=0x2500001 adr=0x3 dar=0x6c spr=0x1ffc flr=0x8 stack_top=0x3
DEBUG:root:cmp #0x0 tick=103 acr=0x6c ipr=0x6 inr=0x9100000 adr=0x3 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:bre *ipr+0x8 tick=104 acr=0x6c ipr=0x7 inr=0xa300008 adr=0x3 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:output: 'Hel' <- 'l'
DEBUG:root:st *0x15b4 tick=107 acr=0x6c ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x6c spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:inc *spr+0x1 tick=111 acr=0x6c ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x4 spr=0x1ffc flr=0x1 stack_top=0x3
DEBUG:root:inc *spr tick=115 acr=0x6c ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x4 spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:ld *spr tick=118 acr=0x4 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x4 spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:cmp #0x80 tick=120 acr=0x4 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x4
DEBUG:root:bre *ipr+0x2 tick=121 acr=0x4 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x4
DEBUG:root:br *ipr+0xffff7 tick=123 acr=0x4 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x4
DEBUG:root:ld **spr+0x1 tick=128 acr=0x6f ipr=0x5 inr=0x2500001 adr=0x4 dar=0x6f spr=0x1ffc flr=0x8 stack_top=0x4
DEBUG:root:cmp #0x0 tick=130 acr=0x6f ipr=0x6 inr=0x9100000 adr=0x4 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:bre *ipr+0x8 tick=131 acr=0x6f ipr=0x7 inr=0xa300008 adr=0x4 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:output: 'Hell' <- 'o'
DEBUG:root:st *0x15b4 tick=134 acr=0x6f ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x6f spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:inc *spr+0x1 tick=138 acr=0x6f ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x5 spr=0x1ffc flr=0x1 stack_top=0x4
DEBUG:root:inc *spr tick=142 acr=0x6f ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x5 spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:ld *spr tick=145 acr=0x5 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x5 spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:cmp #0x80 tick=147 acr=0x5 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x5
DEBUG:root:bre *ipr+0x2 tick=148 acr=0x5 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x5
DEBUG:root:br *ipr+0xffff7 tick=150 acr=0x5 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x5
DEBUG:root:ld **spr+0x1 tick=155 acr=0x2c ipr=0x5 inr=0x2500001 adr=0x5 dar=0x2c spr=0x1ffc flr=0x8 stack_top=0x5
DEBUG:root:cmp #0x0 tick=157 acr=0x2c ipr=0x6 inr=0x9100000 adr=0x5 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:bre *ipr+0x8 tick=158 acr=0x2c ipr=0x7 inr=0xa300008 adr=0x5 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:output: 'Hello' <- ','
DEBUG:root:st *0x15b4 tick=161 acr=0x2c ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x2c spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:inc *spr+0x1 tick=165 acr=0x2c ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x6 spr=0x1ffc flr=0x1 stack_top=0x5
DEBUG:root:inc *spr tick=169 acr=0x2c ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x6 spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:ld *spr tick=172 acr=0x6 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x6 spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:cmp #0x80 tick=174 acr=0x6 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x6
DEBUG:root:bre *ipr+0x2 tick=175 acr=0x6 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x6
DEBUG:root:br *ipr+0xffff7 tick=177 acr=0x6 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x6
DEBUG:root:ld **spr+0x1 tick=182 acr=0xa ipr=0x5 inr=0x2500001 adr=0x6 dar=0xa spr=0x1ffc flr=0x8 stack_top=0x6
DEBUG:root:cmp #0x0 tick=184 acr=0xa ipr=0x6 inr=0x9100000 adr=0x6 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:bre *ipr+0x8 tick=185 acr=0xa ipr=0x7 inr=0xa300008 adr=0x6 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:output: 'Hello,' <- '\n'
DEBUG:root:st *0x15b4 tick=188 acr=0xa ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0xa spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:inc *spr+0x1 tick=192 acr=0xa ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x7 spr=0x1ffc flr=0x1 stack_top=0x6
DEBUG:root:inc *spr tick=196 acr=0xa ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x7 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:ld *spr tick=199 acr=0x7 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x7 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:cmp #0x80 tick=201 acr=0x7 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x7
DEBUG:root:bre *ipr+0x2 tick=202 acr=0x7 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x7
DEBUG:root:br *ipr+0xffff7 tick=204 acr=0x7 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x7
DEBUG:root:ld **spr+0x1 tick=209 acr=0x77 ipr=0x5 inr=0x2500001 adr=0x7 dar=0x77 spr=0x1ffc flr=0x8 stack_top=0x7
DEBUG:root:cmp #0x0 tick=211 acr=0x77 ipr=0x6 inr=0x9100000 adr=0x7 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:bre *ipr+0x8 tick=212 acr=0x77 ipr=0x7 inr=0xa300008 adr=0x7 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:output: 'Hello,\n' <- 'w'
DEBUG:root:st *0x15b4 tick=215 acr=0x77 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x77 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:inc *spr+0x1 tick=219 acr=0x77 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x8 spr=0x1ffc flr=0x1 stack_top=0x7
DEBUG:root:inc *spr tick=223 acr=0x77 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x8 spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:ld *spr tick=226 acr=0x8 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x8 spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:cmp #0x80 tick=228 acr=0x8 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x8
DEBUG:root:bre *ipr+0x2 tick=229 acr=0x8 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x8
DEBUG:root:br *ipr+0xffff7 tick=231 acr=0x8 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x8
DEBUG:root:ld **spr+0x1 tick=236 acr=0x6f ipr=0x5 inr=0x2500001 adr=0x8 dar=0x6f spr=0x1ffc flr=0x8 stack_top=0x8
DEBUG:root:cmp #0x0 tick=238 acr=0x6f ipr=0x6 inr=0x9100000 adr=0x8 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:bre *ipr+0x8 tick=239 acr=0x6f ipr=0x7 inr=0xa300008 adr=0x8 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:output: 'Hello,\nw' <- 'o'
DEBUG:root:st *0x15b4 tick=242 acr=0x6f ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x6f spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:inc *spr+0x1 tick=246 acr=0x6f ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0x9 spr=0x1ffc flr=0x1 stack_top=0x8
DEBUG:root:inc *spr tick=250 acr=0x6f ipr=0xa inr=0xd400000 adr=0x1ffc dar=0x9 spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:ld *spr tick=253 acr=0x9 ipr=0xb inr=0x2400000 adr=0x1ffc dar=0x9 spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:cmp #0x80 tick=255 acr=0x9 ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x9
DEBUG:root:bre *ipr+0x2 tick=256 acr=0x9 ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x9
DEBUG:root:br *ipr+0xffff7 tick=258 acr=0x9 ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0x9
DEBUG:root:ld **spr+0x1 tick=263 acr=0x72 ipr=0x5 inr=0x2500001 adr=0x9 dar=0x72 spr=0x1ffc flr=0x8 stack_top=0x9
DEBUG:root:cmp #0x0 tick=265 acr=0x72 ipr=0x6 inr=0x9100000 adr=0x9 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:bre *ipr+0x8 tick=266 acr=0x72 ipr=0x7 inr=0xa300008 adr=0x9 dar=0x0 spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:output: 'Hello,\nwo' <- 'r'
DEBUG:root:st *0x15b4 tick=269 acr=0x72 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x72 spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:inc *spr+0x1 tick=273 acr=0x72 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0xa spr=0x1ffc flr=0x1 stack_top=0x9
DEBUG:root:inc *spr tick=277 acr=0x72 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0xa spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:ld *spr tick=280 acr=0xa ipr=0xb inr=0x2400000 adr=0x1ffc dar=0xa spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:cmp #0x80 tick=282 acr=0xa ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xa
DEBUG:root:bre *ipr+0x2 tick=283 acr=0xa ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xa
DEBUG:root:br *ipr+0xffff7 tick=285 acr=0xa ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xa
DEBUG:root:ld **spr+0x1 tick=290 acr=0x6c ipr=0x5 inr=0x2500001 adr=0xa dar=0x6c spr=0x1ffc flr=0x8 stack_top=0xa
DEBUG:root:cmp #0x0 tick=292 acr=0x6c ipr=0x6 inr=0x9100000 adr=0xa dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:bre *ipr+0x8 tick=293 acr=0x6c ipr=0x7 inr=0xa300008 adr=0xa dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:output: 'Hello,\nwor' <- 'l'
DEBUG:root:st *0x15b4 tick=296 acr=0x6c ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x6c spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:inc *spr+0x1 tick=300 acr=0x6c ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0xb spr=0x1ffc flr=0x1 stack_top=0xa
DEBUG:root:inc *spr tick=304 acr=0x6c ipr=0xa inr=0xd400000 adr=0x1ffc dar=0xb spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:ld *spr tick=307 acr=0xb ipr=0xb inr=0x2400000 adr=0x1ffc dar=0xb spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:cmp #0x80 tick=309 acr=0xb ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xb
DEBUG:root:bre *ipr+0x2 tick=310 acr=0xb ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xb
DEBUG:root:br *ipr+0xffff7 tick=312 acr=0xb ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xb
DEBUG:root:ld **spr+0x1 tick=317 acr=0x64 ipr=0x5 inr=0x2500001 adr=0xb dar=0x64 spr=0x1ffc flr=0x8 stack_top=0xb
DEBUG:root:cmp #0x0 tick=319 acr=0x64 ipr=0x6 inr=0x9100000 adr=0xb dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:bre *ipr+0x8 tick=320 acr=0x64 ipr=0x7 inr=0xa300008 adr=0xb dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:output: 'Hello,\nworl' <- 'd'
DEBUG:root:st *0x15b4 tick=323 acr=0x64 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x64 spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:inc *spr+0x1 tick=327 acr=0x64 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0xc spr=0x1ffc flr=0x1 stack_top=0xb
DEBUG:root:inc *spr tick=331 acr=0x64 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0xc spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:ld *spr tick=334 acr=0xc ipr=0xb inr=0x2400000 adr=0x1ffc dar=0xc spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:cmp #0x80 tick=336 acr=0xc ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xc
DEBUG:root:bre *ipr+0x2 tick=337 acr=0xc ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xc
DEBUG:root:br *ipr+0xffff7 tick=339 acr=0xc ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xc
DEBUG:root:ld **spr+0x1 tick=344 acr=0x21 ipr=0x5 inr=0x2500001 adr=0xc dar=0x21 spr=0x1ffc flr=0x8 stack_top=0xc
DEBUG:root:cmp #0x0 tick=346 acr=0x21 ipr=0x6 inr=0x9100000 adr=0xc dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:bre *ipr+0x8 tick=347 acr=0x21 ipr=0x7 inr=0xa300008 adr=0xc dar=0x0 spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:output: 'Hello,\nworld' <- '!'
DEBUG:root:st *0x15b4 tick=350 acr=0x21 ipr=0x8 inr=0x32015b4 adr=0x15b4 dar=0x21 spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:inc *spr+0x1 tick=354 acr=0x21 ipr=0x9 inr=0xd400001 adr=0x1ffd dar=0xd spr=0x1ffc flr=0x1 stack_top=0xc
DEBUG:root:inc *spr tick=358 acr=0x21 ipr=0xa inr=0xd400000 adr=0x1ffc dar=0xd spr=0x1ffc flr=0x1 stack_top=0xd
DEBUG:root:ld *spr tick=361 acr=0xd ipr=0xb inr=0x2400000 adr=0x1ffc dar=0xd spr=0x1ffc flr=0x1 stack_top=0xd
DEBUG:root:cmp #0x80 tick=363 acr=0xd ipr=0xc inr=0x9100080 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xd
DEBUG:root:bre *ipr+0x2 tick=364 acr=0xd ipr=0xd inr=0xa300002 adr=0x1ffc dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xd
DEBUG:root:br *ipr+0xffff7 tick=366 acr=0xd ipr=0x4 inr=0xc3ffff7 adr=0xd dar=0x80 spr=0x1ffc flr=0x8 stack_top=0xd
DEBUG:root:ld **spr+0x1 tick=371 acr=0x0 ipr=0x5 inr=0x2500001 adr=0xd dar=0x0 spr=0x1ffc flr=0x8 stack_top=0xd
DEBUG:root:cmp #0x0 tick=373 acr=0x0 ipr=0x6 inr=0x9100000 adr=0xd dar=0x0 spr=0x1ffc flr=0x5 stack_top=0xd
DEBUG:root:bre *ipr+0x8 tick=375 acr=0x0 ipr=0xe inr=0xa300008 adr=0x6 dar=0x0 spr=0x1ffc flr=0x5 stack_top=0xd
DEBUG:root:pop tick=379 acr=0xd ipr=0xf inr=0x7000000 adr=0x1ffc dar=0xd spr=0x1ffd flr=0x5 stack_top=0xd
DEBUG:root:popn tick=380 acr=0xd ipr=0x10 inr=0x8000000 adr=0x1ffc dar=0xd spr=0x1ffe flr=0x5 stack_top=0x13
DEBUG:root:ret tick=384 acr=0xd ipr=0x13 inr=0x5000000 adr=0x1ffe dar=0x13 spr=0x1fff flr=0x5 stack_top=?
INFO:root:instr: 142 ticks: 384
Hello,
world!
Пример проверки исходного кода:
% poetry run pytest . -v
============================================================================================= test session starts ==============================================================================================
platform darwin -- Python 3.12.0, pytest-7.4.3, pluggy-1.3.0 -- /Users/andryssssss/Library/Caches/pypoetry/virtualenvs/lispfuck-qe1KGZJD-py3.12/bin/python
cachedir: .pytest_cache
rootdir: /Users/andryssssss/Programming/Projects/Python/ITMO/ComputerArchitectureLab3
configfile: pyproject.toml
plugins: golden-0.2.2
collected 7 items
integration_test.py::test_translator_and_machine[golden/func.yml] PASSED [ 14%]
integration_test.py::test_translator_and_machine[golden/if.yml] PASSED [ 28%]
integration_test.py::test_translator_and_machine[golden/math.yml] PASSED [ 42%]
integration_test.py::test_translator_and_machine[golden/hello.yml] PASSED [ 57%]
integration_test.py::test_translator_and_machine[golden/prob5.yml] PASSED [ 71%]
integration_test.py::test_translator_and_machine[golden/hello_user_name.yml] PASSED [ 85%]
integration_test.py::test_translator_and_machine[golden/echo.yml] PASSED [100%]
============================================================================================== 7 passed in 0.61s ===============================================================================================
% poetry run ruff check .
% poetry run ruff format .
5 files left unchanged
Статистика:
alg | LoC | code byte | code instr | debug lines | instr | ticks |
---|---|---|---|---|---|---|
hello | 1 | 202 | 20 | 29 | 142 | 384 |
echo | 1 | 174 | 41 | 50 | 126 | 348 |
hello_user_name | 4 | 278 | 47 | 58 | 250 | 688 |
prob5 | 16 | 698 | 132 | 145 | 2781 | 7266 |
if | 1 | 206 | 49 | 58 | 174 | 484 |
math | 6 | 550 | 131 | 143 | 191 | 534 |
math (optimized) | 6 | 422 | 99 | 111 | 159 | 426 |
func | 20 | 562 | 120 | 134 | 275 | 756 |