Skip to content

Instantly share code, notes, and snippets.

@Alikberov
Last active May 13, 2020 10:07
Show Gist options
  • Save Alikberov/4c5da210ff1a862e6469e403b95767de to your computer and use it in GitHub Desktop.
Save Alikberov/4c5da210ff1a862e6469e403b95767de to your computer and use it in GitHub Desktop.
x80 Emulator
<html>
<head>
<meta http-equiv='refresh' content='50000' />
<title>x80 - Rebused Instruction Set Computer</title>
<!--
- 1 1 1 3 1 1 1
2 5 1 1 1 1 1 1
2 2 5 1 1 1 1 1
2 2 2 5 1 1 1 1
3 2 2 2 7 1 1 1
2 2 2 2 2 6 1 1
2 2 2 2 2 2 6 1
2 2 2 2 2 2 2 6
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
0 0 0 0 0 0 0 0 0 0 4 5 6 7 1 2
0 0 0 0 0 0 0 0 0 0 4 5 6 7 1 2
0 0 0 0 0 0 0 0 0 0 4 5 6 7 1 2
0 0 0 0 0 0 0 0 0 0 4 5 6 7 1 2
1010 100
1011 101
1100 110
1101 111
1110
1111
Пользовательские операции
=========================
Контекст задачи имеет область статической памяти под хранение кодов инструкций
программируемых приложением, с возможностью определить до десяти команд в семь
операций каждая с максимальной скоростью выполнения до одной команды в 1 такт.
Для линейного определения пользовательской инструкции имеется особая операция,
трюковая комбинация WAIT+FIX, которыми подготавливается сегмент буфер, ячейкам
определённой цепочки присваивается соответствующая маска к оперативному вводу.
--
B8 FE|WAIT __ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F ______
44 F7 |INT 47 |70:?? ?? FF FF FF FF FF FF FF FF 00 00 00 00 00 00|SKIP 4
04 |MOV AL,[BX]|70:?? ?? 04 00 FF FF FF FF FF FF 00 00 00 00 00 00|3 ticks
70 |MOV [BX],DL|70:?? ?? 04 00 70 00 FF FF FF FF 00 00 00 00 00 00|2 ticks
47 |MOV DL,AL |70:?? ?? 04 00 70 00 47 00 FF FF 00 00 00 00 00 00|1 tick
77 CB |ADD BX,DX |70:?? ?? 04 00 70 00 47 00 CB E0 00 00 00 00 00 00|1 tick
______________________________________________________________________________
==============================================================================
Представляемая концепция процессорного устройства базируется на переработанной
системе команд процессора i8080 с полной утратой совместимости уровня машинных
команд и с частично достигнутой совместимостью с ассемблером процессора i8086.
______________________________________________________________________________
Таблица системы команд процессора была расчитана под интуитивное восприятие на
принципе ассоциативных предпосылок субъективного уровня с учитыванием реальной
возможной частоты использования различных инструкций в построениях алгоритмов.
Некоторые из инструкций, в силу морального устаревания и потерей актуальности,
были изначально исключены или получили более комплексный код редкой комбинации
обычных команд, чтобы не засорять таблицу и сохранять перспективу наращивания.
Регистр статуса процессора был переорганизован и флажки АЛУ получили частичную
связь на дешифратор команд с возможностью управлять периодом выполнения команд
для явного объявления условно реактивных и ленивых участков программного кода.
______________________________________________________________________________
Инструкции: Система команд процессора
=====================================
Дешифратор команд имеет 18 разрядов, имеющий условно разделённо-группированных
восемь проименованных шин и каждая из них имеет своё назначение для дешифрации
всех поддерживаемых архитектурой инструкций с перспективой явного наращивания.
Всего набор команд представляется таблицей команд с восемью слоями и имеющих в
своей структуре до восьми подслоёв, половина из которых доступна лишь основной
программе высшего уровня привелегий, выполняющей роль ядра операционной среды.
В состав процессора входит сверхоперативный контекстный файл с ёмкостью до 128
страниц, каждая из которых вмещает по 256 слов и обеспечивает сохранность всех
значений регистров общего назначения независимо для каждой страницы контекста.
Страница контекста имеет до 160 слов хранения операций реактивного исполнений,
вызываемых трюковым способом из любого места программы и требующих как минимум
от 1 такта на своё выполнение, позволяющих организовывать комплексные команды.
______________________________________________________________________________
Регистры Общего Назначения (РОН)
================================
Каждой исполняемой задаче доступен собственный независимый набор регистров, из
которых можно выделить несколько особенных, имеющих механизмы контроля ошибок,
автоматического инкремента/декремента и организации ленивых вычислений/циклов.
Так, регистры BH:BL / CH:CL / DH:DL составляют набор регистровых пар BX/CX/DX,
позволяющих организовывать косвенную и индексную адресацию для доступа к любой
из всех ячеек предоставляемой операционной средой памяти в оперативном режиме.
Несколько иначе организован регистр аккумулятора AL, имеющий условную половину
AH(FX) косвенно-условной доступности, позволяющего обеспечивать условные петли
и безусловные циклы, а также и опциональные линейные селекторы или вычисления.
________________ _________________ _________________ _________________
| AX | | BX | | CX | | DX |
+---------+------+ +--------+--------+ +--------+--------+ +--------+--------+
| AH(FX) | AL | | BH | BL | | CH | CL | | DH | DL |
+----+----+------+ +--------+--------+ +--------+--------+ +--------+--------+
| FH | FL \
| == | == \________
|0:--|0000: ------- \____________________________________________
|1:BH|0001:-- -- ZF # Zeroed result |
|2:CH|0010:-- CF -- # Carry Flag |
|3:DH|0011:-- CF ZF # Zero with Carry |
|4:AL|0100:PF -- -- # Odd Parity Flag |
|5:BL|0101:{SKIP FH}# Skip mode (upto x8..x15 times/x1..x7 times) |
|6:CL|0110:PF CF -- # Odd Parity with Carry |
|7:DL|0111:{SKIP FH}# Skip mode (upto x8..x15 times/x1..x7 times) |
|8:--|1000:SF -- -- # Signed result |
|9:x1|1001:{LOOP FH}# Loop mode (register counter / x1..x7 times) |
|A:x2|1010:SF CF -- # Signed result with Carry |
|B:x3|1011:{LOOP FH}# Loop mode (register counter / x1..x7 times) |
|C:..|1100:SF PF -- # Signed result with odd Parity |
|D:BX|1101:{ ----- }# |
|E:CX|1110:SF PF CF # Signed result with odd Parity and Carry |
|F:DX|1111:{WAIT FH}# Wait mode (register counter / x1..x7 times) |
+----+------------------------------------------------------------
______________________________________________________________________________
Регистровые указатели
=====================
Указатель инструкций IP имеет опциональный указатель JP, у стековых указателей
SP и BP младший бит имеет опциональное назначение для отслеживания критических
ситуаций или управления автоматическим инкрементом/декрементом значений SI/DI.
+----------------+ +---------------+-+ +---------------+-+ +-----------------+
|______ IP ______| | SP /EF| | BP /FF| |_____ SI/DI _____|
| \__/ | | +-----+ / | | +-----+ / | | \++|--/ |
| JP | | /Error-Flag| | /Fault-Flag| |Auto-Inc|Auto-Dec|
+----------------+ | / /increment| +-----+-----------+ +-----------------+
+----+------------+
______________________________________________________________________________
Флаги: Регистр состояния процессора/АЛУ
=======================================
Регистр состояния FX является старшим AH в AX, разделён на два ниббла FH и FL.
Старшим нибблом хранится индекс опционального регистра/указателя или итерации.
Младшим нибблом отражается комбинация режима дешифратора инструкций с флажками
результата действий команд АЛУ. Правилами постулатов исполнения вычислительных
операций исключаются вариации нуля нечётного паритета или отрицательного нуля.
Ноль нечётного паритета запрещает регистрирование результата выполнения потока
дешифрируемых инструкций на период с декрементацией опционального регистра или
итерации в старшем ниббле, позволяя опционально пропускать цепочку инструкций.
Отрицательный ноль приостанавливает считывание следующих инструкций, организуя
цикл на период с полной или условной декрементацией опционального регистра или
итерации в старшем ниббле, позволяя опционально ставить цикл и режим ожидания.
Через режим условного ожидания организуется возможность доступа к интерфейсным
устройствам ввода/вывода или внешней шине состояния сигналов событий ресурсов,
чтобы описывать алгоритмы своевременной обработки всех допускаемых прерываний.
______________________________________________________________________________
Обработка программных и аппаратных прерываний
=============================================
Архитектурой процессора не предусматривается возможность оперативной реакции в
режиме реального времени на любые внешние сигналы от периферии с генерацией по
их запросам определённых прерываний на обращение к соответствующим процедурам.
После включения ядра процессора и аппаратного сброса, управление передаётся на
нулевой контекст программы по вектору 0xFF00 с возможностью прямого доступа ко
всем ресурсам среды системы, всем контекстным файлам и к регистрам управления.
В обязанности кода основного процесса входит необходимость настройки периферии
и соответствующего реагирования на любые внешние сигналы с её стороны, а также
организации поддержки интерфейса с другим прикладным программным обеспечением.
Процесс ядра системы не имеет возможность непосредственного опроса внешних шин
и считывания их состояния без организации исполнения кода прикладного уровня с
поддержанием его нормального исполнения и надлежащего предоставления ресурсов.
______________________________________________________________________________
Доступ к внешним устройствам и регистрам контекстного файла
===========================================================
Системой команд не предусматриваются непосредственные команды доступа к портам
ввода/вывода для взаимодействия с устройствами периферии или доступа к ячейкам
контекстного файла и управляющим регистрам представления контекстной проекции.
Подобные операции находятся за пределами области задач прикладного уровня и не
засоряют таблицу команд как специализированные инструкции, используемые крайне
редко в зонах временной необходимости сервисных процедур операционной системы.
Процессором имеется достаточное количество префиксов для организации трюкового
достижения необходимых системных ресурсов в рамках кода операционной системы и
ограниченного контролируемого прикладного трюкового доступа к нужным ресурсам.
В момент попытки доступа приложения к порту ввода/вывода, исполнение программы
временно приостанавливается и управление передаётся ядру системы с загрузкой в
историю регистра-приёмника индекса порта, байта данных и режимом доступа в CF.
______________________________________________________________________________
Регистр селектора контекста (CS - Context Select Register)
==========================================================
Для непосредственного доступа к контексту любой имеющейся прикладной задачи на
уровне системного процесса доступен регистр CS, служащего переключателем задач
в системной среде и управляющего привелегиями для текущего активного процесса.
Базовая реализация процессора поддерживает от трёх независимых контекстов, под
которыми может выполняться непосредственно код системного ядра, код диспетчера
системных ресурсов с аппаратным интерфейсом и другой код прикладной программы.
Контекст ядра всегда имеет индекс с базой 0, диспетчерам ресурсов определяются
контексты с индексами от 127 до 100 в сторону уменьшения номера, тогда как все
приложения индексируются контекстами от 1 до 99 в сторону возрастания номеров.
------------------------------------------------------------------------------
00000000 0 :База(0) - Системный код с высоким уровнем привелегий.
0XXXXXXX 1-99 :База(1) - Прикладной код с низким уровнем привелегий.
011XXXXX 100-127:База(127)-Средний уровень диспетчера системных ресурсов.
1XXXXXXX 128-255:Зеркала контекста №0 под высоким системным уровнем привелегий
______________________________________________________________________________
Счётчик выдержки исполнения прикладного кода (TX - Ticks Counter: TL & TH)
===========================================================================
Старший бит регистра CS управляет блокировкой прохождения тактов к регистру TX
и на уровне приложений ведётся обратный отсчёт, окончание которого установит в
CS бит блокировки счёта с переключением контекста в высокий системный уровень.
Если при переключении с ядра к приложению счётчик TX был обнулён, ни один байт
прикладного кода не будет выполнен и управление получит вновь ядро с возвратом
кода состояния внешней периферийной шины через аккумклятор и флаг переноса CF.
Если в момент переключения на контекст приложения счётчик TX готов отсчитать 1
такт, будет выполнена одна единственная операция приложения и управление снова
получит ядро, что позволяет организовывать пошаговый режим отладчика программ.
______________________________________________________________________________
Математические вычисления
==============================================================================
Операции умножения/деления изначально отсутствуют в системе команд процессора,
но достигаются трюковым способом посредством режима цикла условного ожидания с
элементарной арифметической операцией с пошаговыми приближениями к результату.
Если вычислительная периферия в системе присутствует и поддерживает инструкции
аппаратно, итеративного испольнения цикла не будет и он будет линейно прерван,
позволяя программно определить наличие соответствующей поддерживающей системы.
______________________________________________________________________________
Расширитель опции вызова подпрограмм
==============================================================================
Совмещение команд обращения к подпрограммам с префиксами инструкционного цикла
переключает дешифратор команд на пропуск опционального числа операций на входе
в подпрограмму, позволяя выбирать из подфункций вызываемого процедурного кода.
..::: Context File Layout ::::::::::::::::::::::::::::::::::::::::::::::::::::
.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
00:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 0:Up to 7 opcodes
10:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 1:---"---
20:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 2:---"---
30:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 3:---"---
40:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 4:---"---
50:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 5:---"---
60:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 6:---"---
70:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 7:---"---
80:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 8:---"---
90:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 9:---"---
A0:AL>>LO>>Стек истории --|AH>>HI>> ++ .. -- -- --|AX-Stack
B0:BL>>LO>>модификации- --|BH>>HI>> ++ .. -- -- --|BX-Stack
C0:CL>>LO>>всех РОН- -- --|CH>>HI>> ++ .. -- -- --|CX-Stack
D0:DL>>LO>> ++ .. -- -- --|DH>>HI>> ++ .. -- -- --|DX-Stack
E0:SP>LO/BP>LO/SI>LO/DI>LO|SP>HI/BP>HI/SI>HI/DI>HI|SP/BP/SI/DI-Stack
F0:IP>>LO>> ++/.. ../JP.LO|IP>>HI>> ++/.. ../JP.HI|IP/JP
+0:CS -- -- -- -- -- TL.TH |Control Registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Примерная трюковая цепочка ;;; Макрос псевдонима мнемоники с описанием ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MOV [0],DL ;;; Запись индекса проекции контекста
HLT DL ; Указываем регистр источника индекса
WAIT ; Приступаем к ожиданию системной операции
HLT ; Инструкция работает лишь в проекции системы
;;;;;;; MOV DL,[0] ;;; Чтение индекса проекции контекста
HLT ; Выбираем индекс считываемого регистра
WAIT ; Приступаем к ожиданию системной операции
HLT DL ; Считываем в регистр индекс проекции
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MOV DL,[DL] ;;; Читаем байт файла контекста
HLT DL ; Указываем принимающий регистр
WAIT ; Готовимся читать данные
HLT DL ; В регистр DL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MOV [DL],AL ;;; Пишем байт в файл контекста
HLT DL ; Указываем регистр выбора ячейки
WAIT ; Готовимся писать данные
HLT AL ; в ячейку DL из регистра AL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MOV DL,[1] ;;; Читаем байт регистра контроля
HLT 1 ; Указываем индекс считываемого регистра
WAIT ; Готовимся читать данные
HLT DL ; Указываем принимающий регистр
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MOV [1],DL ;;; Пишем байт в регистр контроля
HLT DL ; в ячейку из регистра DL
WAIT ; Готовимся писать данные
HLT 1 ; Указываем регистр контроля
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; IN DH ;;; Читаем данные с порта
HLT 1 ; Вибираем индекс регистра BH с индексом порта
WAIT ; Готовимся читать данные
HLT 1 ; В регистр BH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; OUT [DH],CH ;;; Пишем данные в порт
HLT 1 ; Выбираем регистр BH с записуемым байтом
WAIT ; Готовимся писать данные
HLT 2 ; в порт CH из регистра BH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Примеры инструкций с расширением их возможностей опциональными битами ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV AL,[DI+1] ; Считывает данные с базовым смещением,
; работает во всех стандартных режимах (EF==0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV AL,[DI+1] ; Считывает данные без смещения, но производит
; пост-инкремент указателя, лишь когда (EF==1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Примеры трюковых цепочек для выполнения вычислений с проверкой ускорения ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; MUL AL,CH,CL ; Умножение с суммированием: AL+=CH*CL
HLT CL ; Указываем регистр множителя CL
WAIT ; Готовимся к вычислению
ADD AL,CH ; Приближаемся к результату через множимое CH
AND CL,CL ; Проверка участия регистра множителя в цикле
JZ .software ; Если он обнулён - аппаратной поддержки нет
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; DIV AL,CH,CL ; Деление: CL=255 :: CL-=AL/CH
HLT CL ; Указываем регистр дополненного частного CL
WAIT ; Готовимся к вычислению
SUB AL,CH ; Приближаемся к результату через делитель CH
JC .software ; Если признак CF - аппаратной поддержки нет
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Примерный набросок кода запуска управляющего ядра операционной системы ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0xFEFB ; Следующий макрос занимает 5 байтов
KERNEL: ;;;;;;;;;;;;;;;;;;;;;;;;; Переключатель контекста на прикладной код
.yield: MOV [0],AL ; Макрос переключения контекста регистром CR0
;HLT AL ; Регистр AL указывает контекст/принимает код
;WAIT ; JMP $ - Переход в условный цикл
;HLT 0 ; HLT - Привелегированная операция для CR[0]
;;;;;;;;;;;;;;;;;;;;;;;;;
; Здесь располагается селектор с пропуском до 7 инструкций и передачей
; управления соответствующей ситуации процедуре
.body: ;;;;;;;;;;;;;;;;;;;;;;;;; Тело обработчика прерываний - адрес : FF00h
JMP .overhead ; Запрос к стандартному API
JMP .acclaim ; Обращение к программным прерываниям INT 0-79
JMP .buffer ; Буферная зона - прослойка диспетчера памяти
JMP .context ; Диспетчер переключения контекстов процессов
JMP .device ; Запрос ко внешнему устройству ввода/вывода
JMP .error ; Обработчик программных/аппаратных ошибок
JMP .force ; Внешние форсированные события/прерывания
JMP .garret ; Загрузочная область поверхностного уровня
.context: ;;;;;;;;;;;;;;;;; Тело диспетчера контекста
XOR AL,AL ; Подготавливаем регистр к чтению регистра CR
HLT AL ; Определяем его как приёмник
WAIT ; Переход в условный цикл
HLT 7 ; Считываем содержимое CR[7] в AL
;;; ;;; ;;; ; Оперативные действия с контекстом
MOV AL,0x01 ; Выставляем индекс выбираемого контекста
CMP AL,AL ; Сброс флага переноса CF
CMC ; Устанавливаем флаг, если требуется протокол
JMP .yield ;
.device: ;;;;;;;;;;;;;;;;; Тело диспетчера периферии
HLT___________________________________________________________________________
00 :HLT ;Останов. Команда не работает на системном уровне
nn 00 :HLT Rn ;Захват регистра за опциональный
nn nn :HLT Pn/n ;Захват указателя или числового индекса
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOV___________________________________________________________________________
yx :MOV Rx,Ry ;Пересылка между регистрами
44 yx :MOV Px,Py ;Пересылка между указателями
Ax ii:MOV Rx,i ;Загрузка непосредственной константы в регистр
nn Ax ii:MOV Rx,[Pn+i] ;Загрузка с базовым смещением
nn Bx ii:MOV [Pn+i],Rx ;Выгрузка в базовое смещиние
r# nn Bx ii:MOV [Pn+=i],Rx ;Выгрузка по смещению и итерационным шагом
w# xx :MOV Rx,[Rx] ;Чтение с контекста
w# yx :MOV [Rx],Ry ;Запись в контекст
w# nn nn :MOV Rw,[n] ;Чтение управляющего регистра
w# ?? 00 :MOV [?],Rw ;Запись в управляющий регистр
w# 00 :MOV [0],Rw ;Переключение контекста
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
JMP___________________________________________________________________________
B8 ii:JMP $+i ;Ветвление с относительной адресацией -128..+127
nn B8 ii:JMP $+n+i ;Ветвление с относительной адресацией -1024..+1023
nn 8m ii FF:JMP n+m+i ;Ветвление с абсолютной адресацией 0..65535
w# 00 :JMP Rw ;Переключение контекста
------------------------------------------------------------------------------
WAIT__________________________________________________________________________
B8 FE:WAIT ;Ветвление с замыканием в режим условного ожидания
nn nn B8 FE:WAIT n ;Пример режима ожидания с указанием длительности
nn 00 B8 FE:WAIT Rn ;Пример режима ожидания с указанием счётчика
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
______________________________________________________________________________
r# - означает префикс повтора командами LOOP n/Rn/[Rn]
w# - означает префикс ожидания командами WAIT n/Rn
------------------------------------------------------------------------------
ПРИМЕРЫ_______________________________________________________________________
44 00 B8 FE 55 55:MOV AL,[5] ;Чтение управляющего регистра
44 00 B8 FE 55 00:MOV [5],AL ;Запись в управляющий регистр
44 00 B8 FE 00 :JMP AL ;Переключение на контекст задачи
44 FС 22 B6 03 :MOV [SI+=3],CL ;Запись с итерационным шагом счётчика AL
44 FC 22 A6 7D :MOV CL,[BX+2*AL];Чтение с двойной шириной по базе
[DI+0..99] .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
[DI+100..127] AL BL CL DL BH CH DH DX CX DX
+100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127
................................................. 1*BX 1*BH 1*CH 1*DH 1*AL 1*BL 1*CL 1*DL 1*CX 1*DX 2*BX 2*BH 2*CH 2*DH 2*AL 2*BL 2*CL 2*DL
0:+0
1:+1
2:+2
3:
4:
5:
6:
7:
8:
9:
10:BX*1
11:BH*1
12:CH*1
13:DH*1
14:AL*1
15:BL*1
16:CL*1
17:DL*1
18:CX*1
19:DX*1
20:BX*2
21:BH*2
22:CH*2
23:DH*2
24:AL*2
25:BL*2
26:CL*2
27:DL*2
28:CX*2
29:DX*2
30:-2
31:-1
;;;;;;; IN DH
WAIT
MOV DH,[BX]
;;;;;;; OUT DH,DL
WAIT
MOV DH,DL
;;;;;;; MOV AL,[AL]
WAIT
MOV AL,[
00000000 0 :
0XXXXXXX 1-99 :
011XXXXX 100-127:
1XXXXXXX 128-255:Зеркала контекста №0 под высоким системным уровнем привелегий
00000000|Kernel Mode Execution
0xxxxxxx|Kernel Mode Access
10000000|
1xxxxxxx|User Mode Execution
-->
<!--
span.CPU_Group__ {
background-color: #012;
cursor : pointer;
}
span.CPU_Group_A {
background-color: #771;
}
span.CPU_Group_B {
background-color: #751;
}
span.CPU_Group_C {
background-color: #411;
}
span.CPU_Group_D {
background-color: #551;
}
span.CPU_Group_E {
background-color: #161;
}
span.CPU_Group_F {
background-color: #157;
}
-->
<!--
span.CPU_Group__ {
background-color: #012;
cursor : pointer;
}
span.CPU_Group_A {
background-color: blue;
}
span.CPU_Group_B {
background-color: brown;
}
span.CPU_Group_C {
background-color: cyan;
}
span.CPU_Group_D {
background-color: red;
}
span.CPU_Group_E {
background-color: #161;
}
span.CPU_Group_F {
background-color: magenta;
}
-->
<!--
A:ALU
B:Branch
C:Control
D:Dubbed register pair
E:Stack
F:Flip-flop move
-->
<style>
span[class^=CPU_Group_] {
border : none;
color : brightgreen;
cursor : default;
margin : 0px 0px 0px 0px;
padding : none;
}
span.active {
text-decoration : overline underline;
}
span.halted {
color : magenta;
cursor : cell;
}
span.CPU_Group__ {
background-color: #012;
cursor : pointer;
}
span.CPU_Group_A {
background-color: #772; <!-- ALU - AND/XOR/CMP 772-->
}
span.CPU_Group_B {
background-color: #764; <!-- Branching - Ccnd/Jcnd 752-->
}
span.CPU_Group_C {
background-color: #888; <!-- Controls - HLT/NOP 888-->
}
span.CPU_Group_D {
background-color: #663; <!-- Dubbed/Pair - INC/DEC 552-->
}
span.CPU_Group_E {
background-color: #363; <!-- Xchg/Stack - POP/PUSH 262-->
}
span.CPU_Group_F {
background-color: #367; <!-- Flip-Flop - MOV 257-->
}
span.CPU_Group_X {
background-color: #437; <!-- X-Code - --- 437-->
}
span.CPU_Group_Z {
background-color: #444; <!-- X-Code - --- 437-->
}
body {
background-color: black;
color : lightgreen;
padding : 0 0 0 2;
margin : 0 0 0 0;
overflow : auto;
}
input {
border : none;
border-spacing : 0px 0px;
background-color: grey;
font-family : Courier New;
font-size : 9px;
margin : 0 0 0 0;
padding : 0 0 0 0;
}
table {
border : none;
border-spacing : 0px 0px;
font-family : Courier New;
font-size : 9px;
}
tr {
margin : 10px 10px 10px 10px;
padding : none;
}
td {
border-top : none;
border-left : none;
border-right : thin green solid;
border-bottom : thin green solid;
}
button {
padding : 0 0 0 0;
margin : 0 0 0 0;
font-size : 7px; width: 4em;
}
pre#state {
padding : 0 0 0 0;
margin : 0 0 0 0;
}
pre {
margin : 0px 0px 0px 0px;
}
textarea {
border : none;
padding : 0 0 0 0;
margin : 0px 0px 0px 0px;
font-family : Courier;
font-height : 19px;
font-size : 8px;
}
textarea#Files {
display : none;
}
pre#Screen {
margin : 0px 0px 0px 0px;
font-family : Courier;
font-size : 10px;
font-width : 14px;
//border : thick grey inset;
}
pre#commands {
cursor : default;
}
var {
display : none;
}
span.prefix {
cursor : pointer;
}
span.prefix:hover {
color : yellow;
font-weight : bolder;
}
select {
font-family : Courier New;
font-size : 9px;
}
</style>
<script>
/****************************************************************************/
Number.prototype.Hex = function(n) {
return (n < 0 ? "0x" : "") + ((((this >> 16) & 0x0000FFFF) | 0x00010000).toString(16) + ((this & 0x0000FFFF) | 0x00010000).toString(16).substr(1)).substr(-Math.abs(n)).toUpperCase();
}
Number.prototype.hi = function(n) {
if(isFinite(n))
return (this & 0x00FF) | ((n & 0x00FF) << 8);
return (this >> 8) & 0x00FF;
}
Number.prototype.lo = function(n) {
if(isFinite(n))
return (this & 0xFF00) | (n & 0x00FF);
return this & 0x00FF;
}
Number.prototype.hl = function(hi, lo) {
return (lo & 0x00FF) | ((hi & 0x00FF) << 8);
}
String.prototype.Mul = function(n, j) {var s = this, buf = ""; while(n > 0) { if(n&1) buf+=s; s+=(j?j:"")+s; n >>= 1; } return buf; }
/*
.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
00:STACK/Batch User Layer Loadings Execution Table|INT 0-bullet
10:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 1
20:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 2
30:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 3
40:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 4
50:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 5
60:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 6
70:STACK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 7
80:STOCK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 8
90:STOCK/-- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 9
A0:AL>>LO>> ++/SP>LO/.. ..|AH>>HI>> ++/SP>HI/.. ..|AX / SP /
B0:BL>>LO>> ++/BP>LO/.. ..|BH>>HI>> ++/BP>HI/.. ..|BX / BP /
C0:CL>>LO>> ++/SI>LO/IP>LO|CH>>HI>> ++/SI>HI/IP>HI|CX / SI / IP
D0:DL>>LO>> ++/DI>LO/JP>LO|DH>>HI>> ++/DI>HI/JP>HI|DX / DI / JP
E0:-- I7 I6 I5 I4 I3 I2 I1|-- P7 P6 P5 P4 P3 P2 P1|
F0:-- D7 D6 D5 D4 D3 D2 D1|-- -- -- -- -- -- -- --|
+0:CI -- -- -- -- -- TL.TH |Control Registers
---
PORT(ADDR) = ACC
DATA[ADDR] = ACC
DATA[ADDR ++] = ACC
DATA[-- ADDR] = ACC
ACC = PORT(ADDR)
ACC = DATA[ADDR]
ACC = DATA[ADDR ++]
ACC = DATA[-- ADDR]
WAIT
INT 79 ; 7-instructions of Function #9
; SP.0 = 1; FL=0Fh; FH=017
.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
00:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 0
10:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 1
20:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 2
30:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 3
40:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 4
50:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 5
60:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 6
70:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 7
80:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 8
90:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 9
A0:AL>>LO>>Стек истории --|AH>>HI>> ++ .. -- -- --|AX-Stack
B0:BL>>LO>>модификации- --|BH>>HI>> ++ .. -- -- --|BX-Stack
C0:CL>>LO>>всех РОН- -- --|CH>>HI>> ++ .. -- -- --|CX-Stack
D0:DL>>LO>> ++ .. -- -- --|DH>>HI>> ++ .. -- -- --|DX-Stack
E0:SP>LO/BP>LO/SI>LO/DI>LO|SP>HI/BP>HI/SI>HI/DI>HI|SP/BP/SI/DI-Stack
F0:IP>>LO>> ++/.. ../JP.LO|IP>>HI>> ++/.. ../JP.HI|IP/JP
+0:CI -- -- -- -- -- TL.TH |Control Registers
CI - Context Index Register
===========================
For immediate access to the context file of any executive applications task on
the system level process is available the services register CI, selects a task
in the system environment and sets the all prefers for current active process.
Для непосредственного доступа к контексту любой имеющейся прикладной задачи на
уровне системного процесса доступен регистр CI, служащего переключателем задач
в системной среде и управляющего привелегиями для текущего активного процесса.
Базовая реализация процессора поддерживает от трёх независимых контекстов, под
которыми может выполняться непосредственно код системного ядра, код диспетчера
системных ресурсов с аппаратным интерфейсом и другой код прикладной программы.
Контекст ядра всегда имеет индекс с базой 0, диспетчерам ресурсов определяются
контексты с индексами от 127 до 100 в сторону уменьшения номера, тогда как все
приложения индексируются контекстами от 1 до 99 в сторону возрастания номеров.
______________________________________________________________________________
00000000 0 :База(0) - Системный код с высоким уровнем привелегий.
0XXXXXXX 1-99 :База(1) - Прикладной код с низким уровнем привелегий.
011XXXXX 100-127:База(127)-Средний уровень диспетчера системных ресурсов.
1XXXXXXX 128-255:Зеркала контекста №0 под высоким системным уровнем привелегий
*/
Array.prototype.Dump = function(a, n) {
var s = [], t = "__", d = "INT 0|INT 1|INT 2|INT 3|INT 4|INT 5|INT 6|INT 7|INT 8|INT 9|AX-File(AL:AH)|BX-File(BL:BH)|CX-File(CL:CH)|DX-File(DL:DH)|SP/BP/SI/DI|IP/JP|Services Masking".split("|");
if(isFinite(a))
while(n --)
s.push(this[a ++ & 0xFFFF].Hex(2));
else {
n = this.length;
for(a = 0; a < 16; ++ a)
t += " ." + a.Hex(1);
for(a = 0; a < n; ++ a) {
s.push(this[a].Hex(2));
if((a & 15) == 15)
if(a >= 0xE0 && a <= 0xEF)
t += "\r\n" + (a & 0xF0).Hex(2) + ":" + s.slice(0, 2).join(" ") + "/" + s.slice(2, 4).join(" ") + "/" + s.slice(4, 6).join(" ") + "/" + s.slice(6, 8).join(" "),
t += "|" + s.slice(8, 10).join(" ") + "/" + s.slice(10, 12).join(" ") + "/" + s.slice(12, 14).join(" ") + "/" + s.slice(14, 16).join(" ") + ";" + d.shift(),
s = [];
else
t += "\r\n" + (a & 0xF0).Hex(2) + ":" + s.slice(0, 8).join(" ") + "|" + s.slice(8, 16).join(" ") + ";" + d.shift(),
s = [];
else
if(a == n - 1)
t += "\r\n+0:" + s.join(" ") + ";" + d.shift();
}
return t;
}
return s.join(" ");
}
Array.prototype.Text = function(a, n) {var s = "", c; while(n --) c = this[a ++ & 0xFFFF], s += "&#" + /*String.fromCharCode*/(c >= 32 && c <= 127 ? c : 0xB7) + ";"; return s; }
Array.prototype.Chr = function(a, n, m, xy) {
var i, buf = "";
var smb = [ 0xB7, 0x255D, 0x255A, 0x2569, 0x2554, 0x256A, 0x2560, 0x2510, 0xB7, 0x263A, 0xB7, 0x25B2, 0xB7, 0xB7, 0x25BA, 0x25BC, //0xB7, 0x2598, 0x259D, 0x2580, 0x2597, 0x259A, 0x2590, 0x259C, 0xB7, 0x263A, 0xB7, 0x25B2, 0xB7, 0xB7, 0x25BA, 0x25BC,
0x2557, 0x2563, 0x256B, 0x250C, 0x2566, 0x2514, 0x2518, 0x256C, 0xB7, 0xB7, 0xB7, 0x2551, 0x2550, 0x25C4, 0xB7, 0xB7, //0x2596, 0x258C, 0x259E, 0x259B, 0x2584, 0x2599, 0x259F, 0x2588, 0xB7, 0xB7, 0xB7, 0x2551, 0x2550, 0x25C4, 0xB7, 0xB7,
0x20, 0x21, 0x22, 0x23, 0xA4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B ,0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x25A0];
if(isFinite(m))
m *= n;
else
m = n;
xy = isFinite(xy) ? xy : -1;
for(i = 0; i < m; ++ i, ++ a, -- xy)
buf += (xy ? "&#" : "<u>&#") + (this[a] >= 0 && this[a] < 128 ? smb[this[a]] : smb[0]) + (xy ? ";" : ";</u>") + (i % n == n - 1 && m != n ? "<br />" : "");
return buf;
}
/****************************************************************************/
var lastModified = document.lastModified;
var
AudioAPI = 0,
AudioScript = 0,
AudioStream = [],
AudioAPIscript = 0,
amp = [],
osc = [];
var noteFreq = [ // freq = 2 ** (n / 12) * 440
16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.500, 25.957, 27.500, 29.135, 30.868,
32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55.000, 58.270, 61.735,
65.406, 69.296, 73.416, 77.782, 82.406, 87.307, 92.499, 97.999, 103.83, 110.00, 116.54, 123.47,
130.81, 138.59, 146.83, 155.56, 164.81, 174.81, 185.00, 196.00, 207.65, 220.00, 233.08, 246.84,
261.63, 277.18, 293.67, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88, // #1
523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77, // #2
1046.5, 1108.7, 1174.7, 1244.5, 1318.5, 1396.9, 1480.0, 1568.0, 1661.2, 1760.0, 1864.7, 1975.5, // #3
2093.0, 2217.5, 2349.3, 2489.0, 2637.0, 2793.8, 2960.0, 3136.0, 3322.4, 3520.0, 3729.3, 3951.1, // #4
4186.0, 4434.9, 4698.6, 4978.0, 5274.0, 5587.7, 5919.9, 6271.9, 6644.9, 7040.0, 7458.6, 7902.1, // #5
8372.0, 8869.8, 9397.3, 9956.1, 10548 , 11175 , 11840 , 12544 , 13290 , 14080 , 14917 , 15804 // #6
];
function AudioCallBack(e) {
try {
var i, addr = 0xA0;
var input = e.inputBuffer.getChannelData(0);
var output = e.outputBuffer.getChannelData(0);
var frq = typeof cpu.iox[addr] == "object" ? cpu.iox[addr].data() : cpu.iox[addr];
var evl = 0;
var dur = 0;
document.title = (frq = 440);
dur = AudioStream.length > 0 ? AudioStream[0] : 0;
try {
for(i = 0; i < input.length; ++ i) {
output[i] = dur > 0 ? 255 : 0;
if(dur > 0)
dur --;
if(dur < 0)
dur ++;
if(dur == 0 && AudioStream.length > 0) {
dur = AudioStream.shift();
}
}
if(dur != 0)
AudioStream[0] = dur;
} catch(e) {
while(i < input.length)
output[i ++] = (Math.random() % 255 - 128) / 128;
}
} catch (e) {
//window.status = e.message;
}
}
//
function AudioInit() {
try {
AudioAPI = new AudioContext();
} catch(err) {
AudioAPI = 0;
return;
}
//AudioAPIanalyser = AudioAPI.createAnalyser();
//AudioAPIanalyser.connect(AudioAPI.destination);
AudioAPIfilter = AudioAPI.createBiquadFilter();
AudioAPIfilter.type = 1; // High-pass filter (Тип фильтра)
AudioAPIfilter.frequency.value = 96000; // Cutoff to 1kHZ (Базовая частота)
AudioAPIfilter.frequency.Q = 1.1; // Quality factor (Добротность)
AudioAPIfilter.connect(AudioAPI.destination);//(AudioAPIanalyser);
(amp[0] = AudioAPI.createGain()).connect(AudioAPIfilter); /*amp[0].connect(anl)*/; amp[0].gain.value = 1.0;
(osc[0] = AudioAPI.createOscillator()).connect(amp[0]); osc[0].frequency.value = 440;
try {
osc[0].noteOn(0);
} catch(err) {
osc[0].start(0);
// osc[0].stop(3);
// osc[0].start(7);
}
/* if(!AudioAPI.createScriptProcessor)
AudioAPIscript = AudioAPI.createJavaScriptNode(1 << 10, 1, 1);
else
AudioAPIscript = AudioAPI.createScriptProcessor(1 << 10, 1, 1);
AudioAPIscript.onaudioprocess = AudioCallBack;
// connect the ScriptProcessorNode with the input audio
amp[0].connect(AudioAPIscript);
// if the ScriptProcessorNode is not connected to an output the "onaudioprocess" event is not triggered in chrome
AudioAPIscript.connect(amp[0]);*/
};
var
VK = {
BACK_SPACE :0x08,
TAB :0x09,
RETURN :0x0D,
BREAK :0x13,
CAPITAL :0x14,
ESC :0x1B,
PREV :0x21,
NEXT :0x22,
END :0x23,
HOME :0x24,
LEFT :0x25,
UP :0x26,
RIGHT :0x27,
DOWN :0X28,
PRINT :0x2C,
INSERT :0x2D,
DELETE :0x2E,
CONTEXT :0x5D,
F1 :0x70,
F2 :0x71,
F3 :0x72,
F4 :0x73,
F5 :0x74,
F6 :0x75,
F7 :0x76, // Assembly
F8 :0x77,
F9 :0x78, // Break point on/off
F10 :0x79,
F11 :0x7A,
F12 :0x7B,
BROWSE_BACK :0xA6,
BROWSE_FORWARD :0xA7,
BROWSE_REFRESH :0xA8,
BROWSE_STOP :0xA9,
BROWSE_SEARCH :0xAA,
BROWSE_HOME :0xAC,
PLAYER_FORWARD :0xB0, // Emulation IP ++
PLAYER_REWIND :0xB1, // Emulation IP --
PLAYER_STOP :0xB2, // Emulation stop/step
PLAYER_PLAY :0xB3, // Emulation stop/start
BROWSE_MAIL :0xB4,
};
var X80 =
function(descriptions) {
var _CPU_ID_ = "x80-CPU";
var preset = { // Initial tables
instructions :[], // Instructions set: code -> group, mnemonic, operands, expression
mnemonics :[], // Mnemonical codes: name -> operands -> code
alias :[], // Mnemonical alias: name -> byte codes
files :[],
ascii :[], // ASCII-Graphics memory
};
var trace = {
callback :null,
timer :null,
active :true,
ready :true,
reply :false,
step :false,
is_port :false,
is_context :false,
is_debug :false,
is_freeze :true,
fixing :-1,
expressions :["", "", "", "", "", "", "", "", "", ""],
expression :0,
clock :1024,
scale :8192,
pointer :0,
address :0xF800,
lines :67,
flash :25,
stamps :[0, 0],
halt :[],
text :[],
labels :[], // Assembly idents: address -> name || name -> address
};
var watch = {
active :"",
sAdjust :"IPC",
iAdjust :0,
nAdjust :1,
dirty :7,
instructions :null,
disassembly :null,
registers :null,
address :null,
mnemonic :null,
remark :null,
context :null,
c2d :null,
fontCnv :null,
fonts :null,
fontBit :null,
};
var $CTX = null,
$BRK = false,
$IP = 0|0,
$IE = 0|0, // iteration extension mode neo:[1:Skip; 2:Loop; 3:Wait]
$IF = 0|0, // iteration flag
$IR = 0|0, // iterative register
$IT = 0|0, // iteration tick
$A = 0|0, // immediate short address
$B = 0|0, // immediate unsigned data
$C = 0|0, // immediate signed data
$EV = 0|0; // event value
var DO_OVERHEAD = 0,
DO_ACCLAIM = 1,
DO_BUFFER = 2,
DO_CONTEXT = 3,
DO_DEVICE = 4,
DO_ERROR = 5,
DO_FORCE = 6,
DO_GARRET = 7;
var i, j;
var irq = -1;
var ram;
var ctx = new Array(128);
var cr = [255, 0, 0, 0, 0, 0, 0, 0];
var user = {};
var display = function() {};
var hTimer = null;
this.$EV = $EV;
this.DO_OVERHEAD = DO_OVERHEAD;
this.DO_ACCLAIM = DO_ACCLAIM;
this.DO_BUFFER = DO_BUFFER;
this.DO_CONTEXT = DO_CONTEXT;
this.DO_DEVICE = DO_DEVICE;
this.DO_ERROR = DO_ERROR;
this.DO_FORCE = DO_FORCE;
this.DO_GARRET = DO_GARRET;
//
Number.prototype.Hex = function(n) {
return (n < 0 ? "0x" : "") + ((((this >> 16) & 0x0000FFFF) | 0x00010000).toString(16) + ((this & 0x0000FFFF) | 0x00010000).toString(16).substr(1)).substr(-Math.abs(n)).toUpperCase();
}
Number.prototype.hi = function(n) {
if(isFinite(n))
return (this & 0x00FF) | ((n & 0x00FF) << 8);
return (this >> 8) & 0x00FF;
}
Number.prototype.lo = function(n) {
if(isFinite(n))
return (this & 0xFF00) | (n & 0x00FF);
return this & 0x00FF;
}
Number.prototype.hl = function(hi, lo) {
return (lo & 0x00FF) | ((hi & 0x00FF) << 8);
}
String.prototype.Mul = function(n, j) {var s = this, buf = ""; while(n > 0) { if(n&1) buf+=s; s+=(j?j:"")+s; n >>= 1; } return buf; }
Array.prototype.Dump = function(a, n) {
var s = [], m, t = "__", d = "INT 0|INT 1|INT 2|INT 3|INT 4|INT 5|INT 6|INT 7|INT 8|INT 9|AX-File(AL:AH)|BX-File(BL:BH)|CX-File(CL:CH)|DX-File(DL:DH)|SP/BP/SI/DI|IP/JP|Services Masking".split("|");
if(isFinite(a))
while(n --)
s.push(this[a ++ & 0xFFFF].Hex(2));
else {
n = this.length;
m = microdis();
for(a = 0; a < 16; ++ a)
t += " ." + a.Hex(1);
for(a = 0; a < n; ++ a) {
s.push(this[a].Hex(2));
if((a & 15) == 15)
if(a >= 0xE0 && a <= 0xEF)
t += "\r\n" + (a & 0xF0).Hex(2) + ":" + s.slice(0, 2).join(" ") + "/" + s.slice(2, 4).join(" ") + "/" + s.slice(4, 6).join(" ") + "/" + s.slice(6, 8).join(" "),
t += "|" + s.slice(8, 10).join(" ") + "/" + s.slice(10, 12).join(" ") + "/" + s.slice(12, 14).join(" ") + "/" + s.slice(14, 16).join(" ") + ";" + d.shift(),
s = [];
else
t += "\r\n" + (a & 0xF0).Hex(2) + ":" + s.slice(0, 8).join(" ") + "|" + s.slice(8, 16).join(" ") + ";" + d.shift() + (a > 16 && a <= 0x7F ? "|" + m.shift() : ""),
s = [];
}
for(a = 0; a < 8; ++ a)
s.push(cr[a].Hex(2));
s.push("" + trace.expression);
s = s.concat(trace.expressions[trace.expression].replace(/(.{64})/g, "$1\r\n").split(/\r?\n/));
t += "\r\n+0:" + s.join(" ") + ";" + d.shift();
return t;
}
return s.join(" ");
}
function log() {
if(trace.active && arguments) {
var args = Array.prototype.slice.call(arguments);
var level = args[0].charAt(0);
var group = args[0].replace(/^[!#@]?/, "\1" + _CPU_ID_).split("/");
for(var i = 1; i < group.length; ++ i)
console.group(group[i - 1]);
args.shift();
args.unshift(group.pop())
switch(level) {
case "!":
console.warn.apply(this, args)
break;
case "#":
console.info.apply(this, args)
break;
case "@":
console.error.apply(this, args)
break;
default:
if(trace.active)
console.log.apply(this, args)
break;
}
while(i --)
console.groupEnd();
}
}
//
this.IRQ = function(type) {
if(cr[0] > 127) {
ctx[0][0xA8] = 0x85 | (DO_FORCE << 4);
CR(0, CR(0) & 127);
}
}
function DEBUG_TIMER(on) {
if(on)
log("!/TIMER ON"),
trace.stamps[0] = (new Date()).getTime();
else
log("!/TIMER OFF"),
trace.stamps[0] = -Math.abs(trace.stamps[0]);
return 0;
}
function CTW(index, address, data) {
index &= 0xF;
address &= 0xFF;
if(isFinite(data))
ctx[index][address] = data.lo(),
ctx[index][address ^ 8] = data.hi();
return Number().hl(ctx[index][address ^ 8], ctx[index][address ^ 0]);
}
function CR(index, data) {
if(isFinite(index)) {
index &= 7;
if(isFinite(data)) {
log("!/CR:%s %s", index.Hex(2), data.Hex(2));
data &= 0xFF;
if(!!((data ^ cr[0]) & 128) && !index) {
$CTX = ctx[data < 128 ? 0 : data & 127];
$IE = 0, $IR = 0, $BRK = true;
if(data & 128)
$CTX[0xA8] = ($CTX[0xA8] & 0x02) | (ctx[0][0xA8] & 0x02);
}
if(!index)
trace.expressions = ["", "", "", "", "", "", "", "", "", ""];
return cr[index] = data & 0xFF;
}
return cr[index];
}
return cr[0] < 128 ? 0 : cr[0] & 0x7F;
}
function CTX(index, data) {
//log("/CTX(%d, %d)", index, data);
if(isFinite(data))
ctx[cr[0] & 127][index & 0xFF] = data & 0xFF;
return ctx[cr[0] & 127][index & 0xFF];
}
function FIX(width, index) { // Prepare micro
trace.expressions[index % 10] = "";
index = ((index % 10) << 4) + 1;
width = (width << 1) + 1;
trace.fixing = index + width;
while(++ index & 15)
$CTX[index] = (index & 15) <= width ? 0xFF : 0x00;
}
function FLY(index) {
var tmp, action;
if(trace.expressions[index] == "") {
tmp = ((index) << 4) + 15;
while(!$CTX[tmp] && !$CTX[tmp - 1] && (tmp & 14))
tmp -= 2
while(tmp & 14) {
$B = $CTX[tmp --];
action = $CTX[tmp --] + (($B << 3) & 0x700);
$C = ($B & 31) - ($B & 16) * 2;
$A = $B - ($B & 128) * 2;
$B &= 255;
trace.expressions[index] += preset.instructions[action].expression
.replace(/(\$B)/g, "" + $B)
.replace(/(\$C)/g, "" + $C)
.replace(/(\$A)/g, "" + $A)
.replace(/true/g, "false") + ";\r\n";
}
log("!/EVAL %s", trace.expressions[index]);
}
trace.is_freeze = true;
eval(trace.expressions[index]);
log("!/IT=%s IR=%s REG=%s", $IT.Hex(2), $IR.Hex(2), REG($IR).Hex(2));
if(!(($IT != 8) && (!$IR || (REG($IR) != 1))))
FL(FL() | 2);
//$EV = this.DO_CONTEXT;
//log("!/%d %d %d", it, ir, REG(ir));
}
function GET(index) { // Get data from kernel accumulator history
return ctx[0][0xA8 + (ctx[0][0xA8] & 0x30) - ((ctx[0][0xA8] >> 3) & 0x08) + (index & 7)];
}
function PUT(data) { // Put data to kernel accumulator history
var index = 0xA8 + (ctx[0][0xA8] & 0x30) - ((ctx[0][0xA8] >> 3) & 0x08);
ctx[0].splice(index + 7, 1);
ctx[0].splice(index + 1, 0, data &= 0xFF);
return data;
}
function ACC(data) { // Holded register
var index = ($CTX[0xA8] >> 4) & 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
if(isFinite(data))
data &= 0xFF,
$CTX[index] = data;
else
data = $CTX[index];
return data;
}
/*this.__defineGetter__("ACC", function() {
var index = (this.$CTX[0xA8] >> 4) & 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
data = this.$CTX[index];
return data;
});
this.__defineSetter__("ACC", function(data) {
var index = (this.$CTX[0xA8] >> 4) & 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
data &= 0xFF,
this.$CTX[index] = data;
return data;
});*/
function REG(index, data) {// Register[AH,BH,CH,DH,AL,BL,CL,DL]
index &= 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
if(isFinite(data))
data &= 0xFF,
$CTX[index] = data;
else
data = $CTX[index];
return data;
}
function DST(data) { // Holded pointer
var index = ($CTX[0xA8] >> 4) & 7;
if(index & 4)
index = 0xA0 + 16 * (index & 3);
else
index = 0xE0 + index;
if(isFinite(data))
data &= 0xFFFF,
$CTX[index] = data.lo(),
$CTX[index + 8] = data.hi();
else
data = Number().hl($CTX[index + 8], $CTX[index]);
return data;
}
function PTR(index, data) {// Pointer[SP,BP,SI,DI,AX,BX,CX,DX]
index &= 7;
if(index & 4)
index = 0xA0 + 16 * (index & 3);
else
index = 0xE0 + index;
if(isFinite(data))
data &= 0xFFFF,
$CTX[index] = data.lo(),
$CTX[index + 8] = data.hi();
else
data = Number().hl($CTX[index + 8], $CTX[index]);
return data;
}
function DROP(index) {
if(!isFinite(index))
index = $CTX[0xA8];
index &= 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
$CTX.splice(index + 7, 0, $CTX.splice(index, 1)[0]);
return $CTX[index + 7];
}
function DUP(index) {
if(!isFinite(index))
index = $CTX[0xA8];
index &= 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
$CTX.splice(index + 7, 1), $CTX.splice(index, 0, $CTX[index]);
return $CTX[index + 7];
}
function JP(index, address) {
index &= 1;
if(isFinite(address))
$CTX[0xFE + index] = address.hi(),
$CTX[0xF6 + index] = address.lo();
else
address = Number().hl($CTX[0xFE + index], $CTX[0xF6 + index]);
return address & 0xFFFF;
}
function IP(address) {
if(isFinite(address))
$CTX.splice(0xF3, 1), $CTX.splice(0xF0, 0, address.lo()),
$CTX.splice(0xFB, 1), $CTX.splice(0xF8, 0, address.hi()),
address = Number().hl($CTX[0xF9], $CTX[0xF1]);
else
address = Number().hl($CTX[0xF8], $CTX[0xF0]);
return address & 0xFFFF;
}
function IPnext(address) {
var further;
if(isFinite(address))
further = address;
else
address = Number().hl($CTX[0xF8], $CTX[0xF0]),
further = address + 1;
$CTX[0xF0] = further.lo(), $CTX[0xF8] = further.hi();
return address & 0xFFFF;
}
function SP(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xE0] = address.lo(), $CTX[0xE8] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xE1, 1), $CTX.splice(0xE0, 0, address.lo()),
$CTX.splice(0xE9, 1), $CTX.splice(0xE8, 0, address.hi()),
address = Number().hl($CTX[0xE8], $CTX[0xE0]);
else
address = Number().hl($CTX[0xE8], $CTX[0xE0]);
return address & 0xFFFF;
}
function SPnext() {
var address = Number().hl($CTX[0xE8], $CTX[0xE0]),
further = address + 1;
$CTX[0xE0] = further.lo(), $CTX[0xE8] = further.hi();
return address & 0xFFFF;
}
function SPback() {
var address = Number().hl($CTX[0xE8], $CTX[0xE0]),
further = address - 1;
$CTX[0xE0] = further.lo(), $CTX[0xE8] = further.hi();
return address & 0xFFFF;
}
function _SP_(data) {
var address = Number().hl($CTX[0xE8], $CTX[0xE0]);
if(isFinite(data))
DW(address, data);
else
data = DW(address);
return data;
}
function HEAP(data) {
var address = Number().hl($CTX[0xE8], $CTX[0xE0]);
if(isFinite(data))
DW(address -= 2, data);
else
data = DW(address),
address += 2;
$CTX[0xE0] = address.lo(), $CTX[0xE8] = address.hi();
return data;
}
function BP(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xE2] = address.lo(), $CTX[0xEA] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xE3, 1), $CTX.splice(0xE2, 0, address.lo()),
$CTX.splice(0xEB, 1), $CTX.splice(0xEA, 0, address.hi());
else
address = Number().hl($CTX[0xEA], $CTX[0xE2]);
return address & 0xFFFF;
}
function SI(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xE4] = address.lo(), $CTX[0xEC] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xE5, 1), $CTX.splice(0xE4, 0, address.lo()),
$CTX.splice(0xED, 1), $CTX.splice(0xEC, 0, address.hi());
else
address = Number().hl($CTX[0xEC], $CTX[0xE4]);
return address & 0xFFFF;
}
function DI(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xE6] = address.lo(), $CTX[0xEE] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xE7, 1), $CTX.splice(0xE6, 0, address.lo()),
$CTX.splice(0xEF, 1), $CTX.splice(0xEE, 0, address.hi());
else
address = Number().hl($CTX[0xEE], $CTX[0xE6]);
return address & 0xFFFF;
}
function AX(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xA0] = address.lo(), $CTX[0xA8] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xAF, 1), $CTX.splice(0xA0, 0, address.lo()), $CTX[0xA8] = address.hi();
else
address = Number().hl($CTX[0xA8], $CTX[0xA0]);
return address & 0xFFFF;
}
function BX(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xB0] = address.lo(), $CTX[0xB8] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xBF, 1), $CTX.splice(0xB0, 0, address.lo()), $CTX[0xB8] = address.hi();
else
address = Number().hl($CTX[0xB8], $CTX[0xB0]);
return address & 0xFFFF;
}
function _BX_(data) {
if(isFinite(data))
DB(Number().hl($CTX[0xB8], $CTX[0xB0]), data);
else
data = DB(Number().hl($CTX[0xB8], $CTX[0xB0]));
return data;
}
function CX(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xC0] = address.lo(), $CTX[0xC8] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xCF, 1), $CTX.splice(0xC0, 0, address.lo()), $CTX[0xC8] = address.hi();
else
address = Number().hl($CTX[0xC8], $CTX[0xC0]);
return address & 0xFFFF;
}
function DX(address) {
if(isFinite(address) && trace.is_freeze)
$CTX[0xD0] = address.lo(), $CTX[0xD8] = address.hi();
else
if(isFinite(address))
$CTX.splice(0xDF, 1), $CTX.splice(0xD0, 0, address.lo()), $CTX[0xD8] = address.hi();
else
address = Number().hl($CTX[0xD8], $CTX[0xD0]);
return address & 0xFFFF;
}
function _AL_(data) {
if(isFinite(data))
$CTX.splice(0xA7, 1), $CTX.splice(0xA0, 0, data.lo());
else
data = $CTX[0xA0];
data -= (data & 0x80) << 1;
return data & 0xFFFF;
}
function AL(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xA0] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xA7, 1), $CTX.splice(0xA0, 0, data.lo());
else
data = $CTX[0xA0];
return data & 0x00FF;
}
function AH(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xA8] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xAF, 1), $CTX.splice(0xA8, 0, data.lo());
else
data = $CTX[0xA8];
return data & 0x00FF;
}
function BL(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xB0] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xB7, 1), $CTX.splice(0xB0, 0, data.lo());
else
data = $CTX[0xB0];
return data & 0x00FF;
}
function BH(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xB8] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xBF, 1), $CTX.splice(0xB8, 0, data.lo());
else
data = $CTX[0xB8];
return data & 0x00FF;
}
function CL(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xC0] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xC7, 1), $CTX.splice(0xC0, 0, data.lo());
else
data = $CTX[0xC0];
return data & 0x00FF;
}
function CH(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xC8] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xCF, 1), $CTX.splice(0xC8, 0, data.lo());
else
data = $CTX[0xC8];
return data & 0x00FF;
}
function DL(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xD0] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xD7, 1), $CTX.splice(0xD0, 0, data.lo());
else
data = $CTX[0xD0];
return data & 0x00FF;
}
function DH(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xD8] = data & 0xFF;
else
if(isFinite(data))
$CTX.splice(0xDF, 1), $CTX.splice(0xD8, 0, data.lo());
else
data = $CTX[0xD8];
return data & 0x00FF;
}
function FL(data) {
if(isFinite(data) && trace.is_freeze)
log("!/GLAG %s %s", $IP.Hex(4), data.Hex(2)),
$CTX[0xA8] = ($CTX[0xA8] & 0xF0) | (data & 0x0F);
else
if(isFinite(data))
$CTX.splice(0xAF, 1), $CTX.splice(0xA8, 0, ($CTX[0xA8] & 0xF0) | (data & 0x0F));
else
data = $CTX[0xA8];
return data & 0x000F;
}
function FH(data) {
if(isFinite(data) && trace.is_freeze)
$CTX[0xA8] = ($CTX[0xA8] & 0x0F) | ((data << 4) & 0xFF);
else
if(isFinite(data))
$CTX.splice(0xAF, 1), $CTX.splice(0xA8, 0, ($CTX[0xA8] & 0x0F) | (data << 4).lo());
else
data = $CTX[0xA8] >> 4;
return data & 0x000F;
}
function ADC(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() + bits.lo() + ((FL() >> 1) & 1);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:ADC");
return data + (flags << 8);
}
function SBB(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() - bits.lo() - ((FL() >> 1) & 1);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:SBB");
return data + (flags << 8);
}
function ADD(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() + bits.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:ADD");
return data + (flags << 8);
}
function SUB(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() - bits.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:SUB");
return data + (flags << 8);
}
function AND(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() & bits.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= FL() & 2;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:AND");
return data + (flags << 8);
}
function OR(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() | bits.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= FL() & 2;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:OR");
return data + (flags << 8);
}
function XOR(data, bits) {
var flags; // SF PF CF ZF
data = data.lo() ^ bits.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= FL() & 2;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:XOR");
return data + (flags << 8);
}
function CMP(bits, data) {
var flags; // SF PF CF ZF
data = bits.lo() - data.lo();
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:CMP");
return bits.lo() + (flags << 8);
}
function NOT(data) { // Bitwise not
var flags; // SF PF CF ZF
data = data.lo() ^ 0xFF;
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:NOT");
return data + (flags << 8);
}
function RAR(data) { // Roll Arithmetic Right
var flags; // SF PF CF ZF
data = (data.lo() >> 1) | ((data & 1) << 8) | (data & 0x80);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:RAR");
return data + (flags << 8);
}
function RCL(data) { // Roll Cyclic Left
var flags; // SF PF CF ZF
data = (data.lo() << 1) | ((data >> 7) & 1);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:RCL");
return data + (flags << 8);
}
function RCR(data) { // Roll Cyclic Right
var flags; // SF PF CF ZF
data = (data.lo() >> 1) | ((data & 1) << 7);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 6) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:RCR");
return data + (flags << 8);
}
function ROL(data) { // Roll Overflow Left
var flags; // SF PF CF ZF
data = (data.lo() << 1) | ((FL >> 1) & 1);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:ROL");
return data + (flags << 8);
}
function ROR(data) { // Roll Overflow Right
var flags; // SF PF CF ZF
data = (data.lo() >> 1) | ((data & 1) << 8) | ((FL & 2) << 7);
flags = data ^ (data >> 4);
flags ^= flags << 2;
flags ^= flags >> 1;
flags &= 4;
flags |= (data >> 7) & 2;
data &= 0xFF;
flags |= (((data ^ 0xFF) + 1) >> 8) & 1;
flags |= (data >> 4) & 8;
//log("ALU:ROR");
return data + (flags << 8);
}
var FileIndex = 0;
var FileSeek = 0;
var Value = 0;
var Resume = 0;
var FileMode = 0;
/* cpu.preset.files.push({
name :file.id.substr(5),
text :file.innerText,
code :{
name :"",
begin :65535,
end :0,
bin :[]
}
*/ function PORT(index, data) {
if(cr[0] & 0x80) {
if(isFinite(data)) {
this.ready = false;
if(ctx[0][0xA8] & 0x02) {
FL((FL() & 0xD) | (ctx[0][0xA8] & 0x2)),
ctx[0][0xA8] &= 0xFD;
return data;
}
PUT(data & 0xFF);
PUT(index);
ctx[0][0xA8] |= 0x02;
// IPnext($IP);
$EV = DO_DEVICE;
return index;
} else {
//console.log("!/INPUT %s %s ", index.Hex(2), $EV);
trace.ready = false;
if(ctx[0][0xA8] & 0x02) {
trace.ready = true;
FL((FL() & 0xD) | (ctx[0][0xA8] & 0x2)),
ctx[0][0xA8] &= 0xFD;
return GET(1);
}
PUT(index),
ctx[0][0xA8] &= 0xFD;
// IPnext($IP);
$EV = DO_DEVICE;
return index;
}
}
if(isFinite(data))
log("!/OUT %s,%s", index.Hex(2), data.Hex(2));
else
log("!/IN %s", index.Hex(2));
switch(index) {
case 0xF5:
if(isFinite(data)) {
switch(data) {
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
Value = ((Value << 4) & 0xFFF0) | (data & 15);
log("!PORT/FILE/Code %s", data.Hex(2));
break;
case 0xD1:
FileIndex = Value;
log("!PORT/FILE/File %s", Value.Hex(2));
break;
case 0xD5:
FileSeek = Value;
log("!PORT/FILE/Seek %s", Value.Hex(2));
break;
case 0xD3:
FileMode = Value;
log("!PORT/FILE/Mode %s", Value.Hex(2));
break;
}
Resume = -1;
trace.ready = true;
} else {
trace.ready = true;
switch(FileMode) {
case 0:
Resume = Resume >= 0 ? Resume : preset.files.length;
data = Resume & 255;
Resume >>= 8;
log("!PORT/FILE/Get File Number");
break;
case 1:
Resume = Resume >= 0 ? Resume : 0;
data = preset.files[FileIndex].code.name.charCodeAt(Resume);
Resume ++;
log("!PORT/FILE/Get File Name");
if(Resume >= preset.files[FileIndex].code.name.length)
trace.ready = false;
break;
case 2:
Resume = Resume >= 0 ? Resume : preset.files[FileIndex].begin;
data = Resume & 255;
Resume >>= 8;
log("!PORT/FILE/Get File Start");
break;
case 3:
Resume = Resume >= 0 ? Resume : preset.files[FileIndex].end;
data = Resume & 255;
Resume >>= 8;
log("!PORT/FILE/Get File End");
break;
case 4:
Resume = Resume >= 0 ? Resume : preset.files[FileIndex].code.begin;
data = preset.files[FileIndex].code.bin[Resume];
log("!PORT/FILE/Get File Data");
if(Resume < preset.files[FileIndex].code.end)
++ Resume;
else
trace.ready = false;
break;
}
}
break;
case 0xDB:
if(isFinite(data))
DEBUG_TIMER(!!data);
else
data = Math.floor((core.trace.stamps[1] - core.trace.stamps[0]) / 1000) & 0xFF;
FL(FL() | 0x2);
break;
case 0xFD:
if(isFinite(data)) {
} else {
if(document.getElementById("KeyBoard").value == "")
FL(FL() & 0x0D),
trace.ready = false,
data = 255;
else {
data = document.getElementById("KeyBoard").value.charCodeAt(0), document.getElementById("KeyBoard").value = document.getElementById("KeyBoard").value.substr(1);
FL(FL() | 0x02),
trace.ready = true;
if(data == 0x60) {
data = document.getElementById("KeyBoard").value.charCodeAt(0), document.getElementById("KeyBoard").value = document.getElementById("KeyBoard").value.substr(1);
if(data > 0x40 && data <= 0x5F)
data &= 0x1F;
else
data = 0x7F;
}
}
}
break;
default:
data = 0;
}
return data;
}
function DB(addr, data) {
if(isFinite(data)) {
addr &= 0xFFFF,
data &= 0xFF;
if(trace.is_context && trace.is_port) {
log("#/CONTROL:%s <= %s", addr.Hex(2), data.Hex(2));
if(cr[0] & 15) {
cr[1] |= 1 << 0;
log("!/IRQ %d", type & 7);
IPnext($IP);
cr[0] = ((cr[0] << 4) & 0xF0);
HEAP(IP());
HEAP(AX());
FH(type | 8);
FL(7);
IPnext(JP(0));
}
cr[addr & 7] = data;
trace.is_context = false;
trace.is_port = false;
} else
if(trace.is_context) {
log("#/CONTEXT:%s <= %s", addr.Hex(2), data.Hex(2));
trace.is_context = false;
trace.is_port = false;
} else
if(trace.is_port) {
log("#/PORT:%s <= %s", addr.Hex(2), data.Hex(2));
trace.is_port = false;
data = PORT(addr.lo(), data);
} else {
trace.ready = true;
ram[addr] = data;
}
} else {
if(isFinite(addr))
addr &= 0xFFFF;
else
if(trace.is_context || trace.is_port) {
log("@/:TEST IP = %s ERROR", IP().Hex(4));
trace.is_debug = true;
trace.is_context = false;
trace.is_port = false;
data = Math.random() & 0xFF;
return data;
} else
addr = IPnext();
if(trace.is_context && trace.is_port) {
data = cr[addr & 7];
log("#/CONTROL:%s <= %s", addr.Hex(2), data.Hex(2));
trace.is_context = false;
trace.is_port = false;
if(cr[0] & 15) {
log("!/IRQ %d", type & 7);
IPnext($IP);
cr[0] = ((cr[0] << 4) & 0xF0);
HEAP(IP());
HEAP(AX());
FH(type | 8);
FL(7);
IPnext(JP(0));
}
} else
if(trace.is_context) {
data = 0x55;
log("#/CONTEXT:%s <= %s", addr.Hex(2), data.Hex(2));
trace.is_context = false;
trace.is_port = false;
data = 0x55;
} else
if(trace.is_port) {
data = PORT(addr.lo());
log("#/PORT:%s => %s", addr.Hex(2), data.Hex(2));
trace.is_port = false;
} else {
trace.ready = true;
data = ram[addr].lo();
}
}
return data;
}
function DW(addr, data) {
if(isFinite(data)) {
addr &= 0xFFFF,
data &= 0xFFFF;
ram[addr ++] = data.lo();
data &= 0xFFFF;
ram[addr] = data.hi();
} else {
data = ram[addr ++ & 0xFFFF];
data = Number().hl(ram[addr & 0xFFFF], data);
}
return data;
}
this.$CTX = $CTX;
this.CTW = CTW;
this.CTX = CTX;
this.CR = CR;
this.ACC = ACC;
this.DST = DST;
this.PTR = PTR;
this.REG = REG;
this.DROP = DROP;
this.DUP = DUP;
this.JP = JP;
this.IP = IP;
this.IPnext = IPnext;
this.SP = SP;
this.SPnext = SPnext;
this.SPback = SPback;
this._SP_ = _SP_;
this.HEAP = HEAP;
this.BP = BP;
this.SI = SI;
this.DI = DI;
this.AX = AX;
this.BX = BX;
this._BX_ = _BX_;
this.CX = CX;
this.DX = DX;
this._AL_ = _AL_;
this.AL = AL;
this.BL = BL;
this.CL = CL;
this.DL = DL;
this.AH = AH;
this.BH = BH;
this.CH = CH;
this.DH = DH;
this.FL = FL;
this.FH = FH;
this.ADC = ADC;
this.SBB = SBB;
this.ADD = ADD;
this.SUB = SUB;
this.AND = AND;
this.OR = OR;
this.XOR = XOR;
this.CMP = CMP;
this.NOT = NOT;
this.RAR = RAR;
this.RCL = RCL;
this.RCR = RCR;
this.ROL = ROL;
this.ROR = ROR;
this.PORT = PORT;
this.DB = DB;
this.DW = DW;
function flags(d) {
var fx = AH();
if(!isFinite(d)) {
var d = fx;
s = AL().Hex(2) + " " + AH().Hex(2) + "(AX)" + "----------- USING_BH/BP USING_CH/SI USING_DH/DI USE_AL/[SP] USING_BL/BX USING_CL/CX USING_DL/DX ??????????? INDEX_OF_x1 INDEX_OF_x2 INDEX_OF_x3 INDEX_OF_x4 INDEX_OF_x5 INDEX_OF_x6 INDEX_OF_x7".split(" ")[(d >> 4) & 15].replace(/_/g, " ");
switch(fx & 0xF) {
case 0x5: s += "|SKIP:Missed"; break;
case 0x7: s += "|SKIP:MISSED"; break;
case 0x9: s += "|LOOP:Cycled"; break;
case 0xB: s += "|LOOP:CYCLED"; break;
case 0xD: s += "|WAIT:Bused "; break;
case 0xF: s += "|WAIT:Ready "; break;
default:
s += "|sf pf cf zf".replace(/.f/g, function(str) {
str = d & 0x08 ? str.toUpperCase() : str.toLowerCase();
d <<= 1;
return str;
});
}
d = (fx >> 4) & 15;
d = d < 8 ? REG(d) : d + 248;
s += "|" + ctx[0][0xA1].Hex(2) + ":" + ctx[0][0xA2].Hex(2) + (ctx[0][0xA8] & 2 ? "Ready/Output" : "Bused/Input");
//s += ("|EXx" + (d & 256 ? "#" + d.Hex(1) : d.Hex(2)) + ":" + (isFinite(this.r.ex[d]) ? this.r.ex[d].Hex(2) : "--"));
/*s += (" JPx" + this.r.jp.Hex(4));
s += (" SXx" + this.r.asx[(this.r.ax & 0x8000 ? 248 + (this.r.ax >> 12) : this.reg(this.r.ax >> 12)) % 264].Hex(4));
s += (" TXx" + this.r.atx[(this.r.ax & 0x8000 ? 248 + (this.r.ax >> 12) : this.reg(this.r.ax >> 12)) % 264].Hex(4));
s += (" SRx" + this.r.sr.Hex(4));*/
return s;
}
fx = ((d << 3) & 0x0400) |
(d & 255 ? 0 : 0x100) |
((d << 1) & 0x0200);
d ^= d >> 4;
d ^= d << 2;
d ^= d << 1;
}
this.reset = function(address) {
log("!/CORE:RESET");
CR(0, 0);
IPnext(address);
$CTX[0xA8] = 0xF7;
trace.pointer = address;
trace.active = true;
trace.freeze = true;
clearTimeout(hTimer);
step.bind(this).call();
}
function step() {
"use asm";
var ic = 0|0; // instruction prefix/code
var code = 0|0; // instruction selected code
var action = 0|0; // instruction actions
var scale = 0|0;
var i = 0|0;
var tmp = 0|0;
var ctrl = 0|0;
var $FH = 0|0;
var tick = 0|0;
hTimer = setTimeout(this.step.bind(this), 1000 / trace.clock);
scale = !trace.active || trace.step ? trace.step ? 1 : trace.scale : 0;
if((trace.step && !trace.active && !trace.halt[IP()]))
trace.active = true,
disassm();
if((!trace.step && !trace.active && trace.halt[IP()]))
disassm();
if(tmp = CR())
tick = Number().hl(cr[7], cr[6]) & 0xFFFF;
else
tick = -1;
$EV = -DO_CONTEXT;
$FH = FH();
try {
while(!!(($IP = IP()) || (ready = true)) && (trace.step || (!trace.halt[$IP] && !trace.active)) && (scale -- > 0) && ((tick != 0) && tick --) && ($EV < 0)) {
trace.is_port = false; // Not port access
trace.is_context = false; // Not context access
$BRK = false; // No context break
$A = $B = $C = 0; // Reset instruction Byte/Value/Word
$IR = $IT = FH(); // Iterable Register/Times load
$IR &= $IR & 8 ? 0 : 15; // Select between
$IT &= $IT & 8 ? 15 : 0; // Register or Times
$IE = FL();
$IF = false;
if(!!($IE >> 2) && !!($IE & 1)) // Instruction Extension: 0-None, 1-Skip, 2-Loop, 3-Wait
$IE >>= 2;
else
$IE = 0;
ic = DB(); // Read instruction code and prefix
if(((ic >> 4) == (ic & 0x07)) && (ic || cr[0] < 128))
ic = (ic ? (ic & 0x07) << 8 : 0x0800) | DB();
if((ic & 0xC0) == 0x80) // Read immediate data
$B = DB(),
$C = $B - (($B & 0x0080) << 1),
$A = $C + ((ic & 0x0700) - ((ic & 0x0400) << 1));
// Supevisor mode control
ctrl = !(cr[0] & 0x80) && ($IE == 3) && ((ic.lo() == 0) || ((ic.hi() * 0x11) == ic.lo()));
$FH = -1;
if($IT && $IE && !ctrl) { // Test for Iteration Timer and Extension
i = -- $IT;
if(i == 8) // Timer clear test
FL(FL() & 0xE),
FH(0),
$IT = $IE == 1 || $IE == 3 ? 8 : 0,
$IE = $IE == 1 || $IE == 3 ? $IE : 0;
else
$FH = i;//FH(i);
} else
if(($IT == 8) && !ctrl)
FH(0),
$IT = !ctrl ? 0 : 8;
else
if($IR && !REG($IR) && !ctrl)
$IE = 0;
switch($IE) {
case 3: ic |= CR() < 128 ? 0x7000 : 0x3000; break; // WAIT:011
case 2: ic |= CR() < 128 ? 0x6000 : 0x2000; break; // LOOP:010
default: ic |= CR() >= 128 ? 0x4000 : 0x0000;
}
ic |= $A == -2 ? 0x0800 : 0x0000;
document.title = ic.Hex(4) + '/' + $IE;
code = preset.instructions[ic]; // Get instruction circuit
if(code && code.expression) {
trace.is_freeze = (!!$IR || !!$IT) && !!$IE || !(cr[0] & 0x80) || !(ctx[0][0xA8] & 0x02);
//trace.is_freeze = true;
if(ctrl) {
code.envelope(this, $IP, $B, $C, $A, $IE, $IR, $IT);
if($BRK) {
log("!/LOG $BRK");
trace.pointer = IP();
break;
}
//log("!/CLR (ic.lo = %d) || (ic.hi = %d) ", ic.lo(), ic.hi());
$IE = 0,
// $IT = 0,
$IR = 0;
if(CR() < 128)
FL(FL() & 0xE);
//trace.expression = "";
} else
if($IT != 8 && $IE != 1) {
ctrl = FL() & 0x0D;
/*if(((ic & 0xFF) >= 0xF0) && ((ic & 0xFF) <= 0xF9) && ($IE == 3)) {
trace.expression = ic & 0x0F;
if(ic >= 0x100) {
tmp = ((ic & 0xF) << 4) + 15;
i = ((ic >> 7) & 14) + 1;
while(i < 14)
$CTX[++ i] = 0,
$CTX[++ i] = 0;
while(tmp & 14)
$CTX[tmp] = $CTX[tmp -- & 15],
$CTX[tmp] = $CTX[tmp -- & 15];
FL(FL() & 0xE);
$IE = 0;
trace.expressions[ic & 15] = "";
} else {
if(trace.expressions[ic & 15] == "") {
tmp = ((ic & 0xF) << 4) + 15;
while(!$CTX[tmp] && !$CTX[tmp - 1] && (tmp & 14))
tmp -= 2
while(tmp & 14) {
$B = $CTX[tmp --];
action = $CTX[tmp --] + (($B << 3) & 0x700);
$C = ($B & 31) - ($B & 16) * 2;
$A = $B - ($B & 128) * 2;
$B &= 255;
trace.expressions[ic & 15] += preset.instructions[action].expression
.replace(/(\$B)/g, "" + $B)
.replace(/(\$C)/g, "" + $C)
.replace(/(\$A)/g, "" + $A)
.replace(/true/g, "false") + ";\r\n";
}
log("!/EVAL %s", trace.expressions[ic & 15]);
}
trace.is_freeze = true;
eval(trace.expressions[ic & 15]);
log("!/IT=%s IR=%s REG=%s", $IT.Hex(2), $IR.Hex(2), REG($IR).Hex(2));
if(!(($IT != 8) && (!$IR || (REG($IR) != 1))))
FL(FL() | 2);
//$EV = this.DO_CONTEXT;
//log("!/%d %d %d", it, ir, REG(ir));
}
} else */{
//if($IE == 3)
// $EV = this.DO_DEVICE;//scale = -scale;
eval(code.expression);
//code.envelope(this, $IP, $B, $C, $A, $IE, $IR, $IT);
//trace.expression = "";
}
if($EV == DO_DEVICE) {
log("!/LOG $BRK");
trace.pointer = IP();
break;
}
if($EV == DO_ACCLAIM) {
log("!/LOG $HLT/INT");
trace.pointer = IP();
break;
}
tmp = FL();
if($IE == 2 || $IE == 3)
log("!/FL %s %s", tmp.Hex(2), ctrl.Hex(2)),
FL((tmp & 0x2) | ctrl);
} else { // skip & fix
//$CTX.splice(0x0E, 2),
//$CTX.splice(0x02, 0, (ic & 0xFF), ((ic >> 3) & 0xE0) | ($A & 0x1F));
if((trace.fixing > 1) && ((trace.fixing & 15) > 1)) {
$CTX[-- trace.fixing] = ((ic >> 3) & 0xE0) | ($A & 0x1F);
$CTX[-- trace.fixing] = ic & 0xFF;
}
}
if($IF && ($IE > 1)) {
FL((FL() & 2) | 5);
continue;
}
if($IE != 0) {
if((!!$IR || !!$IT) && ($IE == 2))
//log("!/LOOP %d %s %s", it, $IP, $IP.Hex(4)),
IPnext($IP);
else
if((!!$IR || !!$IT) && ($IE == 3)) {
//log("!/WAIT %d %s %s - %s %s", it, $IP, $IP.Hex(4), FL().Hex(2), trace.ready);
if(!(FL() & 2)) {
IPnext($IP);
} else
//log("!/CLEAR FL"),
FL(FL() & 0x0E);
}
if(!$IR && !$IT)
if(!!(FL() >> 2) && !!(FL() & 1))
FL(FL() & 0x0E);
else
FL(tmp);
}
}
if($FH >= 0)
log("de"),
FH($FH);
if($IR) {
if((i = REG($IR)) && $IE >= 1)
REG($IR, -- i);
if(i == 0 && $IE >= 1)
FL(FL() & 0xE);
}
/* if(tick < 2 && CR()) {
trace.active = true;
break;
}
*/ }
} catch(e) {
trace.active = true;
log("@/CORE/%s %s %s:%s ($C:%s $A:%s) %s\r\n%s", $IP.Hex(4), ic.Hex(3), $B.Hex(2), code.instruction, $C.Hex(2), $A.Hex(4), e, code.expression);
}
if(($EV == DO_DEVICE)) {
IPnext($IP);
FL(0x0D);
log("!/IPnext");
}
if(($EV == DO_ACCLAIM)) {
IPnext($IP);
FL(0x0D);
log("!/IPnext");
}
if(!!CR() && !$BRK) {
//log("!TASK#%d", CR());
if(tick == 0 || $EV >= 0) {
$EV = $EV < 0 ? -$EV : +$EV;
console.log($EV);
switch($EV) {
case DO_OVERHEAD:log("!/CORE OVERHEAD");break;
case DO_ACCLAIM :log("!/CORE ACCLAIM"); break;
case DO_BUFFER :log("!/CORE BUFFER"); break;
case DO_CONTEXT :log("!/CORE CONTEXT"); break;
case DO_DEVICE :log("!/CORE DEVICE %s:%s", ctx[0][0xA8].Hex(2), $CTX[0xA8].Hex(2)); break;
case DO_ERROR :log("!/CORE ERROR"); break;
case DO_FORCE :log("!/CORE FORCE"); break;
case DO_GARRET :log("!/CORE GARRET"); break;
}
cr[1] |= 1 << $EV;
CR(0, CR(0) & 0x7F);
FL((FL() & 0x2) | 0x5), FH(0x8 | $EV);
log("!/CORE DEVICE %s", ctx[0][0xA8].Hex(2));
}
//log("!TASK#%d", CR());
}
if(tick >= 0)
//log("!/CORE tick"),
cr[6] = tick.lo(),
cr[7] = tick.hi();
trace.step = false;
trace.pointer = IP();
if(watch.active == "")
disassm();
}
this.CR = CR;
this.step = step;
this.ram = function(handle, data) {
var ok = false;
var addr;
if(isFinite(handle) && typeof handle == "number") {
addr = handle;
if(isFinite(data)) {
log("#/RAM/[%04X]=%02X", addr, data);
return ram[addr & 0xFFFF] = data;
} else {
data = DB(addr);
log("#/RAM/[%04X]:%02X", addr, data);
return data;
}
} else
if(handle) {
try {
ram = handle;
for(addr = 0; addr < 65536; ++ addr)
trace.halt[addr] = false,
ram[addr] = isFinite(data) ? data : Math.random() * 256 & 0x97;
log("#/RAM/Initializing successful for %d bytes", addr);
ok = true;
} catch(e) {
log("@/Initializing crashed... %d", 5);
}
} else
return ram;
if(!ok)
throw new Error("654");
return true;
}
function command_set(prefix, large) {
if(prefix && typeof prefix != "number")
return user.command_table = prefix;
var ic, ib, code, icx,
cols = 7,
i = 0,
dump = [],
Instructions = [],
operands = [],
Operation, Instruction, Operands;
var hPref = document.getElementById("Prefixes"),
hReps = document.getElementById("Repeats");
var iPref = parseInt(hPref.value),
iReps = parseInt(hReps.value);
if(iPref >= 0) {
ib = iPref & 0xFF,
prefix = (iPref & 0x0F00) | (iReps);
} else
if(isFinite(prefix))
ib = (prefix & 0x0E) == 0x0E ? prefix | 0xF0 : -257,
prefix = (prefix & 0x0E) == 0x0E ? 0 : (prefix & 0x7F) << 8,
ic = -1;
else {
prefix = 0x0000;
dump = parseInt(watch.address.value, 16);
if(!isFinite(dump))
dump = 0xFF00;
if(ram[dump - 2] == 0xB8 && (ram[dump - 1] & 0xFE) == 0xFE)
prefix |= (ram[dump - 1] & 0x0E) << 8;
dump = watch.address.value.replace(/[0-9A-F]{4}/g, "").match(/([0-9A-F]{2})/g);
if(!dump)
dump = [];
dump.push(0, 0);
ic = parseInt(dump.shift(), 16);
if((ic || (cr[0] < 128)) && ic < 0x80 && (ic & 7) == (ic >> 4))
prefix = ic ? (ic & 7) << 8 : 0x0800,
ic = parseInt(dump.shift(), 16),
ib = parseInt(dump.shift(), 16);
else
ib = parseInt(dump.shift(), 16),
prefix |= 0;
//prefix |= (FL() & 1 ? FL() >> 2 : 0) << 12;
prefix |= cr[0] < 128 ? 0x4000 : 0x0000;
dump = [];
}
for(code = 0; code < 256; ++ code) {
icx = prefix | code | ((ib & 0xFE) == 0xFE && code >= 0xB0 && code <= 0xBF && (prefix & 0x0F00) == 0x0000 ? (ib & 0x0F) << 8 : 0x0000);
Operation = preset.instructions[icx];
if(!Operation)
Operation = {
instruction :"fault",
operands :"empty",
remark :""
};
Instruction = Operation.instruction + " ".Mul(cols);
Operands = Operation.operands.replace(/ACC/, "-- BH CH DH AL BL CL DL".split(" ")[(FL() >> 4) & 7]);
len = Operands.length - cols;
if(len > 0)
Instruction = Instruction.substr(0, cols - len) + Operands,
Operands = Operands.substr(-cols);
Instruction += " ",
Operands += " ";
over = Operation.remark;
// if(Operation.expression.indexOf("// ") >= 0)
// over = " title='" + Operation.expression.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "'";
// over = Operation.expression.substr(3 + Operation.expression.indexOf("// ")) + ((code >> 4) == (code & 15) && !(code & 8) && !prefix ? "\r\n[ALT+" + (code & 7) + "]" :"") + "\r\n";
if(large)
over = " onmouseover='document.getElementById(\"Context\").innerText=cpu.preset.instructions[" + (prefix+code) + "].expression'";
html = "<span title='" + over + "'class=CPU_Group_" + Operation.color + " " + ((code >> 4) == (code & 15) && code < 0x80 ? "onclick='cpu.command_set(" + (code & 7) + "," + large + ")'" : "") + over + ">#</span>";
Instruction = Instruction.substr(0, cols);
Operands = Operands.substr(0, cols).replace(/(?:\$)(\+[1-7])/, function(str, high) {
high = parseInt(high);
return high < 4 ? "$+" + high : "$" + (high - (high & 4) * 2);
}).replace(/(\+)(IB)/, "\xB1$2");
Instructions.push(html.replace("#", (ic == code ? "<b style=background-color:white><u style=color:black>" + Instruction + "</u></b>" : Instruction)));
operands.push(html.replace("#", (ic == code ? "<b style=background-color:white><u style=color:black>" + Operands.replace("IB", ib.Hex(2)) + "</u></b>" : Operands)));
if((code & 15) == 15)
dump.push("&#x2551;" + ((large || code <= 0x10 ? "" : "<span style=text-decoration:overline>") + (code >> 4).Hex(1) + "&#x2551;" + Instructions.join("&#x2502;") + (large ? "" : "</span>") + "&#x2551;<br />")
+ ("&#x2551; &#x2551;"+ operands.join("&#x2502;") + "&#x2551;").replace(/(IB|XX)/g, "<b style=color:cyan>$1</b>")),
Instructions = [], operands = [];
}
prefix >>= 8;
for(code = 0; code < 16; ++ code)
operands.push("&#x255D;" + code.Hex(1) + "&#x255A;&#x2550;&#x2550;&#x2550;&#x2550;");
watch.instructions.innerHTML = ("__lwSBLWS".charAt(prefix >> 4)) + (prefix & 15 ? (prefix & 7) + "+" : "__") + "&#x2554;&#x2550;&#x2557; ".Mul(16) + "<br />" +
"&#x2554;&#x2550;&#x2566;" + operands.join("&#x2564;") + "&#x2557;<br />" +
dump.join(large ? "<br />&#x255F;&#x2500&#x256B;" + "&#x2500;".Mul(cols).Mul(16, "&#x253C;") + "&#x2562;<br />" : "<br />") +
"<br />&#x255A;&#x2550;&#x2569" + "&#x2550".Mul(cols).Mul(16, "&#x2567") + "&#x255D";
}
this.preset=preset;
//////// Assembler ///////////////////////////////////////////
this.assembly = function(listing, files) {
var text = listing.split(/\r?\n/),
Acc = 0,
Regs = {
BH :1,
CH :2,
DH :3,
AL :4,
BL :5,
CL :6,
DL :7
},
line, part, regs, args, code, regz, regy, regw,
val_nnIB, val_sxIB, val_s_IB,
instr, ins,
tmp,
dbg = true, // Debug mode
hlt = false, // Halting flag
arg, val,
rego, cnt,
regas, regaz, regay, regaw, regao,
ip, ipx,
labels = {}, // All labels
label, // Current label
labelz = {},
laps = 8,
lap = laps,
prc = 0,
prcs = text.length * laps,
title = document.title,
file = {
name :"",
begin :65535,
end :0,
bin :[]
},
bin = !files ? ram : file.bin;
log("!/ASSM/START");
do {
ip = -1; label = [];
for(line in text) {
++ prc;
if(files && !lap && ip >= 0 && file.begin > ip)
file.begin = ip;
part = text[line];
part = /([^:;"'`\s]*(?::| ?))?(?:\s)*([^\s;]*)(?:\s*)([^\s,;"'`]*)(?:[,\s]*)?([^\s,;"'`]*)(?:[,\s]*)?(?:(?:("(?:\\.|.)*?")|('(?:\\.|.)*?')|(`(?:\\.|.)*?`)|[^;"'`]*)*)*(\.*)/.exec(part);
if(part[1]) {
part[1] = part[1].replace(/[ :]$/, "");
tmp = part[1].replace(/:/g, "..").match(/(\.*)(.*)/);
label = label.slice(0, tmp[1].length).concat(tmp[2].split("."));
part[1] = label.join(".");
if(trace.labels[part[1]] != ip)
delete trace.labels[trace.labels[part[1].toUpperCase()]];
trace.labels[ip] = part[1],
trace.labels[part[1].toUpperCase()] = ip;
/*labelz = {};
cnt = 1 << 8;
do {
var idn = "";
for(var id in trace.labels)
if((id.length > idn.length) && (id.substr(-1) != " ") && !labelz[id])
idn = id;
else
continue;
//idn = (id.length > idn.length) && (id.substr(-1) != " ") && !labelz[id] ? id : idn;
if(idn != "")
labelz[idn] = trace.labels[idn];
} while((cnt --) && (idn != ""));*/
}
instr = part[2].toUpperCase();
if(instr.substr(-1) == "?" || instr.substr(-1) == "!") {
if((dbg || (instr.substr(-1) == "!")) && !lap)
trace.halt[ip] = true;
instr = instr.substr(0, instr.length - 1);
}
regs = [part[2], part[3]].join(" ").toUpperCase();
if(part[4])
regs += "," + part[4].toUpperCase();
if((regs = preset.alias[regs]) || (regs = preset.alias[instr])) {
regs = regs.split(" ");
for(var i in regs) {
if(typeof(regs[i]) == "string")
ram[ip ++] = parseInt(regs[i], 16);
}
continue;
}
part[3] = part[3].replace(/^(\.+)/, function(str, data) {
var data = data.length;
return label.slice(0, data).join(".") + ".";
});
part[4] = part[4].replace(/^(\.+)/, function(str, data) {
var data = data.length;
return label.slice(0, data).join(".") + ".";
});
regs = part[3];
if(part[4])
regs += "," + part[4];
args = [];
try{
regs = regs.replace(/(\.*)([A-Z_a-z][A-Z_a-z.0-9]*)/g, function(str, nest, tag) {
var tmp = trace.labels[label.slice(0, nest.length).concat(tag.split(".")).join(".").toUpperCase()];
//console.log(ip.Hex(4) + " " +str + "::" + nest + ":" + tag + "=" + tmp);
if(isFinite(tmp))
return Number(tmp).Hex(-4);
return nest + tag;
});
/*for(var i in labelz) {
regs = regs.replace(new RegExp("("+i.replace(/(\.)/g, "\\.")+")", "gi"), function(str, data) {
return "0x" + Number(labelz[i]).Hex(4);
});
}*/
}catch(e){}
rego = regs; ipx = false;
regs = regs.replace(/\$([+-](0x[0-9A-F]+|[0-9]+))/g, function(str, data) {
ipx = true;
data = (ip + parseInt(data) - 1) & 0xFFFF;
args.push(data);
return "0x" + data.Hex(4);
});
regs = regs.replace(/(0x[0-9A-F]+|[0-9]+)(\*|\/)(0x[0-9A-F]+|[0-9]+)+/g, function(str, x, op, y) {
return (op == "*" ? parseInt(x) * parseInt(y) : op == "/" && !!parseInt(y) ? parseInt(x) / parseInt(y) : 0x8000).Hex(-4);
});
regs = regs.replace(/(0x[0-9A-F]+|[0-9]+)([+-])(0x[0-9A-F]+|[0-9]+)+/g, function(str, x, op, y) {
return (op == "+" ? parseInt(x) + parseInt(y) : parseInt(x) - parseInt(y)).Hex(-4);
});
regs = regs.replace(/([-+](0x[0-9A-F]+|[0-9]+))/g, function(str, data) {
return "+" + (parseInt(data) + 256).Hex(-2);
});
regs = regs.replace(/\+[ABCD][LH][-+]/i, (str) => {
Acc = Regs[str.substr(1, 2).toUpperCase()];
return "+ACC" + str.substr(-1);
});
ins = preset.mnemonics[instr];
code = -1;
if(instr == "NOP")
console.log("mov");
if(ins && (regs in ins))
code = ins[regs];
else
if(ins && (([part[3].toUpperCase(), "ACC"].join(",") in ins) || (["ACC", part[4].toUpperCase()].join(",") in ins))) {
console.log("ACC", part[3], part[4]);
if(part[4].toUpperCase() in preset.mnemonics["HLT"]) {
code = preset.mnemonics["HLT"][part[4].toUpperCase()];
console.log(code.Hex(4));
code = 0x00008000 | code | (ins[[part[3].toUpperCase(), "ACC"].join(",")] << 16) | 0x20000000;
console.log(code.Hex(8));
} else
if(part[3].toUpperCase() in preset.mnemonics["HLT"]) {
code = preset.mnemonics["HLT"][part[3].toUpperCase()];
console.log(code.Hex(4));
code = 0x00008000 | code | (ins[["ACC", part[4].toUpperCase()].join(",")] << 16) | 0x20000000;
console.log(code.Hex(8));
}
} else {
arg_nnIB = regs.replace(/(0x[0-9A-F]+)|([0-9]+)/gi, function(str, data) { // nnIB
var bin0 = parseInt(data);
var tag0 = regs.replace(/\+(0x[0-9A-F]+|[0-9]+)/, "+IB");
var bin1 = parseInt(data);
var tag1 = bin1.hi().Hex(2) + "IB";
var bin2 = parseInt(data) + (ipx ? -ip- 3 : -ip - 2);
var tag2 = "$+IB";
var bin3 = parseInt(data) + (ipx ? -ip- 4 : -ip - 3);
var bin3a = bin3 + (bin3 < -128 ? +(bin3 & 0x80) * 2 : bin3 >= 128 ? +(bin3 & 0x80) * 2 : 0);
var tag3 = "$+" + ((bin3a >> 8) & 7) + "IB";
if(ins) {
if(tag0 in ins)
return args.push(bin0) ? "IB" : "IB";
if(tag1 in ins)
return args.push(bin1) ? tag1 : tag1;
if(bin2 >= -128 && bin2 < 128 && (tag2 in ins))
return args.push(bin2.lo()) ? tag2 : tag2;
if(((bin3 >= -1024 && bin3 < -128) || (bin3 >= 128 && bin3 <= 895)) && (tag3 in ins))
return args.push(bin3.lo()) ? tag3 : tag3;
if("IB" in ins)
return args.push(bin1) ? "IB" : "IB";
if(part[4] && (regs.split(",")[0] + ",IB") in ins)
return (code = ins[part[3] + ",IB"]) && args.push(bin1) ? "" : "";
if("" in ins)
return "";
}
args.push(bin1);
return "";
});
if(ins && (arg_nnIB in ins))
code = ins[arg_nnIB];
else
if(part[4] && ins && ([part[4].toUpperCase(), part[3].toUpperCase()].join(",") in ins))
code = ins[[part[4].toUpperCase(), part[3].toUpperCase()].join(",")];
else
if(part[4] && ins && (part[3].toUpperCase() in ins) && (part[4].toUpperCase() in ins))
code = ins[part[3].toUpperCase()] | (ins[part[4].toUpperCase()] << 16);
else
if(ins && (part[3].toUpperCase() in ins))
code = ins[part[3].toUpperCase()];
else
if(part[4] && ins && (regs.toUpperCase() in ins))
code = ins[regs.toUpperCase()];
else
if(ins && ((arg_nnIB = arg_nnIB.replace(/(\[[A-Z]{2})(\])/ig, "$1+IB$2")) in ins))
code = ins[arg_nnIB], args.unshift(0);
}
switch(instr) {
case "FILE": file.name = regs; continue;
case "DEBUG":dbg = !!parseInt(regs); continue;
case "ORG": ip = args.shift(); continue;
case "EQU": labels[part[1].toUpperCase()] = args.shift(); continue;
case "BRK": if(files && dbg && !lap) trace.halt[ip] = !!parseInt(regs); continue;
case "DB":
if(part[5]) {
args = part[5].replace(/Ё/ig, "Е").replace(/[абвгдеёжзийклмнопрстуфхцчшщъыьэюя]/ig, function(str, ascii) {
var koi7ru = "ЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ",
data = koi7ru.indexOf(ascii);
if(data < 0)
return ascii;
return String.fromCharCode(ascii + 0x60);
}).split("");
args.shift(); args.pop();
while(args.length) {
tmp = args.shift();
code = tmp.charCodeAt(0);
if(tmp == "\\")
switch(tmp = args.shift()) {
case '0': code = 0x00; break;
case 't': code = 0x09; break;
case 'n': code = 0x0A; break;
case 'h': code = 0x0C; break;
case 'r': code = 0x0D; break;
case 'e': code = 0x1B; break;
case '_': code = 0x1F; break;
case '<': code = 0x08; break;
case '>': code = 0x18; break;
case '^': code = 0x19; break;
case 'v': code = 0x1A; break;
default: code = tmp.charCodeAt(0);
}
trace.text[ip] = true,
bin[ip ++] = code;
}
} else
while(args.length)
trace.text[ip] = true,
bin[ip ++] = args.shift();
continue;
case "DW":
while(args.length)
tmp = args.shift(),
trace.text[ip] = true,
bin[ip ++] = tmp.lo(),
trace.text[ip] = true,
bin[ip ++] = tmp.hi();
continue;
}
hlt = !lap;
if((code & 0x0E00) == 0x0E00)
args.unshift((0xF000 | code) >> 8);
if(code >= 0) {
do {
if(!files)
trace.halt[ip] &= hlt;
switch(code & 0x3000) {
case 0x2000:
trace.text[ip] = false,
bin[ip ++] = 0xE0 + Acc,
trace.halt[ip] = false;
break;
case 0x3000:
trace.text[ip] = false,
bin[ip ++] = 0xB8,
trace.halt[ip] = false,
trace.text[ip] = false,
bin[ip ++] = 0xFE,
trace.halt[ip] = false;
break;
}
if((code & 0x0F00) == 0x0800)
bin[ip ++] = 0x00;
if((code & 0x0F00) > 0x0000 && (code & 0x0F00) <= 0x0700)
trace.text[ip] = false,
bin[ip ++] = ((code >> 8) & 7) * 0x11,
trace.halt[ip] = false;
trace.text[ip] = false,
bin[ip ++] = code & 0xFF;
if(((code & 0x00C0) == 0x080) && args.length > 0)
trace.text[ip] = false,
trace.halt[ip] = false,
bin[ip ++] = args.shift();
} while((code & 0x8000) && (code >>= 16));
}
if(files && !lap && ip >= 0 && file.end < end)
file.end = ip;
//if(Math.floor(100 * prc / prcs) <= 100)
// document.title = Math.floor(100 * prc / prcs) + "%";
}
} while(lap --);
document.title = title;
log("!/ASSM/FINISH");
disassm();
if(files)
return file;
}
function microdis() {
var i, ic, ib, z, asm;
var cmd = [];
i = (trace.expression << 4);
return cmd;////////////////////////////////////////////////////////////////////////////
while((i += 2) & 0x0F) {
ic = $CTX[i] & 0xFF, ib = $CTX[i + 1] & 0xFF;
ic |= (ib & 0xE0) << 3;
ib = (ib & 0x1F) - (ib & 0x10) * 2;
z = preset.instructions[ic];
asm = (z.instruction + " ").substr(0, 5) + z.operands;
asm = asm.replace(/([^$])\+IB/, function(str, ptr, rel) {
return ib < 128 ? ptr + "+" + ib : ptr + (ib - 256);
});
asm = asm.replace(/([0-9A-F]{2})IB/, "0x$1" + ib.Hex(2));
asm = asm.replace(/(\$\+)?([0-7]?IB)/, function(str, rel) {//$+0IB $+IB 0IB
var data, len = str.length;
data = (len == 3 || len == 5 ? +(str.substr(-3, 1)) * 256 : 0);
if(len == 3 || len == 5)
data = (data - (data & 0x400) * 2) + (ib - (ib & 0x80) * 2);
else
data = (data - (data & 0x80) * 2) + (ib - (ib & 0x80) * 2);
//data -= (len == 3 || len == 5 ? data & 0x400 : len == 2 ? 0 : data & 0x80) * 2;
//data += (ib - (ib & 128) * 2);// - (len == 2 ? 0 : (ib & 128) * 2);
return rel ? (i + data).Hex(-4) : data.Hex(len == 3 || len == 5 ? -3 : -2);
});
cmd.unshift(asm);
}
return cmd;
}
//////// Disassembler ////////////////////////////////////////
function disassm() {
var i, j,
addr = (trace.pointer &= 0xFFFF), // active IP
ip = trace.address & 0xFFFF, lines = trace.lines, next = ip,
jp,
alias, walias,
list = [], lp, width,
regs = [],
ips = [],
lid, // label id
ic, ib = 0, ie, asm,
active = addr.Hex(4) + " " + ram[addr].Hex(2),
extend = "",
color,
rem = "", row, halt,
cmm = "",
acc = "???", cnt = 0, Cnt = "", wait = false;
if(ip > addr)
ip = trace.address = (addr + 0xFFF0) & 0xFFFF;
if("PTR".indexOf(watch.active) >= 0) {
i = 2;
active = true||this.w.rg < 0 ? " style=background-color:#252>" : this.w.xx == this.r16(this.w.rg) ? " style=background-color:blue>" : " style=background-color:red>";
if(extend)
regs.push(extend);
else
regs.push((jp = SP()).Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[SP]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = BP(), rem = "BP", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = SI(), rem = "SI", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = DI(), rem = "DI", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
regs.push(AX().Hex(4) + " " + flags());
jp = BX(), rem = "BX", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = CX(), rem = "CX", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = DX(), rem = "DX", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - i, i)+ "</u>[" + rem + "]" + ram.Dump(jp, 8) + "|" + ram.Dump(jp + 8, 8) + "<u>" + ram.Text(jp - i, i) + "</u>" + ram.Text(jp, 16));
jp = IP(), rem = "IP", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - 0, i)+ "</u>[" + rem + "]" + ram.Dump(jp & 0xFFF0, 8) + "|" + ram.Dump((jp & 0xFFF0) + 8, 8) + " " + ram.Text(jp & 0xFFF0, 16));
//jp = IP() + 16, rem = "IP", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - 0, i)+ "</u>[" + rem + "]" + ram.Dump(jp & 0xFFF0, 8) + "|" + ram.Dump((jp & 0xFFF0) + 8, 8) + " " + ram.Text(jp & 0xFFF0, 16));
//jp = IP() + 32, rem = "IP", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - 0, i)+ "</u>[" + rem + "]" + ram.Dump(jp & 0xFFF0, 8) + "|" + ram.Dump((jp & 0xFFF0) + 8, 8) + " " + ram.Text(jp & 0xFFF0, 16));
//jp = IP() + 48, rem = "IP", regs.push(jp.Hex(4) + " <u>" + ram.Dump(jp - 0, i)+ "</u>[" + rem + "]" + ram.Dump(jp & 0xFFF0, 8) + "|" + ram.Dump((jp & 0xFFF0) + 8, 8) + " " + ram.Text(jp & 0xFFF0, 16));
regs = regs.concat(ctx[cr[0] & 127].Dump().split(/\r?\n/));
command_set();
}
lines -= regs.length;
for(i = 0, jp = ip; i < lines - 2 || jp < addr; ++ i) {
ie = 0;
ips.push(jp);
ic = ram[jp], jp = (jp + 1) & 0xFFFF;
if((ic || !(cr[0] & 0x80)) && (ic & 7) == (ic >> 4))
ie |= ic & 7 ? ic & 7 : 8;
if(ie)
ic = ram[jp], jp = (jp + 1) & 0xFFFF;
if((ic & 0xC0) == 0x80)
jp = (jp + 1) & 0xFFFF;
}
if(ips.length > lines - 2)
ip = trace.address = ips.pop();
walias = 0;
while(lines -- > 0) {
if(!lines)
this.DIP = ip, ip = addr & 0xFFFF;
jp = ip;
row = [ip.Hex(4)];
rem = "";
cmm = [];
ie = 8;
if(typeof trace.labels[ip] == "string")
cmm[1] = trace.labels[ip] + ":";
if(walias < 1) {
alias = "";
walias = 6;
data = [ram[ip].lo().Hex(2), ram[(ip + 1) & 65535].lo().Hex(2), ram[(ip + 2) & 65535].lo().Hex(2), ram[(ip + 3) & 65535].lo().Hex(2), ram[(ip + 4) & 65535].lo().Hex(2), ram[(ip + 5) & 65535].lo().Hex(2)].join("");
do {
if(data in preset.alias) {
alias = preset.alias[data];
rem = alias.split(/\t/)[1];
alias = alias.split(/\t/)[0];
extend = alias.split(/\s|!/);
if(extend[1]) {
extend = extend[1].replace(/(?:\[)([0-7])(?:\])/g, "$1").split(/[\s\t,]/);
extend.push("--", "--");
if(rem)
rem = rem.replace(/\%X/g, extend[0]).replace(/\%Y/g, extend[1]);
break;
}
}
data = data.substr(0, -- walias * 2);
} while(walias);
}
halt = true && trace.halt[ip];
lp = ip == addr;
if(trace.text[ip]) {
i = 0;
while(i < 29 && trace.text[ip]) {
if(ram[ip] < 32 || ram[ip] > 128)
row.push(ram[ip].Hex(2));
lp |= ip == addr;
++ i, ++ ip;
}
row.push("..", "..", "..");
asm = ram.Text(ip - i, i) + String.fromCharCode(0xB7).Mul(29 - i);
asm = row.slice(0, 4).join("\\") + "|" + asm + "|Text";
if(lines)
list.push("<span class=CPU_Group_Z>" + asm + "</span>");
if(lp)
active = asm;
continue;
}
if((ram[ip - 2] & 0xFF) == 0xB8 && (ram[ip - 1] & 0xFF) == 0xFE)
ie = 0x30;//(ram[ip - 1] & 0x0F) << 8;
else
ie = 0x00;
ic = ram[ip].lo(), ip = (ip + 1) & 0xFFFF,
walias --;
if((ic || !(cr[0] & 0x80)) && (ic & 7) == (ic >> 4))
ie |= ic & 7 ? ic & 7 : 8,
lp |= ip == addr,
halt |= true && trace.halt[ip],
row.push(ic.Hex(2)),
ic = ram[ip].lo(), ip = (ip + 1) & 0xFFFF,
row.push(ic.Hex(2)),
acc = ic == 0 ? "?? BH CH DH AL BL CL DL".split(" ")[ie & 7] : acc,
cnt = ic & 7,
walias --;
else
row.push(" ", ic.Hex(2));
if((ic & 0xC0) == 0x80)
lp |= ip == addr,
halt |= true && trace.halt[ip],
ib = ram[ip].lo(), ip = (ip + 1) & 0xFFFF,
ie |= (ic & 0xF0) == 0xB0 && (ib & 0xFE) == 0xFE && (ie & 7) == 0 ? ib & 0x0F : 0x00,
row.push(ib.Hex(2)),
walias --;
if(Cnt != "" && preset.instructions[(ie << 8) | ic | 0x2000])
ic |= 0x2000;
z = preset.instructions[(ie << 8) | ic];
if(!z)
z = {
instruction :"fault",
operands :"empty"
};
asm = (z.instruction + " ").substr(0, 5) + z.operands;
asm = asm.replace(/(ACC)/, function() { return Cnt != "" ? Cnt : acc; });
asm = asm.replace(/(CNT)/, function() { return cnt; });
if(z.instruction == "HLT" && z.operands != "")
acc = z.operands;
asm = asm.replace(/([^$])\+IB/, function(str, ptr, rel) {
return ib < 128 ? ptr + "+" + ib : ptr + (ib - 256);
});
asm = asm.replace(/([0-9A-F]{2})IB/, "0x$1" + ib.Hex(2));
asm = asm.replace(/(\$\+)?([0-7]?IB)/, function(str, rel) {//$+0IB $+IB 0IB
var data, len = str.length;
data = (len == 3 || len == 5 ? +(str.substr(-3, 1)) * 256 : 0);
if(len == 3 || len == 5)
data = (data - (data & 0x400) * 2) + (ib - (ib & 0x80) * 2);
else
data = (data - (data & 0x80) * 2) + (ib - (ib & 0x80) * 2);
//data -= (len == 3 || len == 5 ? data & 0x400 : len == 2 ? 0 : data & 0x80) * 2;
//data += (ib - (ib & 128) * 2);// - (len == 2 ? 0 : (ib & 128) * 2);
return rel ? (ip + data).Hex(-4) : data.Hex(len == 3 || len == 5 ? -3 : -2);
});
if(ic > 0xE0 && ic <= 0xE7)
cnt = ic & 7, Cnt = "-- BH CH DH AL BL CL DL".split(" ")[cnt];
else
Cnt = "";
//cmm[1] = (ie+ic).Hex(4);
if(!cmm[1]) {
lid = asm.match(/(0x[0-9A-F]{4})/);
if(lid) {
// log("!/DIS:%s %s", lid[0], trace.labels[parseInt(lid[0])]);
if(typeof trace.labels[parseInt(lid[0])] == "string")
cmm[1] = "(" + trace.labels[parseInt(lid[0])] + ")";
};
}
width = row.length;
while(row.length < 4)
row.push(" ");
// if(!cmm[1])
// cmm = z.expression.split("// ");
if(!cmm[1])
cmm[1] = z.remark;
if(alias != "") {
data = alias.split(/[!\s]/);
asm = asm.split(/\s+/);
asm = asm.join(" ".Mul(5 - asm[0].length));
asm = (data[0] + " ".Mul(4)).substr(0, 5) + (data[1] + " ".Mul(7)).substr(0, 7) + ";" + (asm + " ".Mul(16)).substr(0, 16);//, rem = "";
//asm = (data.replace("!", "") + " ".Mul(7)).substr(0, 9) + (" ".Mul(16) + asm.replace(/\s+/g, " ")).substr(-18), rem = "";
}
if(rem == "")
if(cmm[1]) {
if(rem.split(" ")[0] == z.instruction)
asm += "/" + rem.split(" ")[1];
else
if(rem)
asm += " ".Mul(16 - asm.length) + ";" + rem;
else
rem = cmm[1];//z.expression.substr(3 + z.expression.indexOf("// "));
}
if(walias >= 0 && alias == "")
asm = row.join(" ") + "|" + " ".Mul(12) + ";" + (asm + " ".Mul(16)).substr(0, 16) + "|" + rem;
else
asm = row.join(" ") + "|" + (asm + " ".Mul(29)).substr(0, 29) + "|" + rem;
alias = "";
if(lp)
active = asm;
color = (watch.dirty || (watch.active == "")) && (walias < 0) ? z.color : "Z";
asm = "<span class='CPU_Group_" + color + (halt ? " halted" : "") + (lp ? " active" : "") + "' onclick='cpu.trace.halt[" + jp + "] ^= true; cpu.disassm()' ondblclick='cpu.trace.pointer = " + jp + "'>" + asm + "</span>";
// asm = "<span class='CPU_Group_" + z.color + (halt ? " halted" : "") + (lp ? " active" : "") + " title='style=text-decoration:overline><u'>" + asm + "</span>";
if(lp) {
/* if(ie && (ic & 0xEF) == 0xEA) {
i = (AX() >> 12) & 15;
i = i < 8 ? this.reg(i) : i + 248;
extend = (i & 256 ? "EX#" + i.Hex(1) : "Ex" + i.Hex(2)) + " <u>";
{
extend += (i >= 256 && i > 257) || (i < 256 && i >= 2) ? this.r.ex[i - 2].Hex(2) + " " : "?? ";
extend += (i >= 256 && i > 256) || (i < 256 && i >= 1) ? this.r.ex[i - 1].Hex(2) : "??";
extend += "</u>[RX]";
for(j = 0; j < 16; ++ j)
extend += (j ? (j & 0xFF) == 1 ? "|" : " " : "") + ((i < 256 && i + j < 256) || (i >= 256 && i + j < 264) ? this.r.ex[i + j].Hex(2) : "??");
extend += " ";
for(j = 0; j < 16; ++ j)
extend += String.fromCharCode(i >= 256 | (i + j) > 255 ? 0xB7 : this.r.ex[i + j] >= 32 && this.r.ex[i + j] < 127 ? this.r.ex[i + j] : 0xB7);
}
}*/
}// else asm = "<span class=CPU_Group_" + z.color + " onclick='document.getElementById(\"DebugAddr\").value=(cpu.DR=" + parseInt(asm, 16) + ").Hex(4)' title='Set break point'>" + asm + "</span>";
//if(halt)
// asm = "<s>" + asm + "</s>";
//asm = "<span class=prefix onclick='document.getElementById(\"DebugAddr\").value=(cpu.DR=" + parseInt(asm, 16) + ").Hex(4)' title='Set break point'>" + asm + "</span>";
if(!list.length)
next = ip;
if(lines)
list.push(asm);
}
watch.disassembly.innerHTML = list.concat(regs).join("<br />");
var inter = active.split("|");
if(watch.active != "P")
watch.address.value = inter.shift().replace(/\s+$/, "");
else
inter.shift();
if(watch.active != "T")
watch.mnemonic.value = inter.shift().replace(/\s+/g, "\t").replace(/\s+(\(.*)?$/, "");
else
inter.shift();
if(watch.active != "R")
watch.remark.value = inter.shift().replace(/\s+$/, "");
if(!(watch.active in "012345678".split("")))
command_set();
//watch.dirty = true;
}
this.display = function(callback) {
display = callback;
display(this);
}
this.interface = function(controls) {
watch.instructions = controls.instructions || watch.instructions;
watch.disassembly = controls.disassembly || watch.disassembly;
watch.registers = controls.registers || watch.registers;
watch.address = controls.address || watch.address;
watch.mnemonic = controls.mnemonic || watch.mnemonic;
watch.remark = controls.remark || watch.remark;
watch.context = controls.context || watch.context;
}
//////////////////////////////////////
this.command_set = command_set;
this.disassm = disassm;
this.JP = JP;
this.trace = trace;
this.watch = watch;
this.log = log;
this.ctx = ctx;
this.preset = preset;
//////////////////////////////////////
i = ctx.length;
while(i --) {
ctx[i] = new Array(j = 256);
while(j --)
ctx[i][j] = Math.random() * 0*256 & 255;
}
log("!/POWER/CONTEXT[%d]", ctx.length);
DEBUG_TIMER(true);
if(descriptions) {
var instructions = /^([0X1_]{19,})([A-F_X])\t([^:+\t]+)(\+?)\t*([^:\t]*?)\t*:(.*)(\/\/.*)$/gm;
var Register = []; // Register alias
var Logic = []; // Logic alias
var text = [];
var Pin = {
$M :0,
$T :0,
$U :0,
$V :0,
$W :0,
$X :0,
$Y :0,
$Z :0
};
var Pins = [];
var Registers = [];
var Logics = [];
var schema = descriptions;
var decoder = schema.match(instructions);
for(var id in Pin)
Pins.push(id);
schema = schema.replace(/^ASCx([0-9A-F]{4})(( ([0-9A-F]{2})){16})/gm, function(str, address, bytes) {
var addr = parseInt(address, 16);
bytes.substr(1).split(" ").forEach(function(code) {
preset.ascii[addr ++] = parseInt(code, 16);
});
return "";
});
schema = schema.replace(/^([A-Z]+[0-9 A-Z\[,\]!]*)\t+?\@([0-9A-F\s\t]+?(\t.*)?)$/gm, function(str, alias, instr) {
preset.alias[alias.replace(/(!)(.)/, " $2").replace(/!/, "")] = instr.replace(/\t.*/, "");
instr = instr.split(/\t+/);
preset.alias[instr[0].replace(/\s+/g, "")] = alias + (instr[1] ? "\t" + instr[1] : "");
//console.log(alias + "=" + instr + " / (" + alias.replace(/(!)(.)/, " $2").replace(/!/, "") + ")");
return "";
});
schema = schema.replace(/^([^\s]{1,13})\t(.*)$/gm, function(str) {
var str = str.split(/\t+/);
Registers.push(str[0]);
Register[str[0]] = str[1];
if(str[3])
Logics.unshift(str[0] + "!"),
Logic[str[0] + "!"] = str[3];
if(str[2])
Logics.push(str[0]),
Logic[str[0]] = str[2];
text.push([str].join("\t"));
return "";
});
Pins = new RegExp("(" + Pins .join("|").replace(/(\$)/g, "\\$1") + ")", "g");
Registers = new RegExp("(" + Registers .join("|").replace(/(\$)/g, "\\$1") + ")", "g");
Logics = new RegExp("(" + Logics .join("|").replace(/(\$)/g, "\\$1") + ")", "g");
var base,
over,
last,
mix,
bits,
laps,
lap,
counter, cnt,
mask;
var $D, // MMMLLLKZZZJYYYIXXX
$X, // ---------------XXX
$I, // --------------I---
$Y, // -----------YYY----
$J, // ----------J-------
$Z, // -------ZZZ--------
$K, // ------K-----------
$L, // ---LLL------------
$M; // MMM---------------
var $1, $2;
var instruction,
operand,
expression,
description,
alias, xalias,
logic;
decoder.forEach(function(str) {
str.replace(instructions,
function(str, pins, groups, mnemonics, few, operands, expressions, descriptions) {
pins = pins.replace(/_+/g, "");
base = parseInt(pins.replace(/X/g, "0"), 2), // 0XX1X0X1XX -> 0001000100
over = parseInt(pins.replace(/X/g, "1"), 2), // 0XX1X0X1XX -> 0111101111
last = parseInt(pins.replace(/./g, "1"), 2), // 0XX1X0X1XX -> 1111111111
mix = base ^ over ^ last; // 1001010100
/*bits = [],
laps = 1,
mask = parseInt(pins.replace(/X/g,
function(str, position, digits) {
bits.push(1 << (digits.length - position - 1));
laps <<= 1;
return "0";
}), 2);
for(lap = 0; lap < laps; ++ lap) {
counter = bits.length,
$D = mask, cnt = lap;
while(counter --)
$D |= cnt & 1 ? bits[counter] : 0,
cnt >>= 1;*/
for($D = base; $D <= over; $D = ((($D | mix) + 1) & ~mix) | base) {
$X = 0x07 & ($D >> 0),
$I = 0x01 & ($D >> 3),
$Y = 0x07 & ($D >> 4),
$J = 0x01 & ($D >> 7),
$Z = 0x0F & ($D >> 8),
$z = 0x07 & ($D >> 8),
$L = 0x07 & ($D >> 12),
$M = $J ? ($Y < 4 ? $Y : !$I ? 4 : 4 | [0, 0, 1, 3, 3, 3, 2, 2][$X])
: (!$Y && ($X == $Z)) || (!$X && ($Y == $Z)) ? 3
: ($X == $Y ? $Y == ($L & 4 ? $Z : $z) ? 7 : $Y > $z ? 5 : 6 : $X < $Y ? 1 : 2),
Pin.$T = $Z * 10 + ($D & 15),
Pin.$U = $Z ? (($Z - ($Z & 4) * 2) & 7).Hex(1) : "",
Pin.$V = ($Z * 16 ^ ($D & 15) ^ (($D & 16) ? 0xF0 : 0x00)).Hex(2),
Pin.$W = ($D & 31).Hex(2),
Pin.$X = $X,
Pin.$Y = $Y,
Pin.$Z = $Z;
Pin.$M=$M;
/// console.log($D.Hex(5) + ":" + $M);
if(((($D >> 15) & 7) == ($M & 7)) && !preset.instructions[$D & 0x7FFF]) {
instruction = mnemonics .replace(Pins ,function(str, id) { return Pin[id]; });
operand = operands .replace(Pins ,function(str, id) { return Pin[id]; });
expression = expressions .replace(Pins ,function(str, id) { return Pin[id]; });
description = descriptions .replace(Pins ,function(str, id) { return Pin[id]; });
instruction = instruction .replace(Registers ,function(str, id) { return Register[id]; });
operand = operand .replace(Registers ,function(str, id) { return Register[id]; });
description = description .replace(Registers ,function(str, id) { return Register[id]; });
expression = expression .replace(Logics
,function(str, id) {
logic = Logic[id];
if(typeof logic == "string")
logic = logic .replace(Pins ,function(str, id) { return Pin[id]; });
return logic;
});
if(mnemonics == "HLT")
console.log(`M :${$M}`);
//console.log(expression);
// console.log([groups, ("0".Mul(17) + ($D & 0x7FFF).toString(2)).substr(-18), instruction, operand, expression, description].join("\t"));
/*if(operand.indexOf(" ") > 0) {
console.log(operand);
$1 = operand.split(",")[0].split(/\s/);
$2 = operand.split(",")[1].split(/\s/);
if($1[0] in preset.mnemonics) {
} else
if($2[0] in preset.mnemonics) {
console.log($2[0] + "(" + $2[1] + ")");
console.log(preset.mnemonics[$2[0]]);
for(var N = 1; N <= 7; ++ N) {
$2[1] = "" + N;//$2[1].replace(/(\$N)/g, function(str, n) {console.log(str,n,N); return "/"+N;});//.replace(Pins ,function(str, id) { return Pin[id]; });
console.log(N + ":" + $2);
console.log(preset.mnemonics[$2[0]][$2[1]]);
}
}
}*/
try {
preset.instructions[$D & 0x7FFF] = {
color : groups,
instruction : instruction,
operands : operand.replace(/\{0\}/, "").replace(/\{(.+)\}/, "$1"),
expression : expression,
envelope : new Function("_, $IP, $B, $C, $A, $IE, $IR, $IT", "with(_) {" + expression + ";} return true;"),
remark : description.replace(/^\/\//, "")
};
} catch(e) {
console.log($D.Hex(4) + ":" + expression);
}
if(!preset.mnemonics[instruction])
preset.mnemonics[instruction] = [];
operand.split("/").forEach(function(operand) {
if(!(operand in preset.mnemonics[instruction]))
preset.mnemonics[instruction][operand] = ($D & 0x7FFF);
});
}
}
});
});
/* schema.replace(instructions, function(str, pattern, color, Instruction, Few, Operands, Expression) {
var bits = [],
chop = 0,
laps = 1,
counter, code,
mask = parseInt(pattern.replace(/X/g, function(str, position, digits) {
bits.unshift(1 << (digits.length - position - 1));
chop |= position < 2 ? bits[0] : 0;
laps <<= 1;
return "0";
}), 2);
for(var lap = 0; lap < laps; ++ lap) {
counter = bits.length,
code = mask;
while(counter --)
code |= (lap >> counter) & 1 ? bits[counter] : 0;
var _z = 0x07 & (code >> 8),
_y = 0x07 & (code >> 4),
_x = 0x07 & (code >> 0),
locker = code & 0x80
? ((0x3EA80 >> (_y & 2)) >> (_x << 1)) & (code & 8 ? 3 : 0) | (_x > 1 && _x < 6 && _y < 4 ? 4 : 0)
: (((_x == _y ? 0 : 3) | (_z == 0 ? 0 : _x == _z ? 0 : _x > _z ? 1 : _z > _x ? 2 : 3)) | (_x < _y ? 4 : 0)),
helpers = {
"#T": ((code >> 8) & 7) * 10 + (code & 15),
"#U": ((code >> 8) & 7) ? ((_z - (_z & 4) * 2) & 7).Hex(1) : "",
"#V": (((code >> 8) & 7) * 16 ^ (code & 15) ^ ((code & 16) ? 0xF0 : 0x00)).Hex(2),
"#W": ((code >> 0) & 31).Hex(2),
"#X": ((code >> 0) & 7),
"#Y": ((code >> 4) & 7),
"#Z": ((code >> 8) & 7)
};
if(!preset.instructions[code & 0x07FF] && (((code >> 11) == locker))) {
var instruction = Instruction,
operands = Operands,
expression = Expression;
for(counter in helpers) {
var alias = new RegExp(counter, "g");
instruction = instruction.replace(alias, helpers[counter]),
operands = operands.replace(alias, helpers[counter]),
expression = expression.replace(alias, helpers[counter]);
}
for(counter in Registers)
instruction = instruction.replace(new RegExp(counter, "g"), Registers[counter]),
operands = operands.replace(new RegExp(counter, "g"), Registers[counter]);
for(counter in Logics) {
var logic = Logics[counter];
if(typeof logic == "string") {
for(var cnt in helpers) {
var alias = new RegExp(cnt, "g");
logic = logic.replace(alias, helpers[cnt]);
}
}
expression = expression.replace(new RegExp(counter, "g"), logic);
}
//console.log(expression);
preset.instructions[code & 0x07FF] = {
color : color,
instruction : instruction,
operands : operands,
expression : expression.replace(/\s*\/\/.*(?#---)/, ""),
envelope : new Function("_, $IP, $IB, $IV, $IW, $IE, $IR, $IT", "with(_) {" + expression.replace(/\s*\/\/.*(?#---)/, ";} return true;")),
remark : expression.replace(/^.*?\/\/\s(.*)/, "$1")
};
if(!preset.mnemonics[instruction])
preset.mnemonics[instruction] = [];
preset.mnemonics[instruction][operands] = (code & 0x07FF) | (Few ? 0x0800 : 0x0000);
text.push([color, (code & 0x0FFF).Hex(4), instruction, operands, expression].join("\t"));
}
}
});*/
var w, h, c, b, j, x, y, z, p, q, d, a;
watch.fontCnv = document.createElement("canvas");
watch.fontCnv.width = 256 * 8 * 2;
watch.fontCnv.height = 16 * 8 * 2;
watch.fonts = watch.fontCnv.getContext("2d");
watch.fontBit = watch.fonts.getImageData(0, 0, watch.fontCnv.width, watch.fontCnv.height);
d = watch.fontBit.data;
w = watch.fontCnv.width;
q = w * 4 * 8;
for(i = 0; i < 256; ++ i) {
x = i * 16;
for(y = 0; y < 8; ++ y) {
a = preset.ascii[i * 8 + y];
p = (x + y * w + 7) * 4;
for(z = 0; z < 8; ++ z, p -= 4, a >>= 1) {
b = a & 1 ? 0 : 0xFF000000;
c = a & 1 ? 0xFF000000 : 0;
d[p + q * 0 + 0] = (c >> 0) & 255; d[p + q * 1 + 0] = (b >> 0) & 255;
d[p + q * 0 + 1] = (c >> 8) & 255; d[p + q * 1 + 1] = (b >> 8) & 255;
d[p + q * 0 + 2] = (c >> 16) & 255; d[p + q * 1 + 2] = (b >> 16) & 255;
d[p + q * 0 + 3] = (c >> 24) & 255; d[p + q * 1 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFF0000FF;
c = a & 1 ? 0xFF0000FF : 0;
d[p + q * 2 + 0] = (c >> 0) & 255; d[p + q * 3 + 0] = (b >> 0) & 255;
d[p + q * 2 + 1] = (c >> 8) & 255; d[p + q * 3 + 1] = (b >> 8) & 255;
d[p + q * 2 + 2] = (c >> 16) & 255; d[p + q * 3 + 2] = (b >> 16) & 255;
d[p + q * 2 + 3] = (c >> 24) & 255; d[p + q * 3 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFF00FF00;
c = a & 1 ? 0xFF00FF00 : 0;
d[p + q * 4 + 0] = (c >> 0) & 255; d[p + q * 5 + 0] = (b >> 0) & 255;
d[p + q * 4 + 1] = (c >> 8) & 255; d[p + q * 5 + 1] = (b >> 8) & 255;
d[p + q * 4 + 2] = (c >> 16) & 255; d[p + q * 5 + 2] = (b >> 16) & 255;
d[p + q * 4 + 3] = (c >> 24) & 255; d[p + q * 5 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFF00FFFF;
c = a & 1 ? 0xFF00FFFF : 0;
d[p + q * 6 + 0] = (c >> 0) & 255; d[p + q * 7 + 0] = (b >> 0) & 255;
d[p + q * 6 + 1] = (c >> 8) & 255; d[p + q * 7 + 1] = (b >> 8) & 255;
d[p + q * 6 + 2] = (c >> 16) & 255; d[p + q * 7 + 2] = (b >> 16) & 255;
d[p + q * 6 + 3] = (c >> 24) & 255; d[p + q * 7 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFFFF0000;
c = a & 1 ? 0xFFFF0000 : 0;
d[p + q * 8 + 0] = (c >> 0) & 255; d[p + q * 9 + 0] = (b >> 0) & 255;
d[p + q * 8 + 1] = (c >> 8) & 255; d[p + q * 9 + 1] = (b >> 8) & 255;
d[p + q * 8 + 2] = (c >> 16) & 255; d[p + q * 9 + 2] = (b >> 16) & 255;
d[p + q * 8 + 3] = (c >> 24) & 255; d[p + q * 9 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFFFF00FF;
c = a & 1 ? 0xFFFF00FF : 0;
d[p + q * 10 + 0] = (c >> 0) & 255; d[p + q * 11 + 0] = (b >> 0) & 255;
d[p + q * 10 + 1] = (c >> 8) & 255; d[p + q * 11 + 1] = (b >> 8) & 255;
d[p + q * 10 + 2] = (c >> 16) & 255; d[p + q * 11 + 2] = (b >> 16) & 255;
d[p + q * 10 + 3] = (c >> 24) & 255; d[p + q * 11 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFFFFFF00;
c = a & 1 ? 0xFFFFFF00 : 0;
d[p + q * 12 + 0] = (c >> 0) & 255; d[p + q * 13 + 0] = (b >> 0) & 255;
d[p + q * 12 + 1] = (c >> 8) & 255; d[p + q * 13 + 1] = (b >> 8) & 255;
d[p + q * 12 + 2] = (c >> 16) & 255; d[p + q * 13 + 2] = (b >> 16) & 255;
d[p + q * 12 + 3] = (c >> 24) & 255; d[p + q * 13 + 3] = (b >> 24) & 255;
b = a & 1 ? 0 : 0xFFFFFFFF;
c = a & 1 ? 0xFFFFFFFF : 0;
d[p + q * 14 + 0] = (c >> 0) & 255; d[p + q * 15 + 0] = (b >> 0) & 255;
d[p + q * 14 + 1] = (c >> 8) & 255; d[p + q * 15 + 1] = (b >> 8) & 255;
d[p + q * 14 + 2] = (c >> 16) & 255; d[p + q * 15 + 2] = (b >> 16) & 255;
d[p + q * 14 + 3] = (c >> 24) & 255; d[p + q * 15 + 3] = (b >> 24) & 255;
}
}
}
watch.fonts.putImageData(watch.fontBit, 0, 0);
}
};
/*X80.prototype = {
get _Acc() {
var index = ($CTX[0xA8] >> 4) & 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
data = $CTX[index];
return data;
},
set _Acc(data) {
var index = ($CTX[0xA8] >> 4) & 7;
index = 0xA8 + (index & 3) * 16 - (index & 4) * 2;
data &= 0xFF,
$CTX[index] = data;
return data;
}
}
/*
80..87:
*/
var Reset = 0,
Source = "";
var cpu;
var cnv;
var c2d;
var img;
var date = new Date();
function display(core) {
var row = [], ram, i, p, h, w, x, y, cx = -1, cy = -1, c, d, u, f = 7, g = 0, col = 7, gnd = 0, s = "";
var oldSeconds = date.getSeconds();
date = new Date();
core.trace.stamps[1] = date.getTime();
var ms = (date.getMilliseconds() % 500 > 250);
if(date.getSeconds() != oldSeconds)
;//core.IRQ(core.DO_FORCE);
setTimeout(display, 1000 / cpu.trace.flash, cpu);
ram = core.ram();
cx = ram[0x76CF].lo(), cy = ram[0x76CE].lo();
if(document.getElementById("Display").style.display != "none") {
w = 78, h = 30;
x = 0, y = 0, p = 0x76D0;
f <<= 4, g <<= 4;
while(y < h) {
c = ram[p];
d = c & 255;
if(d >= 0x80 && d <= 0x87)
f = (c & 7) << 4;
if(d >= 0x90 && d <= 0x97)
g = (c & 7) << 4;
d = x == cx && y == cy ? 0 : 8;
if(true || c < 255 || d == 0) {
c &= 255;
d = ms ? d | 8 : d;
core.watch.c2d.drawImage(core.watch.fontCnv, c * 16 + 2, 8 ^ g ^ d, 6, 8, x * 6, y * 8, 6, 8),
core.watch.c2d.drawImage(core.watch.fontCnv, c * 16 + 2, 0 ^ f ^ d, 6, 8, x * 6, y * 8, 6, 8);
ram[p] = ms || !d ? c : c | 256;
}
ram[p] = c | 256;
if(++ x >= w)
f = 7 << 4,
g = 0 << 4,
x = 0,
++ y;
++ p;
}
} else {
for(i = 0, w = 78, h = 30, x, y, c, u; i < w * h * 0; ++ i)
x = i % w, y = Math.floor(i / w),
c = ram[(i + 0x76D0) & 0xFFFF],
ram[(i + 0x76D0) & 0xFFFF] = (c | 256),
u = c < 256 ? "<span style=color:red>" : (c &= 255, "<span>"),
row[y] = (x ? row[y] : "") + u +
(x == ram[0x76CF].lo() && y == ram[0x76CE].lo() && (new Date()).getMilliseconds() % 500 > 250
? "<u>&#" + (c < 32 || c > 127 ? 0xB7 : c == 127 ? 0x2588 : c) + ";</u>"
: "&#" + (c < 32 || c > 127 ? 0xB7 : c == 127 ? 0x2588 : c) + ";") + "</span>";
document.getElementById("Screen").innerHTML = row.join("<br />");//ram.Chr(0x76D0, 78, 30, (new Date()).getMilliseconds() % 500 > 250 ? ram[0x76CF] + ram[0x76CE] * 78 : -1);//row.join("<br />");
}
c = core.watch.iAdjust, i = 1;
document.getElementById("state").innerHTML = [ "FPS: IPC: IPS: ".replace(/([A-Z]+)/g, function(str, tag) { return ++ i && c -- ? tag : "<u>" + (s = tag) + "</u>"; }),
(" " + core.trace.flash).substr(-2) + " "
+ (" " + core.trace.scale).substr(-6) + " "
+ (" " + core.trace.clock).substr(-4)
].join("\r\n");
core.watch.nAdjust = i,
core.watch.sAdjust = s;
if(core.trace.active)
core.watch.dirty = 7;
if(core.watch.dirty > 0)
-- core.watch.dirty,
core.disassm();
if(core.trace.stamps[0] >= 0) {
i = Math.floor((core.trace.stamps[1] - core.trace.stamps[0]) / 1000);
document.getElementById("Context").innerText = core.CR(0).Hex(2) + "#" + ("0" + Math.floor(i / 60)).substr(-2) + ":" + ("0" + (i % 60)).substr(-2);
}
//core.watch.active = core.watch.active.toUpperCase();
//core.disassm();
//document.getElementById("Dumper").innerHTML = this.state.isHalt || !this.state.isRun || this.state.scale == 1 || this.state.isHint ? this.r.ex.Dump() : "";
}
var x80 =
function(description) {
var _CPU_ID_ = "x80-CPU";
var preset = {
instructions :"pop",
}
function AL() {
console.log("AL " + preset.instructions);
}
function step() {
AL();
setTimeout(this.step, 1250);
}
this.step = step;
}
var Switches = {
"ALT+1|11+": function() {cpu.watch.active = cpu.watch.active == "1" ? "0" : "1"; cpu.command_set(+cpu.watch.active);},
"ALT+2|22+": function() {cpu.watch.active = cpu.watch.active == "2" ? "0" : "2"; cpu.command_set(+cpu.watch.active);},
"ALT+3|33+": function() {cpu.watch.active = cpu.watch.active == "3" ? "0" : "3"; cpu.command_set(+cpu.watch.active);},
"ALT+4|44+": function() {cpu.watch.active = cpu.watch.active == "4" ? "0" : "4"; cpu.command_set(+cpu.watch.active);},
"ALT+5|55+": function() {cpu.watch.active = cpu.watch.active == "5" ? "0" : "5"; cpu.command_set(+cpu.watch.active);},
"ALT+6|66+": function() {cpu.watch.active = cpu.watch.active == "6" ? "0" : "6"; cpu.command_set(+cpu.watch.active);},
"ALT+7|77+": function() {cpu.watch.active = cpu.watch.active == "7" ? "0" : "7"; cpu.command_set(+cpu.watch.active);},
"ALT+8|00+": function() {cpu.watch.active = cpu.watch.active == "8" ? "0" : "8"; cpu.command_set(+cpu.watch.active);},
"ALT+L|Loop+": function() {cpu.command_set(parseInt(cpu.watch.active) | 0x20);},
"ALT+W|Wait+": function() {cpu.command_set(parseInt(cpu.watch.active) | 0x30);},
"ALT+A|Assm": function() {document.getElementById("Assm").style.visibility = document.getElementById("Assm").style.visibility == "hidden" ? "visible" : "hidden"},
"ALT+B|Buffer": function() {},
"ALT+C|Context":function() {cpu.command_set(parseInt(cpu.watch.active) | 0x40);},
"ALT+D|Deprive":function() {cpu.command_set(parseInt(cpu.watch.active) | 0x50);},
"ALT+E|Enlist": function() {cpu.command_set(parseInt(cpu.watch.active) | 0x0E);},
"ALT+F|Forcing":function() {cpu.command_set(parseInt(cpu.watch.active) | 0x0F);},
};
//A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
function main() {
/* t = document.createElement("pre");
i = 256*8;
for($D = 0x00; i --; ++ $D) {
$X = 0x07 & ($D >> 0),
$I = 0x01 & ($D >> 3),
$Y = 0x07 & ($D >> 4),
$J = 0x01 & ($D >> 7),
$Z = 0x07 & ($D >> 8),
$K = 0x01 & ($D >> 11),
$L = 0x07 & ($D >> 12),
$M = $J ? ($Y < 4 ? $Y : !$I ? 4 : 4 | [0, 0, 1, 3, 3, 3, 2, 2][$X])
: ($X == $Y ? $Y == $Z ? 7 : $Y > $Z ? 3 : 0 : $X < $Y ? 1 : 2);
t.innerText += $M + (($D & 15) == 15 ? ($D & 255) == 255 ? "\r\n\r\n" : "\r\n" : " ");
}
document.body.appendChild(t);
return;//*/
var i, hClear = setTimeout("window.location.reload()", 150000);
var Selector = document.getElementById("Selector");
var hFiles = document.getElementsByTagName("pre");
cpu = new X80(document.getElementById("Schema_x80").innerText);
cpu.interface({
instructions :document.getElementById("Instructions"),
disassembly :document.getElementById("Disassembly"),
registers :document.getElementById("Registers"),
address :document.getElementById("Address"),
mnemonic :document.getElementById("Mnemonic"),
remark :document.getElementById("Remark"),
context :document.getElementById("Context")
});
document.getElementById("Prelude").style.display = "none";
document.getElementById("Terminal").style.display = "block";
if(i = window.location.href.match(/instructions([1-7])?/)) {
cpu.command_set(document.getElementById("commands"));
cpu.command_set(isFinite(i[1]) ? parseInt(i[1]) : 0, true);
return clearTimeout(hClear);
}
for(var file, i = 0; i < hFiles.length; ++ i) {
file = hFiles[i];
if(file.id.substr(0, 5) == "FILE:") {
Selector.add(
new Option(file.id.substr(5), Files.length),
null
);
cpu.preset.files.push({
name :file.id.substr(5),
text :file.innerText,
code :{
name :"",
begin :65535,
end :0,
bin :[]
}
});
}
}
var Triggers = document.getElementById("Triggers");
//for(var i = 0, btn, spn; i < 16; ++ i) {
var i = 0;
/* for(var id in Switches) {
spn = document.createElement("span");
spn.innerText = " ".Mul(i ++ ? 8 : 6);
btn = document.createElement("button");
btn.style.position = "absolute";
btn.onclick = Switches[id];
id = id.split("|");
btn.innerText = id[1];
btn.title = id[0];
btn.style.zIndex = 0;
btn.accessKey = id[0].substr(-1);
Triggers.appendChild(spn);
Triggers.appendChild(btn);
}*/
Selector.onchange = function(e) {
document.getElementById("Assm").value = cpu.preset.files[this.selectedIndex].text;
if(cpu.preset.files[this.selectedIndex].code.length > 0)
document.getElementById("Action").innerText = "Save It";
else
document.getElementById("Action").innerText = "Compile";
}
document.getElementById("Action").onclick = function(e) {
var i = document.getElementById("Selector").selectedIndex;
if(cpu.preset.files[i].code.bin.length > 0) {
this.innerText = "Compiling...";
cpu.preset.files[i].code = cpu.assembly(cpu.preset.files[i].text, true);
this.innerText = "Save It";
} else {
cpu.preset.files[i].code = cpu.assembly(cpu.preset.files[i].text);
this.innerText = "Compile";
cpu.preset.files[i].text = document.getElementById("Assm").value;
cpu.preset.files[i].bin.length = 0;
}
}
cpu.ram([]);
cpu.reset(0xFF00);
cnv = document.getElementById("Display");
cnv.width = 6 * 80;
cnv.height = 8 * 30;
cpu.watch.c2d = cnv.getContext("2d");
cpu.display(display);
cpu.command_set(document.getElementById("commands"));
cpu.disassm();
document.getElementById("KeyBoard").focus();
cpu.command_set(4, false);
setTimeout("cpu.assembly(document.getElementById('BootSection').innerText), cpu.reset(0xFF00)", 1);
clearTimeout(hClear);
/////////////////////////////////
document.getElementById("Address").onkeydown = function(e) {
var pointer, i, codes, n = -1;
var regs = "ALAHBLBHCLCHDLDHAXBXCXDXSPBPSIDIIPJP".match(/../g);
var re = new RegExp("((" + regs.join("|") + ")[1-7]?)" + "|" + "([0-9A-F]+)" + "|" + "(<<|--|>>|\\+\\+)", "g");
switch(e.keyCode) {
case VK.UP:
cpu.trace.pointer -= 1;
window.event.returnValue = false;
cpu.disassm();
break;
case VK.DOWN:
cpu.trace.pointer += 1;
window.event.returnValue = false;
cpu.disassm();
break;
case VK.RETURN:
pointer = -1;
codes = this.value.match(re);
codes.forEach(function(code) {
if(("<<-->>++".indexOf(code) & 1) == 0)
switch(code) {
case "--":
cpu.ctx[cpu.CR()][0xFFFF & pointer] = (cpu.ctx[cpu.CR()][0xFFFF & pointer] - 1) & 0xFF;
if(pointer >= 0x100A0 && pointer <= 0x100FF && (pointer & 0x08) == 0 && cpu.ctx[cpu.CR()][0xFFFF & pointer] == 0xFF && n >= 8)
cpu.ctx[cpu.CR()][0xFFFF & (pointer + 8)] = (cpu.ctx[cpu.CR()][0xFFFF & (pointer + 8)] - 1) & 0xFF;
pointer ++;
break;
case "++":
cpu.ctx[cpu.CR()][0xFFFF & pointer] = (cpu.ctx[cpu.CR()][0xFFFF & pointer] + 1) & 0xFF;
if(pointer >= 0x100A0 && pointer <= 0x100FF && (pointer & 0x08) == 0 && cpu.ctx[cpu.CR()][0xFFFF & pointer] == 0x00 && n >= 8)
cpu.ctx[cpu.CR()][0xFFFF & (pointer + 8)] = (cpu.ctx[cpu.CR()][0xFFFF & (pointer + 8)] + 1) & 0xFF;
pointer ++;
break;
}
else
if((n = regs.join("").indexOf(code.substr(0, 2)) >> 1) >= 0)
pointer = 0x10000 + (n < 8 ? 0xA0 + n * 8 : n < 12 ? 0xA0 + (n - 8) * 16 : 0xE0 + (n - 12) * 2 + (n < 12 ? 0 : 8)) + parseInt("0" + code.charAt(2)), console.log("n:" + n + "/" + pointer.Hex(-5));
else
if(code.length == 1)
pointer = 0x10100 + parseInt(code, 16);
else
if(code.length == 4) {
n = parseInt(code, 16);
if(pointer < 0)
cpu.trace.pointer = pointer = parseInt(code, 16);
else
if(pointer <= 0xFFFE)
cpu.ram[pointer ++] = n.lo(),
cpu.ram[pointer ++] = n.hi();
else
if(pointer <= 0x1009F)
cpu.ctx[cpu.CR()][0xFFFF & pointer ++] = n.lo(),
cpu.ctx[cpu.CR()][0xFFFF & pointer ++] = n.hi();
else
if(pointer <= 0x100FF)
cpu.ctx[cpu.CR()][0xFFFF & pointer] = n.lo(),
cpu.ctx[cpu.CR()][0xFFFF & (8 + pointer ++)] = n.hi();
} else
if(code.length == 2)
if(pointer < 0)
pointer = 0x10000 + parseInt(code, 16);
else
if(pointer < 0x10000)
cpu.ram(pointer ++, parseInt(code, 16));
else
if(pointer < 0x10100)
cpu.ctx[cpu.CR()][0xFFFF & pointer ++] = parseInt(code, 16);
else
if(pointer < 0x10108)
cpu.CR(0x0007 & pointer ++, parseInt(code, 16));
});
cpu.disassm();
}
};
document.getElementById("Mnemonic").onkeydown = function(e) {
switch(e.keyCode) {
case VK.UP:
cpu.trace.pointer -= 1;
window.event.returnValue = false;
cpu.watch.active = cpu.watch.active.toLowerCase();
cpu.disassm();
break;
case VK.DOWN:
cpu.trace.pointer += 1;
window.event.returnValue = false;
cpu.watch.active = cpu.watch.active.toLowerCase();
cpu.disassm();
break;
case VK.RETURN:
window.event.returnValue = false;
cpu.watch.active = cpu.watch.active.toLowerCase();
cpu.assembly("\tORG\t" + parseInt(document.getElementById("Address").value, 16).Hex(-4) + "\r\n\t" + this.value);
cpu.disassm();
break;
default:
cpu.watch.active = cpu.watch.active.toUpperCase();
}
};
document.getElementById("Remark").onkeydown = function(e) {
switch(e.keyCode) {
case VK.TAB:
window.event.returnValue = false;
document.getElementById("Address").focus();
break;
}
}
document.getElementById("KeyBoard").onkeydown = function(e) {
window.event.returnValue = false;
switch(e.keyCode) {
case VK.TAB: this.value += "`I"; break;
case VK.ESC: this.value += "`["; break;
case VK.BACK_SPACE: this.value += "`{"; break;
case VK.LEFT: this.value += "`H"; break;
case VK.RETURN: this.value += "`M"; break;
default:
window.event.returnValue = true;
}
}
document.getElementById("KeyBoard").onkeyup = function(e) {
window.event.returnValue = false;
switch(e.keyCode) {
case VK.TAB:
case VK.ESC:
case VK.BACK_SPACE:
case VK.LEFT:
case VK.RETURN: break;
default:
window.event.returnValue = true;
}
}
document.body.onkeydown = function(e) {
//document.title = e.keyCode;
switch(e.keyCode) {
/* case VK.ESC: // ESC
cpu.iox[0xFD].data(0x1B); break;
cpu.preset.command_cycles = -Math.abs(cpu.preset.command_cycles), cpu.do_tick(true); break;
case VK.LEFT: // <--
cpu.iox[0xFD].data(0x08); break;
case VK.UP: // //\
cpu.iox[0xFD].data(0x19); break;
case VK.RIGHT: // -->
cpu.iox[0xFD].data(0x18); break;
case VK.DOWN: // \//
cpu.iox[0xFD].data(0x1A); break;
case VK.BACK_SPACE: // \//
cpu.iox[0xFD].data(0x7F); break;
*/ ////////////////////////////////////
case VK.BREAK: // Break-point
cpu.trace.halt[Number().hl(cpu.CTX(0xF8), cpu.CTX(0xF0))] ^= true;
if(e.shiftKey)
cpu.trace.halt[(Number().hl(cpu.CTX(0xF8), cpu.CTX(0xF0)) + 1) & 0xFFFF] = false;
cpu.disassm();
break;
case VK.F1: // Step
if(e.ctrlKey) { // Start cycle
/*var ip = cpu.r.ip;
cpu.do_tick(true);
cpu.r.qp = ip;
cpu.trace.active = false;*/
} else
if(e.shiftKey)
cpu.step(),
cpu.trace.active = true;
else
if(e.altKey)
cpu.state.isHint ^= true;
else
cpu.trace.step = true;//cpu.do_tick(true);
// cpu.disassm();
window.event.returnValue = false;
break;
case VK.F7:
cpu.watch.iAdjust = (cpu.watch.iAdjust + 1) % cpu.watch.nAdjust;
window.event.returnValue = false;
break;
case VK.F6: // IP --
switch(cpu.watch.sAdjust) {
case "FPS":
cpu.trace.flash -= cpu.trace.flash > 1 ? 1 : 0;
break;
case "IPS":
cpu.trace.clock >>= cpu.trace.clock & 1 ? 0 : 1;
break;
case "IPC":
cpu.trace.scale >>= cpu.trace.scale & 1 ? 0 : 1;
break;
default:
var txt = document.getElementById("Logger").value.split(/\r?\n/).pop().toUpperCase().split(/[\s\t]+/);
cpu.do_regs(txt[0], -1);
cpu.trace.active = true;
}
cpu.disassm();
break;
case VK.F8: // IP ++
switch(cpu.watch.sAdjust) {
case "FPS":
cpu.trace.flash += cpu.trace.flash < 50 ? 1 : 0;
break;
case "IPS":
cpu.trace.clock <<= cpu.trace.clock < 1000 ? 1 : 0;
break;
case "IPC":
cpu.trace.scale <<= cpu.trace.scale < 500000 ? 1 : 0;
break;
default:
var txt = document.getElementById("Assm").value.split(/\r?\n/).pop().toUpperCase().split(/[\s\t]+/);
cpu.do_regs(txt[0], +1);
cpu.trace.active = true;
}
cpu.disassm();
break;
case VK.F5: // Assembly/Reset
window.event.returnValue = false;
if(e.ctrlKey) // Reset
cpu.JP(0, 0xF800),
cpu.JP(1, 0xE000),
cpu.reset(0xFF00);
else // Assembly
cpu.trace.active = true,
cpu.assembly(document.getElementById("Assm").value);
cpu.disassm();
break;
case VK.F4: // Start/Break emulation
if(e.shiftKey)
cpu.trace.active = false;
else
cpu.trace.active = !cpu.trace.active;
cpu.disassm();
break;
case VK.F3:
if(e.ctrlKey)
cpu.stack(cpu.r.ip);
else
if(e.shiftKey)
cpu.r.ip = cpu.stack();
cpu.disassm();
window.event.returnValue = false;
break;
case VK.RETURN:
if(e.shiftKey);
break;
default:
if(e.ctrlKey && e.keyCode > 48 && e.keyCode <= 56)
cpu.CR(0, e.keyCode & 7);
break;if(e.altKey && e.keyCode >= 48 && e.keyCode <= 55)
cpu.command_set(e.keyCode & 7, false);
//cpu.iox[0xFD].data(e.keyCode);
}
}
document.body.onkeyup = function(e){
switch(e.keyCode) {
case VK.F1: // Help
case VK.F3: // Push/Pop
case VK.F5: // Assembly
window.event.returnValue = false;
break;
default:
//cpu.iox[0xFD].data(0xFF); break;
}
}
document.getElementById("Assm").onkeydown = function(e) {
if(e.keyCode == 13) {
if(e.ctrlKey) {
var txt = document.getElementById("Assm").value.split(/\r?\n/).pop().toUpperCase().split(/[\s\t]+/);
cpu.do_regs(txt[0], txt[1]);
cpu.disassm();
} else
if(e.shiftKey) {
var keybrd = document.getElementById("Assm"),
start = keybrd.selectionStart,
ascii;
if(keybrd.value.length > start) {
//ascii = keybrd.value.charAt(start).toUpperCase();
//cpu.iox[0xFD].data(
document.getElementById("KeyBoard").value = keybrd.value.substr(start).replace(/[Ёё]/igm, "Е").replace(/[Ъъ]/igm, "'").replace(/(`[A-Z@\[\\\]\^_\x01-\x1F]|.)/gm,
function(str, ascii) {
// alert(str + '...........'+ascii);
ascii = ascii.toUpperCase();
if(ascii.length == 2)
return "`" + ascii.charAt(1);
var koi7ru = "ЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ",
data = koi7ru.indexOf(ascii);
if(data < 0)
return ascii.charCodeAt(0) < 0x7F && ascii.charCodeAt(0) >= 32 ? ascii.toUpperCase() : ascii.charCodeAt(0) < 32 ? "`" + String.fromCharCode(ascii.charCodeAt(0) + 64) : "";
return String.fromCharCode(96 + data);
}
);
}/*
alert("1$"+cpu.iox[0xFD].text);
alert("1#"+cpu.iox[0xFD].data());
alert("1@"+cpu.port(0xFD));
alert("2$"+cpu.iox[0xFD].text);
alert("2#"+cpu.iox[0xFD].data());
alert("2@"+cpu.port(0xFD));
alert("3$"+cpu.iox[0xFD].text);
alert("3#"+cpu.iox[0xFD].data());
alert("3@"+cpu.port(0xFD));*/
window.event.returnValue = false;
}
} else
if(e.keyCode == 9) {
var start = this.selectionStart, end = this.selectionEnd;
this.value = this.value.substr(0, start) + "\t" + this.value.substr(end),
this.selectionStart = start + 1,
this.selectionEnd = start + 1,
window.event.returnValue = false;
}
}
document.getElementById("Assm").onkeyup = function(e) {
if(e.keyCode == 9) {
window.event.returnValue = false;
}
}
return;
//return;
/*var part = "F800 JMP 0xF701"
.split(/\s|\t/),
arg_nnIB,
ip = parseInt(part[0], 16),
ipx = ip*0,
instr = part[1],
regs = part[2],
args = [],
ins = { "$+IB": {},
"$+1IB": {},
"$+2IB": {},
"$+3IB": {},
"$+4IB": {},
"$+5IB": {},
"$+6IB": {},
"$+7IB": {}, };
arg_nnIB = regs.replace(/(0x[0-9A-F]+)|([0-9]+)/gi, function(str, data) { // nnIB
var bin0 = parseInt(data);
var tag0 = regs.replace(/\+(0x[0-9A-F]+|[0-9]+)/, "+IB");
var bin1 = parseInt(data);
var tag1 = bin1.hi().Hex(2) + "IB";
var bin2 = parseInt(data) - (ip + 2) - ipx;
// bin2 -= (bin2 & 32768) * 2;
var tag2 = "$+IB";
var bin3 = parseInt(data) - (ip + 3) - ipx;
//bin3 += (bin3 & 32768) * 2;
//bin3 += (bin3 < -128 ? +(bin3 & 0x80) * 2 : bin3 >= 128 ? +(bin3 & 0x80) * 2 : 0);
var bin3a = bin3 + (bin3 < -128 ? +(bin3 & 0x80) * 2 : bin3 >= 128 ? +(bin3 & 0x80) * 2 : 0);
var tag3 = "$+" + ((bin3a >> 8) & 7) + "IB";
console.log([ip.Hex(4), "bin0", instr, str, bin0.Hex(4), bin0, "?" + ins + "?" + tag0].join(" "));
console.log([ip.Hex(4), "bin1", instr, str, bin1.Hex(4), bin1, "?" + ins + "?" + tag1].join(" "));
console.log([ip.Hex(4), "bin2", instr, str, bin2.Hex(4), bin2, "?" + ins + "?" + tag2].join(" "));
console.log([ip.Hex(4), "bin3", instr, str, bin3.Hex(4), bin3, "?" + ins + "?" + tag3].join(" "));
console.log([ip.Hex(4), "bin3a", instr, str, bin3a.Hex(4), bin3a, "?" + ins + "?" + tag3].join(" "));
if(ins) {
if(tag0 in ins) {
console.log("0");
return args.push(bin0) ? "IB" : "IB";
}
if(tag1 in ins) {
console.log("1");
return args.push(bin1) ? tag1 : tag1;
}
if(bin2 >= -128 && bin2 < 128 && (tag2 in ins)) {
console.log("2");
return args.push(bin2.lo()) ? tag2 : tag2;
}
if(((bin3 >= -1024 && bin3 < -128) || (bin3 >= 128 && bin3 <= 895)) && (tag3 in ins)) {//console.log("bin3="+bin3+"");
console.log("3");
return args.push(bin3.lo()) ? tag3 : tag3; //}//else console.log("bin3="+bin3+" tag3=" + tag3 + "/" + (tag3 in ins));
}
if("IB" in ins) {
console.log("4");
return args.push(bin1) ? "IB" : "IB";
}
if(part[4] && (regs.split(",")[0] + ",IB") in ins) {
console.log("5");
return (code = ins[part[3] + ",IB"]) && args.push(bin1) ? "" : "";
}
if("" in ins)
return "";
}
args.push(bin1);
//console.log([ip.Hex(4), "nnIB//", instr, str, bin1.Hex(4), bin1].join(" "));
return "";
});
console.log(arg_nnIB);
console.log(args[0].Hex(4) + "=" + (args[0] - (args[0] & 32768) * 2));
return;*/
var url = window.location.href, match = 0, i;
Source = document.getElementById("Listing").innerText;
cpu.preset.command_speed = +((match = url.match(/speed=([^&]+)/)) ? match[1] : .1*0+500);
cpu.preset.command_cycles = +((match = url.match(/cycle=([^&]+)/)) ? match[1] : 1);
cpu.preset.command_reset = +((match = url.match(/reset=([^&]+)/)) ? match[1] : 1);
cpu.init(document.getElementById("Schema").innerText);
if(url.match(/instructions/)) {
var body = document.createElement("body");
cpu.preset.command_table = document.createElement("pre");
var span = document.createElement("span");
cpu.preset.command_table.id = "commands";
span.id = "expression";
body.appendChild(cpu.preset.command_table);
body.appendChild(span);
body.style.backgroundColor = "steelblue";
document.body = body;
cpu.command_set(0, true);
return;
}
for(i = 0; i < 264; ++ i)
cpu.preset.regs.asx[i] = 0,
cpu.preset.regs.atx[i] = 0;
for(i = 0x0000; i <= 0xFFFF; ++ i)
cpu.halt[i] = false;
for(i = 0x0000; i <= 0x00FF; ++ i) {
if(!isFinite(cpu.iox[i]) && !cpu.iox[i])
cpu.iox[i] = 0x80;
}
//alert(cpu.iox[0xD0].data().Hex(2));
for(i = 0x76CE; i <= 0x7FF3; ++ i)
cpu.ram[i] = Math.random() * 256 & 0;
cpu.iox[0xF1].data(document.getElementById("Files").innerText);
cpu.do_reset();
i = 0;
document.getElementById("Listing").innerText.replace(/\s*;.*/gm, "").replace(/([0-9A-F]{4})(?:\:)|([0-9A-F]{2})(?:\s)/gm, function(str, p1, p2) {
if(p1)
i = parseInt(p1, 16);
if(p2)
cpu.ram[i ++] = parseInt(p2, 16);
return "_";
});
cpu.preset.command_table = document.getElementById("commands");
cpu.command_set(Math.floor((new Date()).getSeconds() / 3) % 11 * 0);
cpu.display();
cpu.disassm();
////////////////////////////////////////
setTimeout(function() {
// cpu.assembly(Source);
document.getElementById("Logger").value = Source;//\
" ORG 0xF780\
\rgoe: NOP\
\r ORG 0xF800\
\rgo: NOP\
\r JC $-1\
\r NOP\
\r JMP goal\
\r NOP\
\r DW 0xB977\
\r DB 0x01\
\r NOP\
\r JS goe\
\r NOP\
\r ORG 0xF903\
\rgoal: NOP\
\r!IP 0x100";
cpu.assembly(document.getElementById("Logger").value);
cpu.disassm();
document.getElementById("Logger").focus();
//cpu.state.hTimer = setInterval("cpu.do_tick()", 1500);
//AudioInit();
}, 1);
//cpu.assembly(" ORG 0xF800\r\nStart:\r\n INC BX_DX\r\n POP AX_CX\r\n");
document.body.onkeypress = function(e) {
cpu.iox[0xFD].data(e.keyCode);//e.charCode;
document.title+=" _"+e.keyCode.Hex(4);
// window.event.returnValue = false;
}
document.body.onkeyup = function(e){
switch(e.keyCode) {
case VK.F1: // Help
case VK.F3: // Push/Pop
case VK.F5: // Assembly
window.event.returnValue = false;
break;
default:
//cpu.iox[0xFD].data(0xFF); break;
}
document.title+=" ^"+e.keyCode.Hex(4);
}
}
</script>
</head>
<body onload='setTimeout(main,1000)'>
<var id=Schema_x80>
<!--
$A:Address (-2048..2047)
$B:Byte (0..255)
$C:Character(-128..127)
$D:Decoder (0..255)
$K:Keep-mode (00..07) .0:Normal, .1:Express, .2:Loop, .3:Wait, 4:System...
$X:Low Nibble (00..07)
$Y:High Nibble(00..07)
$Z:Zip-prefix (00..07)
+---------------=> $L:Lock-mask
| +------------=> $K:Keep code
| | +---------=> $Z:PREFIX #Z
| | | +-------=> $J:
| | | | +-----=> $Y:
| | | | | +---=> $I:
| | | | | | +-=> $X:
| | | | | | |
/|\/|\/|\|/|\|/|\
LLLKKKZZZJYYYIXXX_
XXX11100000000000C MOV [0],ACC :
XXX1XX00000000000C HLT 0 :
XXXXXX00000000000C HLT :
000XXX0000XXX0XXX_ PREFIX R$X/P$Y :
A:ALU
B:Branch
C:Control
D:Dubbed register pair
E:Stack
F:Flip-flop move
$D<128
000:
001: $X < $Y
010: $X > $Y
011: $X = $Y
100: $Z
101: $Z < $X = $Y
110; $Z > $X = $Y
111: $Z = $X = $Y
x>y?1
y>x?2
x=y?x>z?3:7
7 1 1 1 3 1 1 1
2 5 1 1 1 1 1 1
2 2 5 1 1 1 1 1
2 2 2 5 1 1 1 1
3 2 2 2 7 1 1 1
2 2 2 2 2 6 1 1
2 2 2 2 2 2 6 1
2 2 2 2 2 2 2 6
- - - - - - - - - - - - - - - -
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4 5 7 7 7 6 6
4 4 4 4 4 4 4 4 4 4 5 7 7 7 6 6
4 4 4 4 4 4 4 4 4 4 5 7 7 7 6 6
4 4 4 4 4 4 4 4 4 4 5 7 7 7 6 6
$M = $J ? ($Y < 4 ? $Y : !$I ? 4 : 4 | [0, 0, 1, 3, 3, 3, 2, 2][$X])
: (!$Y && ($X == $Z)) || (!$X && ($Y == $Z)) ? 3
: ($X == $Y ? $Y == $Z ? 7 : $Y > $Z ? 5 : 6 : $X < $Y ? 1 : 2)
ZF=0 - BF:JF - Fictional
ZF=1 - BE:JE - Equivalent
CF=0 - BD:JD - Discarded
CF=1 - BC:JC - Carrier
SF=0 - BB:JB - Bigger
SF=1 - BA:JA - Among
PF=1 - B0:JO - Odd parity
MMMLLLZZZZJYYYIXXX_ --
0XXXXX100000000000C HLT :return 0 //HALT the Application
1XXXXX10000XXX0XXX_ PREFIX R$X/P$Y :return 0 //Prefix
111X00XXXX0XXX0XXXC HLT P$Z/$Z :FH($Z | 8) //Hold P$Z!/$Z
1XXX00XXXX00000000C HLT R$Z :FH($Z | 0) //Hold R$Z!
101XXX0XXX0XXX0XXXF XCHG R$Z,R$Y :$1=R$Z(),R$Z(R$Y()),R$Y($1) //Exchange R$Z! and R$Y!
110XXX0XXX0XXX0XXXF XCHG P$Z,P$Y :$1=P$Z(),P$Z(P$Y()),P$Y($1) //Exchange P$Z! and P$Y!
XXXXXX1XXX0XXX0XXXF MOV R$X,R$Y :R$X(R$Y()) //Move R$Y! to R$X!
XXXX000XXX11101011C LOOP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z bits
XXXX000XXX11101100C LOOP R$Z :FH($Z), FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z counter
XXXX000XXX11101101C LOOP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x09) //Forcing next operation by $Z times
XXXXXXXXXXXXXXXXXXX Y$Y_X$X ($M) :0 //reserved
<!--
MMM_LLL_ZZZZ_JYYY_IXXX_ -->
0XX_0XX_0000_0000_0000C HLT :(CR(0,CR(0)&255)),$EV = DO_ACCLAIM //HALT
XXX_1XX_0000_0000_0000_ PREFIX SUPER :return 0 //Super Prefix
1XX_XXX_0000_0XXX_0XXX_ PREFIX R$X/P$Y :return 0 //Prefix
XXX_X00_0XXX_0000_0000C HLT R$Z :FH($Z | 0) //Hold R$Z!
111_X00_0XXX_0XXX_0XXXC HLT P$Z/$Z :FH($Z | 8) //Hold P$Z!/$Z
XXX_000_1000_0000_0000X .$Y$X :return 0 //
XXX_X00_1000_0XXX_0000C MOV [0],R$Y :CR(0,R$Y())+ FL(0),$IE=0 //CR[$Y] = ACC
XXX_X10_0100_0000_0XXXF MOV R$X,[$Y] :R$X(CR($Y))+ FL(0),$IE=0 //R$X = CR[$Z]
1XX_X10_0100_0XXX_0XXXF MOV R$X,[R$Y] :R$X(CTX(R$Y()))+ FL(0) //Context
XXX_X10_0100_0XXX_0XXXF MOV [R$X],R$Y :CTX(R$X(), R$Y())+ FL(0),$IE=0 //Context
101_X00_0XXX_0XXX_0XXXF XCHG R$Z,R$Y :$1=R$Z(),R$Z(R$Y()),R$Y($1) //Exchange R$Z! and R$Y!
110_X00_0XXX_0XXX_0XXXF XCHG P$Z,P$Y :$1=P$Z(),P$Z(P$Y()),P$Y($1) //Exchange P$Z! and P$Y!
XXXX1XXXXX0XXX0000X .Y$Y :0 //reserved
XXXX1XXXXX00000XXXX .X$X :0 //reserved
1XX_X11_X100_0XXX_0XXXC IN R$X :R$X(PORT(R$X())) //Input from port
XXX_X11_X100_0XXX_0XXXC OUT R$X,R$Y :PORT(R$X(),R$Y()) //Output to port
001X1XX0000XXX0000F .Y$Y R$X;[R$Y] :0 //reserved
010X1XX00000000XXXF .X$X [R$X];R$Y :0 //reserved
XXXX01X10000000100C MOV :$CTX.splice(0xAF, 1), $CTX.splice(0xA9, 0, FH()),$IE=0 //Set argument
XXXX01X1000XXX0000C MOV $Y :FH($CTX[0xA8 + $Y]),$IE=0 //Get argument
XXX_XXX_0100_0XXX_1XXXA BIT R$X,$Y :$1=FL(),FL($1&0xFE)|((R$X()>>$Y)&1),R$X(~(~R$X()|(1<<$Y)))/*>*/ //Bit exchange
0XX_X00_0000_0XXX_0XXXF MOV R$X,R$Y :R$X(R$Y()) //Move R$Y! to R$X!
XXX_X00_0XXX_0000_0XXXF MOV R$X,[$Z] :R$X(CR($Z)) //Move [$Z] to R$X!
XXX_X00_0XXX_0XXX_0000F MOV [$Z],R$Y :CR($Z,R$Y()) //Move R$X! to [$Z]
0XX_X00_0100_0XXX_0XXXF MOV P$X,P$Y :P$X(P$Y()) //Move P$Y! vector to P$X!
XXX_X10_0100_0XXX_1XXXX -- Z$Y :$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi()) //ALU$X! with Z$Y! and retained
XXX_XXX_0XXX_0XXX_1XXXA ALU$X Z$Z,R$Y :$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and R$Y!
XXX_XXX_0100_1010_1XXXA ADC P$X,IB :$1=ALU$X(DROP(FH()),$B),ACC($1),FL($1.hi()) //ALU$X! with retained and immediate
XXX_XXX_0XXX_1010_1XXXA ALU$X Z$Z,IB :$1=ALU$X(Z$Z(),$B),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and byte
XXX_X00_0XXX_100X_XXXXE PUSH $VIB :HEAP(0x$V00 + $B) //Push immediate data into stack
XXX_XXX_0000_1110_1110C NOP :$Z //Hollow operation
XXX_XXX_0XXX_1110_1110C NOP $Z :$Z //Hollow operation
XXX_X0X_0000_1111_1110B DBG 0 :HEAP($IP)+IP(JP(10>$T?0:1)) ;$IF=true //Interruption
XXX_X0X_0000_1111_1111B DBG :HEAP($IP)+IP(JP(10>$T?0:1)) ;$IF=true //Interruption
111_XXX_0000_1100_1XXXD INC Q$X :Q$X(Q$X()+1) //Increment Q$X!
111_XXX_0000_1101_1XXXD DEC Q$X :Q$X(Q$X()-1) //Decrement Q$X!
XXX_X00_0000_1100_1111A CMC :FL(FL() ^ 2) //Complement carry flag
-XXX_XXX_0XXX_1100_1110X Y$Y_X$X ($M) :0 //reserved
-XXX_XXX_0XXX_1100_1110D ADC BX,T$Z :$1=BX()+T$Z()+(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Addition register pair with carry
111_XXX_0XXX_1100_1XXXD ADD Q$X,P$Z :$1=Q$X()+P$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Addition register pair
-XXX_XXX_0XXX_1101_1110X Y$Y_X$X ($M) :0 //reserved
-XXX_XXX_0XXX_1101_1110D SBB BX,T$Z :$1=BX()-T$Z()-(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Subtraction register pair with borrow
111_XXX_0XXX_1101_1XXXD SUB Q$X,P$Z :$1=Q$X()-P$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Subtraction register pair
XXXX00X00011001010A XCHG :$1=ACC(); for($2=0,$0=0;8>$0;++$0,$1>>=1) $2=($2<<1)+($1&1); ACC($2)>0 //Exchange retained bits by mirror
XXXX00XXXX11001010A XCHG P$Z :$1=DST(),DST(P$Z()),P$Z($1) //Exchange P$Z! with retained pair
XXXX00XXXX11001111A XCHG R$Z :$1=ACC(),ACC(R$Z()),R$Z($1) //Exchange R$Z! with retained register
XXX_XXX_0000_1101_1110C DOZ :CND7?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0 //Execute next operation if CF
XXX_XXX_0000_1101_1111C DONZ :CND6?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0 //Execute next operation if no CF
XXX_XXX_0XXX_1101_111XX --- :return 0 //
XXX_XXX_0100_110X_1XXXX --- :$1=ACC(ALU$W(ACC())),FL($1.hi()) //ALU$W! with retained
XXX_XXX_0XXX_1100_1110A ALU1F Z$Z :$1=Z$Z(ALU1F(Z$Z())),FL($1.hi()) //ALU$W! with Z$Z!
XXX_XXX_0XXX_110X_1XXXA ALU$W Z$Z :$1=Z$Z(ALU$W(Z$Z())),FL($1.hi()) //ALU$W! with Z$Z!
XXX_X00_0000_1010_0XXXF MOV R$X,IB :R$X($B) //Move immediate data into R$X!
XXXX0X10001011000XC BCND$X :CND$X?0:FL((FL() & 0x02) | 0x05) ;$IF=true //Conditional do
XXXX0X00001011000XB BCND$X $+$UIB :CND$X?IP(IP()+$A):0 ;$IF=true //Relative branching if CND$X!
XXX_X00_X100_1011_0000E PUSH $+IB :HEAP(IP()+$A) //Push instruction based relative address
XXX_X0X_O000_1011_0XXXB CCND$X :CND$X?($1=P$Z(),P$Z(DW(SP())), DW(SP(), $1)):HEAP() ;$IF=true //Condition call
XXX_X0X_0000_1011_0XXXB CCND$X $+IB :CND$X?HEAP(IP())+IP(IP()+$A):0 ;$IF=true //Relative call if CND$X!
XXX_XXX_0000_1100_0XXXA INC R$X :$1=ADD(R$X(),1),R$X($1),FL($1.hi()) //Increment R$X!
XXX_XXX_0000_1101_0XXXA DEC R$X :$1=SUB(R$X(),1),R$X($1),FL($1.hi()) //Decrement R$X!
XXX_XXX_0XXX_1100_0XXXA ADD P$Z,R$X :$1=(P$Z()+R$X()),P$X($1),FL($1.hi()) //Increment R$X!
XXX_XXX_0XXX_1101_0XXXA SUB P$Z,R$X :$1=(P$Z()+R$X()),P$X($1),FL($1.hi()) //Increment R$X!
XXX_XXX_0XXX_1101_0XXXA DEC R$X :$1=SUB(R$X(),1),R$X($1),FL($1.hi()) //Decrement R$X!
XXX_X00_0XXX_1010_0000E POP [P$Z+IB] :DW(P$Z()+$C,HEAP()) //Pop data into memory indexed by P$Z
XXX_X00_0XXX_1010_0XXXF MOV R$X,[P$Z+IB] :R$X(DB(P$Z()+$C)) //Move memory data by P$Z pointer into R$X
XXX_X00_111X_1011_0000E PUSH [P$Z+IB] :HEAP(DW(P$Z()+$C)) //Push data from memory indexed by P$Z
XXX_X00_0XXX_1011_0000E PUSH [P$Z+IB] :HEAP(DW(P$Z()+$C)) //Push data from memory indexed by P$Z
XXX_X00_0XXX_1011_0XXXF MOV [P$Z+IB],R$X :DB(P$Z()+$C,R$X()) //Move R$X register data into memory by P$Z
XXX_X10_0XXX_1010_0XXXF MOV R$X,[P$Z+ACC+IB]:R$X(DB(P$Z()+ACC()+$C)),FL(0),$IE=0 //Move R$X register data into memory by P$Z
XXX_X10_0XXX_1011_0XXXF MOV [P$Z+ACC+IB],R$X:DB(P$Z()+ACC()+$C,R$X()),FL(0),$IE=0 //Move R$X register data into memory by P$Z
XXX_XXX_X100_1011_1XXXX --- IB :return 0 //Reserved extended code
XXX_X00_X100_1011_1010E LEA +IB :DST(DST()+$B) //Load retained effective address
XXX_X00_X100_1011_1XXXF MOV [U$X],IB :DB(U$X(),$B) //Load immediate data into memory by U$X
XXX_X00_1110_1011_1000C WAIT :FL((FL() & 0x02) | 0x0D),trace.expression=0 //Wait
XXX_X00_1111_1011_1000B RET :IP(HEAP()) //Return
XXX_X0X_0XXX_1011_1000B JMP $+$UIB :IP(IP()+$A) ;$IF=true //Unonditional relative branching
XXXX0X0XXX10111001B CALL $+$UIB :$A==-2?0:HEAP(IP(IP()+$A)) ;$IF=true //Unconditional relative call
XXXX0X1XXX10111XXXC BCND$X :CND$X?0:FL((FL() & 0x02) | 0x05) ;$IF=true //Conditional do
XXXX00100010111001X . :0 //reserved
XXXX00100010111XXXX . :0 //reserved
XXX_XXX_0XXX_1011_1XXXB JCND$X $+$UIB :CND$X?IP(IP()+$A):0 ;$IF=true //Branching if CND$X!
XXX_XXX_1111_1011_1XXXB RCND$X :CND$X?IP(HEAP()):0 //Return if CND$X
1X1_X00_0000_1110_1XXXE PUSH U$X :HEAP(U$X()) //Push U$X! into stack
1X1_X00_0000_1111_1XXXE POP U$X :U$X(HEAP()) //Pop U$X! from stack
XXXX00X10011101110F XCHG [SP] :$1=DST(),DST(DW($2=SP())), DW($2, $1) //Exchange retained pair with stack heap
XXX_X00_XXXX_1110_1111F XCHG P$Z,[SP] :$1=P$Z(),P$Z(DW(SP())), DW(SP(), $1) //Exchange pair P$Z! with stack heap
XXXX00X10011101111E PUSH :HEAP(DST()) //Push retained pair
XXXX00XXXX11101111E PUSH S$Z :HEAP(S$Z()) //Push service S$Z register pair to stack
XXXX00X10011111111E POP :DST(HEAP()) //Pop retained pair
XXXX0XXXXX11111111E POP S$Z :S$Z(HEAP()) ;$IF=true //Pop service S$Z register pair from stack
XXXX00XXXX11101010E PUSH R$Z :DUP($Z) //Dup R$Z register history
XXX_X00_0000_1110_0000C SKIP :FH(1 | 8), FL((FL() & 0x02) | 0x05) //Exclude next operation
XXX_X10_0000_1110_0000C SKIP ACC :FH(1 | 8), FL((FL() & 0x02) | 0x05) //Exclude next operation
XXX_X00_0000_1110_0XXXC LOOP $X :FH($X | 8), FL((FL() & 0x02) | 0x09) //Forcing next operation by $X times
XXX_X00_0000_1110_1000C DOC :CND5?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0 //Execute next operation if CF
XXX_X00_0000_1110_1001C DONC :CND4?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0 //Execute next operation if no CF
XXX_X00_0XXX_1110_1011C LOOP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z bits
XXX_X00_0XXX_1110_1100C LOOP R$Z :FH($Z), FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z counter
XXXX000XXX11101101C LOOP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x09) //Forcing next operation by $Z times
XXXX00XXXX11111010E POP R$Z :DROP($Z) //Drop R$Z register history
XXX_X00_0XXX_1111_1011C SKIP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x05) //Exclude next operations by R$Z bits
XXX_X00_0XXX_1111_1100C SKIP R$Z :FH($Z), FL((FL() & 0x02) | 0x05) //Exclude next operations by R$Z counter
XXX_X00_0XXX_1111_1101C SKIP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x05) //Exclude next operations by $Z times
100X10X0001111XXXXB FLY $T :FLY($T) //Fix the alias
100X10XXXX1111XXXXB FIX $T :FH($Z | 8), FL((FL() & 0x02) | 0x05),$IE=0;FIX($Z, $T) //Fix the alias
100_X0X_0XXX_1111_XXXXB INT $T :HEAP($IP)+IP(JP(10>$T?0:1)) ;$IF=true //Interruption
XXX_XXX_1000_10XX_XXXXX Y$Y_X$X IB :return 0 //
XXX_XXX_XXXX_XXXX_XXXXX Y$Y_X$X ($M) :0 //reserved
<!--
+----------------=> $M[17:15]:Mask
| +-------------=> $L[14:12]:Loop mode(0:Normal; 1:Wait+Fn; 2:Loop; 3:Wait; 4+:System+...) (asm: LOOP/WAIT)
| +-------------=> $L[14:12]:Loop mode(0:Normal; 1:Loop; 2:Wait; 3:Wait+Fn; 4+:System+...) (asm: LOOP/WAIT)
| | +-----------=> $K[ 11 ]:Keep open(1:$Z==FH/$B==-2) (asm: HLT $Z + WAIT)
| | | +---------=> $Z[10:8 ]:PREFIX $Z
| | | | +-------=> $J[ 7 ]:
| | | | | +-----=> $Y[ 6:4 ]:
| | | | | | +---=> $I[ 3 ]:
| | | | | | | +-=> $X[ 2:0 ]:
| | | | | | | |
/|\/|\|/|\|/|\|/|\
MMMLLLKZZZJYYYIXXX_ --><!--
XXXX00X00000000000C HLT :return 0 //HALT
111X00XXXX0XXX0XXXC HLT P$Z/$Z :FH($Z | 8) //Hold P$Z!/$Z
1XXX00XXXX00000000C HLT R$Z :FH($Z | 0) //Hold R$Z!
XXXX10X0000XXX0000C MOV [$Y],ACC :CR($Y,ACC())+ FL(0),$IE=0 //CR[$Y] = ACC
0XXX10XXXX00000XXXF MOV R$X,[$Z] :R$X(CR($Z))+ FL(0),$IE=0 //R$X = CR[$Z]
011X10XXXX0XXX0000F MOV R$Z,[R$Z] :R$Z(CTX(R$Z()))+ FL(0) //Context
0XXX10XXXX0XXX0000F MOV [R$Z],R$Y :CTX(R$Z(), R$Y())+ FL(0),$IE=0 //Context
1XXXXXX0000XXX0XXX_ PREFIX R$X/P$Y :return 0 //Prefix
101X00XXXX0XXX0XXXF XCHG R$Z,R$Y :$1=R$Z(),R$Z(R$Y()),R$Y($1) //Exchange R$Z! and R$Y!
110X00XXXX0XXX0XXXF XCHG P$Z,P$Y :$1=P$Z(),P$Z(P$Y()),P$Y($1) //Exchange P$Z! and P$Y!
XXXX1XXXXX0XXX0000X .Y$Y :0 //reserved
XXXX1XXXXX00000XXXX .X$X :0 //reserved
1XXX1XX1000XXX0XXXC IN R$X :R$X(PORT(R$X())) //Input from port
XXXX1XX1000XXX0XXXC OUT R$X,R$Y :PORT(R$X(),R$Y()) //Output to port
001X1XX0000XXX0000F .Y$Y R$X;[R$Y] :0 //reserved
010X1XX00000000XXXF .X$X [R$X];R$Y :0 //reserved
XXXX01X10000000100C MOV :$CTX.splice(0xAF, 1), $CTX.splice(0xA9, 0, FH()),$IE=0 //Set argument
XXXX01X1000XXX0000C MOV $Y :FH($CTX[0xA8 + $Y]),$IE=0 //Get argument
XXXX00X0000XXX0XXXF MOV R$X,R$Y :R$X(R$Y()) //Move R$Y! to R$X!
0XXX00X1000XXX0XXXF MOV P$X,T$Y :P$X(T$Y()) //Move T$Y! vector to P$X!
XXXXXXX1000XXX1XXXA ALU$X Z$Y :$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi()) //ALU$X! with Z$Y! and retained
XXXXXXXXXX0XXX1XXXA ALU$X Z$Z,R$Y :$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and R$Y!
XXXXXXX10010101XXXA ALU$X IB :$1=ALU$X(DROP(FH()),$B),ACC($1),FL($1.hi()) //ALU$X! with retained and immediate
XXXXXXXXXX10101XXXA ALU$X Z$Z,IB :$1=ALU$X(Z$Z(),$B),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and byte
XXXX00XXXX100XXXXXE PUSH $VIB :HEAP(0x$V00 + $B) //Push immediate data into stack
XXXX0XX00011111110C NOP :$Z //Hollow operation
XXXX0XXXXX11111110C NOP {$Z} :$Z //Hollow operation
111XXXX00011001XXXD INC Q$X :Q$X(Q$X()+1) //Increment Q$X!
111XXXX00011011XXXD DEC Q$X :Q$X(Q$X()-1) //Decrement Q$X!
XXXX00X00011001111A CMC :FL(FL() ^ 2) //Complement carry flag
XXXXXXXXXX11001110D ADC BX,T$Z :$1=BX()+T$Z()+(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Addition register pair with carry
111XXXXXXX11001XXXD ADD Q$X,T$Z :$1=Q$X()+T$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Addition register pair
XXXXXXXXXX11011110D SBB BX,T$Z :$1=BX()-T$Z()-(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Subtraction register pair with borrow
111XXXXXXX11011XXXD SUB Q$X,T$Z :$1=Q$X()-T$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Subtraction register pair
XXXX00X00011001010A XCHG :$1=ACC(); for($2=0,$0=0;8>$0;++$0,$1>>=1) $2=($2<<1)+($1&1); ACC($2)>0 //Exchange retained bits by mirror
XXXX00XXXX11001010A XCHG P$Z :$1=DST(),DST(P$Z()),P$Z($1) //Exchange P$Z! with retained pair
XXXX00XXXX11001111A XCHG R$Z :$1=ACC(),ACC(R$Z()),R$Z($1) //Exchange R$Z! with retained register
XXXXXXX100110X1XXXA ALU$W :$1=ACC(ALU$W(ACC())),FL($1.hi()) //ALU$W! with retained
XXXXXXXXXX110X1XXXA ALU$W Z$Z :$1=Z$Z(ALU$W(Z$Z())),FL($1.hi()) //ALU$W! with Z$Z!
XXXX00X00010100XXXF MOV R$X,IB :R$X($B) //Move immediate data into R$X!
XXXX0X10001011000XC BCND$X :CND$X?0:FL((FL() & 0x02) | 0x05) ;$IF=true //Conditional do
XXXX0X00001011000XB BCND$X $+$UIB :CND$X?IP(IP()+$A):0 ;$IF=true //Relative branching if CND$X!
XXXX00X10010111001E BIAS $+IB :HEAP(IP()+$A) //Push instruction based relative address
XXXX0X100010110XXXB CCND$X :CND$X?($1=P$Z(),P$Z(DW(SP())), DW(SP(), $1)):HEAP() ;$IF=true //Condition call
XXXX0XX00010110XXXB CCND$X $+IB :CND$X?HEAP(IP())+IP(IP()+$A):0 ;$IF=true //Relative call if CND$X!
XXXXXXX00011000XXXA INC R$X :$1=ADD(R$X(),1),R$X($1),FL($1.hi()) //Increment R$X!
XXXXXXX00011010XXXA DEC R$X :$1=SUB(R$X(),1),R$X($1),FL($1.hi()) //Decrement R$X!
XXXX00XXXX10100000E POP [P$Z+IB] :DW(P$Z()+$C,HEAP()) //Pop data into memory indexed by P$Z
XXXX00XXXX10100XXXF MOV R$X,[P$Z+IB] :R$X(DB(P$Z()+$C)) //Move memory data by P$Z pointer into R$X
XXXX00XXXX10110000E PUSH [P$Z+IB] :HEAP(DW(P$Z()+$C)) //Push data from memory indexed by P$Z
XXXX00XXXX10110XXXF MOV [P$Z+IB],R$X :DB(P$Z()+$C,R$X()) //Move R$X register data into memory by P$Z
XXXXXXX10010111XXXX --- IB :return 0 //Reserved extended code
XXXX00X10010111010E LEA +IB :DST(DST()+$B) //Load retained effective address
XXXX00X10010111XXXF MOV [U$X],IB :DB(U$X(),$B) //Load immediate data into memory by U$X
XXXX00100010111000C WAIT :FL((FL() & 0x02) | 0x0D) //Wait
XXXX0X0XXX10111000B JMP $+$UIB :$A==-2?(FL((FL() & 0x02) | 0x0D),trace.expression=0):IP(IP()+$A);$IF=true //Unonditional relative branching
XXXX0X0XXX10111001B CALL $+$UIB :$A==-2?0:HEAP(IP(IP()+$A)) ;$IF=true //Unconditional relative call
XXXX0X1XXX10111XXXC BCND$X :CND$X?0:FL((FL() & 0x02) | 0x05) ;$IF=true //Conditional do
XXXX00100010111001X . :0 //reserved
XXXX00100010111XXXX . :0 //reserved
XXXX0X0XXX10111XXXB BCND$X $+$UIB :CND$X?IP(IP()+$A):0 ;$IF=true //Branching if CND$X!
1X1X00X00011101XXXE PUSH U$X :HEAP(U$X()) //Push U$X! into stack
1X1X00X00011111XXXE POP U$X :U$X(HEAP()) //Pop U$X! from stack
XXXX00X10011101110F XCHG [SP] :$1=DST(),DST(DW($2=SP())), DW($2, $1) //Exchange retained pair with stack heap
XXXX00XXXX11101110F XCHG P$Z,[SP] :$1=P$Z(),P$Z(DW(SP())), DW(SP(), $1) //Exchange pair P$Z! with stack heap
XXXX00X10011101111E PUSH :HEAP(DST()) //Push retained pair
XXXX00XXXX11101111E PUSH S$Z :HEAP(S$Z()) //Push service S$Z register pair to stack
XXXX00X10011111111E POP :DST(HEAP()) //Pop retained pair
XXXX0XXXXX11111111E POP S$Z :S$Z(HEAP()) ;$IF=true //Pop service S$Z register pair from stack
XXXX00XXXX11101010E PUSH R$Z :DUP($Z) //Dup R$Z register history
XXXX00XXXX11101011C LOOP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z bits
XXXX00XXXX11101100C LOOP R$Z :FH($Z), FL((FL() & 0x02) | 0x09) //Forcing next operation by R$Z counter
XXXX00XXXX11101101C LOOP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x09) //Forcing next operation by $Z times
XXXX00XXXX11111010E POP R$Z :DROP($Z) //Drop R$Z register history
XXXX00XXXX11111011C SKIP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x05) //Exclude next operations by R$Z bits
XXXX00XXXX11111100C SKIP R$Z :FH($Z), FL((FL() & 0x02) | 0x05) //Exclude next operations by R$Z counter
XXXX00XXXX11111101C SKIP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x05) //Exclude next operations by $Z times
100X10X0001111XXXXB FLY $T :FLY($T) //Fix the alias
100X10XXXX1111XXXXB FIX $T :FH($Z | 8), FL((FL() & 0x02) | 0x05),$IE=0;FIX($Z, $T) //Fix the alias
100X0XXXXX1111XXXXB INT $T :HEAP($IP)+IP(JP(10>$T?0:1)) ;$IF=true //Interruption
XXXXXXXXXXXXXXXXXXX Y$Y_X$X ($M) :0 //reserved
-->
000X11XXX0XXX0XXXC MOV [$X],ACC :CR($X, ACC()) //CR[$X] = ACC
XXXXXX00000000000C HLT :return 0 // HALT
XXXXXXXXX00000000C HLT R$Z :IS_WAIT ? FH() == $Z ? ACC(CTX(ACC())) : $IR ? CTX(ACC(),R$Z()) : R$Z(CR(FH())) : FH($Z) // Hold R$Z!/P$Z! as retained
000XXX0000XXX0XXX_ PREFIX R$X/P$Y :return 0 // PREFIX
XXXXXX00011111110C NOP :$B==$B //
X10XXX00011101XXXE PUSH U$X :HEAP(U$X()) //
X10XXX00011111XXXE POP U$X :U$X(HEAP()) //
XXXXXXXXX11111110C NOP $Z :return $Z //Hollow operation til $Z ticks
XXXXXX10010101XXXA ALU$X IB :$1=ALU$X(DROP(FH()),$B),ACC($1),FL($1.hi()) //ALU$X! with retained and immediate
XXXXXXXXX10101XXXA ALU$X Z$Z,IB :$1=ALU$X(Z$Z(),$B),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and byte
XXXXXX1000XXX1XXXA ALU$X Z$Y :$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi()) //ALU$X! with Z$Y! and retained
XXXXXXXXX0XXX1XXXA ALU$X Z$Z,R$Y :$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and R$Y!
000000XXX0XXX0XXXC HLT $Z :FH($Z+8) //Hold $Z index number
X10XXX00011001XXXD INC Q$X :Q$X(Q$X()+1) // Increment Q$X!
X10XXX00011011XXXD DEC Q$X :Q$X(Q$X()-1) // Decrement Q$X!
XXXXXX00011001111A CMC :FL(FL() ^ 2) // Complement carry flag
XXXXXXXXX11001110D ADC BX,T$Z :$1=BX()+T$Z()+(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) // Addition register pair with carry
X10XXXXXX11001XXXD ADD Q$X,T$Z :$1=Q$X()+T$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) // Addition register pair
XXXXXXXXX11011110D SBB BX,T$Z :$1=BX()-T$Z()-(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) // Subtraction register pair with borrow
X10XXXXXX11011XXXD SUB Q$X,T$Z :$1=Q$X()-T$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) // Subtraction register pair
XXXXXX00011001010A XCHG :$1=ACC(); for($2=0,$0=0;8>$0;++$0,$1>>=1) $2=($2<<1)+($1&1); ACC($2)>0 // Exchange retained bits by mirror
XXXXXXXXX11001010A XCHG P$Z :$1=DST(),DST(P$Z()),P$Z($1) // Exchange P$Z! with retained pair
XXXXXXXXX11001111A XCHG R$Z :$1=ACC(),ACC(R$Z()),R$Z($1) // Exchange R$Z! with retained register
XXXXXX100110X1XXXA ALU$W :$1=ACC(ALU$W(ACC())),FL($1.hi()) // ALU$W! with retained
XXXXXXXXX110X1XXXA ALU$W Z$Z :$1=Z$Z(ALU$W(Z$Z())),FL($1.hi()) // ALU$W! with Z$Z!
X11XXX1000XXX0000A MUL R$Y :return 0 //
X11XXX10000000XXXF XCHG R$X :$1=ACC(),ACC(R$X()),R$X($1) // Exchange R$Z! with retained register
X11XXX1000XXX0100F XCHG P$Y :$1=DST(),DST(P$Y()),P$Y($1) // Exchange P$Z! with retained pair
X11XXX1000XXX0XXXF MOV P$X,T$Y :P$X(T$Y()) // Move T$Y! vector to P$X!
000X110000XXX0XXXC IN R$X :R$X(PORT(R$X())) //Input from port
XXXX110000XXX0XXXC OUT R$X,R$Y :PORT(R$X(),R$Y()) //Output to port
XXXXXX0000XXX0XXXF MOV R$X,R$Y :R$X(R$Y()) //Move data
XXXXXX00010110000B JCND$X $+IB :CND$X?IP(IP()+$A):0 // Relative branching if CND$X!
XXXXXX00010100XXXF MOV R$X,IB :R$X($B) // Move immediate data into R$X!
XXXXXX00010110001E BIAS $+IB :HEAP(IP()+$A) // Push instruction based relative address
XXXXXX00010110XXXB CCND$X $+IB :CND$X?HEAP(IP())+IP(IP()+$A):0 // Relative call if CND$X!
XXXXXX00011000XXXA INC R$X :$1=ADD(R$X(),1),R$X($1),FL($1.hi()) // Increment R$X!
XXXXXX00011010XXXA DEC R$X :$1=SUB(R$X(),1),R$X($1),FL($1.hi()) // Decrement R$X!
X00X00XXX1111XXXXB INT $T :HEAP($IP)+IP(JP($T<10?0:1))>0 // Programm interruption indexed by $T
XXXX0010011101110F XCHG [SP] :$1=DST(),DST(DW($2=SP())), DW($2, $1) // Exchange retained pair with stack heap
XXXX00XXX11101110F XCHG P$Z,[SP] :$1=P$Z(),P$Z(DW(SP())), DW(SP(), $1) // Exchange pair P$Z! with stack heap
001X00XXX0XXX0XXXF XCHG P$Z,P$Y :$1=P$Z(),P$Z(P$Y()),P$Y($1) // Exchange P$Z! and P$Y!
010X00XXX0XXX0XXXF XCHG R$Z,R$Y :$1=R$Z(),R$Z(R$Y()),R$Y($1) // Exchange R$Z! and R$Y!
XXXX00XXX10100000E POP [P$Z+IB] :DW(P$Z()+$C,HEAP()) // Pop data into memory indexed by P$Z
XXXX00XXX10100XXXF MOV R$X,[P$Z+IB] :R$X(DB(P$Z()+$C)) // Move memory data by P$Z pointer into R$X
XXXX00XXX10110000E PUSH [P$Z+IB] :HEAP(DW(P$Z()+$C)) // Push data from memory indexed by P$Z
XXXX00XXX10110XXXF MOV [P$Z+IB],R$X :DB(P$Z()+$C,R$X()) // Move R$X register data into memory by P$Z
XXXX0010011101111E PUSH :HEAP(DST()) // Push retained pair
XXXX00XXX11101111E PUSH S$Z :HEAP(S$Z()) // Push service S$Z register pair to stack
XXXX0010011111111E POP :DST(HEAP()) // Pop retained pair
XXXX00XXX11111111E POP S$Z :S$Z(HEAP()) // Pop service S$Z register pair from stack
XXXX00XXX11101010E PUSH R$Z :DUP($Z) // Dup R$Z register history
XXXX00XXX11101011C SKIP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x05) // Exclude next operations by R$Z bits
XXXX00XXX11101100C SKIP R$Z :FH($Z), FL((FL() & 0x02) | 0x05) // Exclude next operations by R$Z counter
XXXX00XXX11101101C SKIP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x05) // Exclude next operations by $Z times
XXXX00XXX11111010E POP R$Z :DROP($Z) // Drop R$Z register history
XXXX00XXX11111011C LOOP [R$Z] :FH(R$Z()|8),FL((FL() & 0x02) | 0x09) // Forcing next operation by R$Z bits
XXXX00XXX11111100C LOOP R$Z :FH($Z), FL((FL() & 0x02) | 0x09) // Forcing next operation by R$Z counter
XXXX00XXX11111101C LOOP $Z :FH($Z | 8), FL((FL() & 0x02) | 0x09) // Forcing next operation by $Z times
XXXX00XXX100XXXXXE PUSH $VIB :HEAP(0x$V00 + $B) // Push immediate data into stack
0XXXXX10010111XXXX --- IB :return 0 // Reserved extended code
XXXX0010010111010E LEA +IB :DST(DST()+$B) // Load retained effective address
X10X0010010111XXXF MOV [U$X],IB :DB(U$X(),$B) // Load immediate data into memory by U$X
XXXX00XXX10111000B JMP $+$UIB :$A==-2?(FL((FL() & 0x02) | 0x0D),trace.expression=0):IP(IP()+$A) // Unonditional relative branching
XXXX00XXX10111001B CALL $+$UIB :$A==-2?0:HEAP(IP(IP()+$A)) // Unconditional relative call
XXXX00XXX10111XXXB JCND$X $+$UIB :CND$X?IP(IP()+$A):0 // Branching if CND$X!
XXXXXXXXXXXXXXXXXX --- :return 0 // Reserved code
XXX00000000000C HLT :IS_BOOT ? IS_WAIT ? CR(0, ACC()) : FH(8) : (CR(CR(0) & 0xF0), FH(0xB), FL(0x5)) // Halting
XXX00011111110C NOP :$IB==$IB // No operation
0000000XXX0XXX_ PREFIX R#X/P#X :0 // Prefix for R#X!/P#X!
X1000011101XXXE PUSH+ U#X :HEAP(U#X()) // Push pointer into stack
X1000011111XXXE POP+ U#X :U#X(HEAP()) // Pop pointer from stack
XXXXXX11111110C NOP #Z :#Z // Hollow operation through #Z ticks
XXX10010101XXXA ALU#X IB :$1=ALU#X(DROP(FH()),$IB),ACC($1),FL($1.hi()) // ALU#X! with retained and immediate
XXXXXX10101XXXA ALU#X Z#Z,IB :$1=ALU#X(Z#Z(),$IB),Z#Z($1),FL($1.hi()) // ALU#X! with Z#Z! and byte
XXX1000XXX1XXXA ALU#X Z#Y :$1=ALU#X(DROP(#Y),REG(#Y)),REG(#Y,$1),FL($1.hi()) // ALU#X! with Z#Y! and retained
XXXXXX0XXX1XXXA ALU#X Z#Z,R#Y :$1=ALU#X(Z#Z(),R#Y()),Z#Z($1),FL($1.hi()) // ALU#X! with Z#Z! and R#Y!
000XXX0XXX0XXXC HLT #Z :IS_BOOT && IS_WAIT ? FH()==(#Z+8) ? ACC(PORT(ACC())) : FH()>=8 ? PORT(R#Z(),ACC()) : CR(#Z,ACC()) : FH(#Z+8) // Hold #Z index number
X1000011001XXXD INC+ Q#X :Q#X(Q#X()+1) // Increment Q#X!
X1000011011XXXD DEC+ Q#X :Q#X(Q#X()-1) // Decrement Q#X!
XXX00011001111A CMC :FL(FL() ^ 2) // Complement carry flag
XXXXXX11001110D ADC BX,T#Z :$1=BX()+T#Z()+(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) // Addition register pair with carry
X10XXX11001XXXD ADD Q#X,T#Z :$1=Q#X()+T#Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q#X($1) // Addition register pair
XXXXXX11011110D SBB BX,T#Z :$1=BX()-T#Z()-(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) // Subtraction register pair with borrow
X10XXX11011XXXD SUB Q#X,T#Z :$1=Q#X()-T#Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q#X($1) // Subtraction register pair
XXX00011001010A XCHG :$1=ACC(); for($2=0,$0=0;$0<8;++$0,$1>>=1) $2=($2<<1)+($1&1); ACC($2)>0 // Exchange retained bits by mirror
XXXXXX11001010A XCHG P#Z :$1=DST(),DST(P#Z()),P#Z($1) // Exchange P#Z! with retained pair
XXXXXX11001111A XCHG R#Z :$1=ACC(),ACC(R#Z()),R#Z($1) // Exchange R#Z! with retained register
XXX100110X1XXXA ALU#W :$1=ACC(ALU#W(ACC())),FL($1.hi()) // ALU#W! with retained
XXXXXX110X1XXXA ALU#W Z#Z :$1=Z#Z(ALU#W(Z#Z())),FL($1.hi()) // ALU#W! with Z#Z!
X111000XXX0000A MUL R#Y :0 //
X1110000000XXXF XCHG R#X :$1=ACC(),ACC(R#X()),R#X($1) // Exchange R#Z! with retained register
X111000XXX0100F XCHG P#Y :$1=DST(),DST(P#Y()),P#Y($1) // Exchange P#Z! with retained pair
X111000XXX0XXXF MOV P#X,T#Y :P#X(T#Y()) // Move T#Y! vector to P#X!
01110000000XXXD_PUSH+ T#X+[T#Y] :HEAP(T#X()+DW(T#Y())) // Correct effective address in stack
0111000XXX0XXXD_PUSH+ T#X+T#Y :HEAP(T#X()+T#Y()) // Push effective address into stack
1111000XXX0000D_PUSH+ [T#X]-T#Y :HEAP(HEAP()-T#Y()) // Correct effective address in stack
1111000XXX0XXXD_PUSH+ T#X-T#Y :HEAP(T#X()-T#Y()) // Push effective address into stack
XXXXXX00000000C HLT R#Z :IS_WAIT ? FH() == #Z ? ACC(CTX(ACC())) : $IR ? CTX(ACC(),R#Z()) : R#Z(CR(FH())) : FH(#Z) // Hold R#Z!/P#Z! as retained
XXX0000XXX0XXXF MOV R#X,R#Y :IS_WAIT && true ? #Y == 0 ? ($1=PORT(R#X()),trace.eady?R#X($1):0) : PORT(R#X(),R#Y()) : R#X(R#Y()) // Move R#Y! data into R#X!
X11XXX0XXX0XXXD_ALU#Z P#X,T#Y :0 //
XXX00010110000B JCND#X $+IB :CND#X?IP(IP()+$IV):0 // Relative branching if CND#X!
XXX00010100XXXF MOV R#X,IB :R#X($IB) // Move immediate data into R#X!
XXX00010110001E BIAS $+IB :HEAP($IP+$IV) // Push instruction based relative address
XXX00010110XXXB CCND#X $+IB :CND#X?HEAP(IP())+IP(IP()+$IV):0 // Relative call if CND#X!
XXX00011000XXXA INC+ R#X :$1=ADD(R#X(),1),R#X($1),FL($1.hi()) // Increment R#X!
XXX00011010XXXA DEC+ R#X :$1=SUB(R#X(),1),R#X($1),FL($1.hi()) // Decrement R#X!
X00XXX1111XXXXB INT #T :HEAP($IP)+IP(JP(#T<10?0:1))>0 // Programm interruption indexed by #T
XXX10011101110F XCHG [SP] :$1=DST(),DST(DW($2=SP())), DW($2, $1) // Exchange retained pair with stack heap
XXXXXX11101110F XCHG P#Z,[SP] :$1=P#Z(),P#Z(DW(SP())), DW(SP(), $1) // Exchange pair P#Z with stack heap
001XXX0XXX0XXXF XCHG P#Z,P#Y :$1=P#Z(),P#Z(P#Y()),P#Y($1) // Exchange P#Z! and P#Y!
010XXX0XXX0XXXF XCHG R#Z,R#Y :$1=R#Z(),R#Z(R#Y()),R#Y($1) // Exchange R#Z! and R#Y!
011XXX0XXX0XXXD LEA P#Z,T#X+T#Y :P#Z(T#X()+T#Y()) // Load T#X!+T#Y! effective address into P#Z
111XXX0XXX0XXXD LEA P#Z,T#X-T#Y :P#Z(T#X()-T#Y()) // Load T#X!-T#Y! effective address into P#Z
XXXXXX10100000E POP+ [P#Z+IB] :DW(P#Z()+$IV,HEAP()) // Pop data into memory indexed by P#Z
XXXXXX10100XXXF MOV R#X,[P#Z+IB] :trace.is_port=IP_BP; trace.is_context=IP_SP; R#X(DB(P#Z()+$IV)) // Move memory data by P#Z pointer into R#X
XXXXXX10110000E PUSH+ [P#Z+IB] :HEAP(DW(P#Z()+$IV)) // Push data from memory indexed by P#Z
XXXXXX10110XXXF MOV [P#Z+IB],R#X :trace.is_port=IP_BP; trace.is_context=IP_SP; DB(P#Z()+$IV,R#X()) // Move R#X register data into memory by P#Z
XXX10011101111E PUSH :HEAP(DST()) // Push retained pair
XXXXXX11101111E PUSH+ S#Z :HEAP(S#Z()) // Push service S#Z register pair to stack
XXX10011111111E POP :DST(HEAP()) // Pop retained pair
XXXXXX11111111E POP+ S#Z :S#Z(HEAP()) // Pop service S#Z register pair from stack
XXXXXX11101010E PUSH+ R#Z :DUP(#Z) // Dup R#Z register history
XXXXXX11101011C SKIP [R#Z] :FH(R#Z()|8),FL((FL() & 0x02) | 0x05) // Exclude next operations by R#Z bits
XXXXXX11101100C SKIP R#Z :FH(#Z), FL((FL() & 0x02) | 0x05) // Exclude next operations by R#Z counter
XXXXXX11101101C SKIP #Z :FH(#Z | 8), FL((FL() & 0x02) | 0x05) // Exclude next operations by #Z times
XXXXXX11111010E POP+ R#Z :DROP(#Z) // Drop R#Z register history
XXXXXX11111011C LOOP [R#Z] :FH(R#Z()|8),FL((FL() & 0x02) | 0x09) // Forcing next operation by R#Z bits
XXXXXX11111100C LOOP R#Z :FH(#Z), FL((FL() & 0x02) | 0x09) // Forcing next operation by R#Z counter
XXXXXX11111101C LOOP #Z :FH(#Z | 8), FL((FL() & 0x02) | 0x09) // Forcing next operation by #Z times
XXXXXX100XXXXXE PUSH+ #VIB :HEAP(0x#V00 + $IB) // Push immediate data into stack
0XX10010111XXXX --- IB :return 0 // Reserved extended code
XXX10010111010E LEA +IB :DST(DST()+$IB) // Load retained effective address
X1010010111XXXF MOV [U#X],IB :DB(U#X(),$IB) // Load immediate data into memory by U#X
XXXXXX10111000B JMP $+#UIB :$IW==-2?(FL((FL() & 0x02) | 0x0D),trace.expression=0):IP(IP()+$IW) // Unonditional relative branching
XXXXXX10111001B CALL $+#UIB :$IW==-2?0:HEAP(IP(IP()+$IW)) // Unconditional relative call
XXXXXX10111XXXB JCND#X $+#UIB :CND#X?IP(IP()+$IW):0 // Branching if CND#X!
XXXXXXXXXXXXXXX --- :return 0 // Reserved code
// Helpers
ALU08 ROL ROL Roll Overflow Left
ALU09 RCL RCL Roll Cyclic Left
ALU0A XCHG
ALU0F NEG 0
ALU18 ROR ROR Roll Overflow Right
ALU19 RCR RCR Roll Cyclic Right
ALU1A RAR RAR Roll Arithmetic Right
ALU1F NOT NOT Bitwise NOT
ALU0 ADC ADC Addition with carry
ALU1 SBB SBB Subtract with borrow
ALU2 ADD ADD Addition
ALU3 SUB SUB Subtract
ALU4 AND AND Bitwise AND/conjunct
ALU5 OR OR Bitwise OR/disjunct
ALU6 XOR XOR Bitwise eXclusive OR
ALU7 CMP CMP Comparation
// Register descriptions
// Pointers
P14 -- -- --
P15 -- -- --
P0 IP IP IP
P1 BP BP BP
P2 SI SI SI
P3 DI DI DI
P4 SP SP SP
P5 BX BX DX
P6 CX CX CX
P7 DX DX DX
// Quad
Q3 BX BX BX
Q4 CX CX CX
Q5 DX DX DX
Q6 SP SP SP
// Regular
R0 [BX] _BX_ [BX]
R1 BH BH BH
R2 CH CH CH
R3 DH DH DH
R4 AL AL AL
R5 BL BL BL
R6 CL CL CL
R7 DL DL DL
// Special
S0 IP IP IP
S1 BP BP BP
S2 SI SI SI
S3 DI DI DI
S4 [SP] _SP_ [SP]
S5 EX Extend Ex
S6 SX SX Sx
S7 TX Timers Tx
// Tabular
T0 SP SP SP
T1 BP BP BP
T2 SI SI SI
T3 DI DI DI
T4 AL _AL_ AL
T5 BX BX BX
T6 CX CX CX
T7 DX DX DX
// Unical
U2 AX AX AX
U3 BX BX BX
U4 CX CX CX
U5 DX DX DX
Z0 AL AL AL
Z1 BH BH BH
Z2 CH CH CH
Z3 DH DH DH
Z4 AL AL AL
Z5 BL BL BL
Z6 CL CL CL
Z7 DL DL DL
Z8 AL AL AL
_ZF ZF !!(FL() & 1)
_CF CF !!(FL() & 2)
_PF PF !!(FL() & 4)
_SF SF !!(FL() & 8)
// Conditional
CND0 PO !!(FL() & 4) Parity is Odd
CND1 PE !(FL() & 4) Parity is Even
CND2 S !!(FL() & 8) result is Among
CND3 NS !(FL() & 8) result is Bigger
CND4 C !!(FL() & 2) result with Carry
CND5 NC !(FL() & 2) result Carry Discarded
CND6 Z !!(FL() & 1) result is Equal
CND7 NZ !(FL() & 1) result is Fictional
IS_BOOT IS_BOOT (!(CR() & 128))
IS_WAIT IS_WAIT ($IE == 3)
IP_BP IP_BP (BP().hi()==IP().hi() && (($Z==1)||($Z==4)))
IP_SP IP_SP (SP().hi()==IP().hi() && ($Z==4))
CLC! @BD 01 CF Clear CARRY FLAG
STC! @BC 01 CF Store CARRY FLAG
RPE! @B0 FF Return by EVEN PARITY
RPO! @B1 FF Return by ODD PARITY
RS! @BA FF Return by Positive
RNS! @BB FF Return by Negative
RC! @BC FF Return by CARRY
RNC! @BD FF Return by not CARRY
RZ! @BE FF Return by ZERO
RNZ! @BF FF Return by not ZERO
RET! @B8 FF Return from subroutine
<!--
// Aliases
HLT 0 @00
HLT BP @11 00
HLT SI @22 00
HLT DI @33 00
HLT [SP] @44 00
HLT BX @55 00
HLT CX @66 00
HLT DX @77 00
WAIT!0 @B8 FE F0 Express Function #0
WAIT!1 @B8 FE F1 Express Function #1
WAIT!2 @B8 FE F2 Express Function #2
WAIT!3 @B8 FE F3 Express Function #3
WAIT!4 @B8 FE F4 Express Function #4
WAIT!5 @B8 FE F5 Express Function #5
WAIT!6 @B8 FE F6 Express Function #6
WAIT!7 @B8 FE F7 Express Function #7
WAIT!8 @B8 FE F8 Express Function #8
WAIT!9 @B8 FE F9 Express Function #9
CALL![SP] @EE Call subroutine
WAIT! @B8 FE Waitable mode
MOV!BX,CX @21 65 Load %Y register pair to %X
MOV!BX,DX @31 75 Load %Y register pair to %X
MOV!CX,BX @12 56 Load %Y register pair to %X
MOV!CX,DX @31 76 Load %Y register pair to %X
MOV!DX,BX @13 57 Load %Y register pair to %X
MOV!DX,CX @23 67 Load %Y register pair to %X
MOV!BP,SI @22 EF 11 FF Load %Y register pair to %X
MOV!BP,DI @33 EF 11 FF Load %Y register pair to %X
MOV!BP,BX @EB 11 FF Load %Y register pair to %X
MOV!BP,CX @EC 11 FF Load %Y register pair to %X
MOV!BP,DX @ED 11 FF Load %Y register pair to %X
MOV!SI,BP @11 EF 22 FF Load %Y register pair to %X
MOV!SI,DI @33 EF 22 FF Load %Y register pair to %X
MOV!SI,BX @EB 22 FF Load %Y register pair to %X
MOV!SI,CX @EC 22 FF Load %Y register pair to %X
MOV!SI,DX @ED 22 FF Load %Y register pair to %X
MOV!DI,BP @11 EF 33 FF Load %Y register pair to %X
MOV!DI,SI @22 EF 33 FF Load %Y register pair to %X
MOV!DI,BX @EB 33 FF Load %Y register pair to %X
MOV!DI,CX @EC 33 FF Load %Y register pair to %X
MOV!DI,DX @ED 33 FF Load %Y register pair to %X
MOV!BX,BP @11 EF FB Load %Y register pair to %X
MOV!BX,SI @22 EF FB Load %Y register pair to %X
MOV!BX,DI @33 EF FB Load %Y register pair to %X
MOV!CX,BP @11 EF FC Load %Y register pair to %X
MOV!CX,SI @22 EF FC Load %Y register pair to %X
MOV!CX,DI @33 EF FC Load %Y register pair to %X
MOV!DX,BP @11 EF FD Load %Y register pair to %X
MOV!DX,SI @22 EF FD Load %Y register pair to %X
MOV!DX,DI @33 EF FD Load %Y register pair to %X
MOV [0],BH @11 00 B8 FE 00 Set control register #%X by %Y
MOV [0],CH @22 00 B8 FE 00 Set control register #%X by %Y
MOV [0],DH @33 00 B8 FE 00 Set control register #%X by %Y
MOV [0],AL @44 00 B8 FE 00 Set control register #%X by %Y
MOV [0],BL @55 00 B8 FE 00 Set control register #%X by %Y
MOV [0],CL @66 00 B8 FE 00 Set control register #%X by %Y
MOV [0],DL @77 00 B8 FE 00 Set control register #%X by %Y
MOV [1],BH @11 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],CH @22 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],DH @33 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],AL @44 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],BL @55 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],CL @66 00 B8 FE 11 11 Set control register #%X by %Y
MOV [1],DL @77 00 B8 FE 11 11 Set control register #%X by %Y
MOV [2],BH @11 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],CH @22 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],DH @33 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],AL @44 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],BL @55 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],CL @66 00 B8 FE 22 22 Set control register #%X by %Y
MOV [2],DL @77 00 B8 FE 22 22 Set control register #%X by %Y
MOV [3],BH @11 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],CH @22 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],DH @33 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],AL @44 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],BL @55 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],CL @66 00 B8 FE 33 33 Set control register #%X by %Y
MOV [3],DL @77 00 B8 FE 33 33 Set control register #%X by %Y
MOV [4],BH @11 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],CH @22 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],DH @33 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],AL @44 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],BL @55 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],CL @66 00 B8 FE 44 44 Set control register #%X by %Y
MOV [4],DL @77 00 B8 FE 44 44 Set control register #%X by %Y
MOV [5],BH @11 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],CH @22 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],DH @33 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],AL @44 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],BL @55 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],CL @66 00 B8 FE 55 55 Set control register #%X by %Y
MOV [5],DL @77 00 B8 FE 55 55 Set control register #%X by %Y
MOV [6],BH @11 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],CH @22 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],DH @33 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],AL @44 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],BL @55 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],CL @66 00 B8 FE 66 66 Set control register #%X by %Y
MOV [6],DL @77 00 B8 FE 66 66 Set control register #%X by %Y
MOV [7],BH @11 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],CH @22 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],DH @33 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],AL @44 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],BL @55 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],CL @66 00 B8 FE 77 77 Set control register #%X by %Y
MOV [7],DL @77 00 B8 FE 77 77 Set control register #%X by %Y
MOV BH,[0] @00 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[0] @00 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[0] @00 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[0] @00 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[0] @00 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[0] @00 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[0] @00 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[1] @11 11 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[1] @11 11 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[1] @11 11 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[1] @11 11 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[1] @11 11 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[1] @11 11 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[1] @11 11 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[2] @22 22 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[2] @22 22 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[2] @22 22 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[2] @22 22 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[2] @22 22 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[2] @22 22 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[2] @22 22 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[3] @33 33 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[3] @33 33 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[3] @33 33 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[3] @33 33 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[3] @33 33 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[3] @33 33 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[3] @33 33 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[4] @44 44 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[4] @44 44 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[4] @44 44 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[4] @44 44 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[4] @44 44 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[4] @44 44 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[4] @44 44 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[5] @55 55 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[5] @55 55 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[5] @55 55 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[5] @55 55 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[5] @55 55 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[5] @55 55 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[5] @55 55 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[6] @66 66 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[6] @66 66 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[6] @66 66 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[6] @66 66 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[6] @66 66 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[6] @66 66 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[6] @66 66 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[7] @77 77 B8 FE 11 00 Get control register #%Y to %X
MOV CH,[7] @77 77 B8 FE 22 00 Get control register #%Y to %X
MOV DH,[7] @77 77 B8 FE 33 00 Get control register #%Y to %X
MOV AL,[7] @77 77 B8 FE 44 00 Get control register #%Y to %X
MOV BL,[7] @77 77 B8 FE 55 00 Get control register #%Y to %X
MOV CL,[7] @77 77 B8 FE 66 00 Get control register #%Y to %X
MOV DL,[7] @77 77 B8 FE 77 00 Get control register #%Y to %X
MOV BH,[BH] @11 00 B8 FE 11 00 Read context cell [%X] to %X
MOV CH,[CH] @22 00 B8 FE 22 00 Read context cell [%X] to %X
MOV DH,[DH] @33 00 B8 FE 33 00 Read context cell [%X] to %X
MOV AL,[AL] @44 00 B8 FE 44 00 Read context cell [%X] to %X
MOV BL,[BL] @55 00 B8 FE 55 00 Read context cell [%X] to %X
MOV CL,[CL] @66 00 B8 FE 66 00 Read context cell [%X] to %X
MOV DL,[DL] @77 00 B8 FE 77 00 Read context cell [%X] to %X
MOV [BH],CH @11 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [BH],DH @11 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [BH],AL @11 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [BH],BL @11 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [BH],CL @11 00 B8 FE 66 00 Write %Y to context cell [%X]
MOV [BH],DL @11 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [CH],BH @22 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [CH],DH @22 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [CH],AL @22 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [CH],BL @22 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [CH],CL @22 00 B8 FE 66 00 Write %Y to context cell [%X]
MOV [CH],DL @22 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [DH],BH @33 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [DH],CH @33 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [DH],AL @33 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [DH],BL @33 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [DH],CL @33 00 B8 FE 66 00 Write %Y to context cell [%X]
MOV [DH],DL @33 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [AL],BH @44 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [AL],CH @44 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [AL],DH @44 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [AL],BL @44 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [AL],CL @44 00 B8 FE 66 00 Write %Y to context cell [%X]
MOV [AL],DL @44 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [BL],BH @55 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [BL],CH @55 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [BL],DH @55 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [BL],AL @55 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [BL],CL @55 00 B8 FE 66 00 Write %Y to context cell [%X]
MOV [BL],DL @55 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [CL],BH @66 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [CL],CH @66 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [CL],DH @66 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [CL],AL @66 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [CL],BL @66 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [CL],DL @66 00 B8 FE 77 00 Write %Y to context cell [%X]
MOV [DL],BH @77 00 B8 FE 11 00 Write %Y to context cell [%X]
MOV [DL],CH @77 00 B8 FE 22 00 Write %Y to context cell [%X]
MOV [DL],DH @77 00 B8 FE 33 00 Write %Y to context cell [%X]
MOV [DL],AL @77 00 B8 FE 44 00 Write %Y to context cell [%X]
MOV [DL],BL @77 00 B8 FE 55 00 Write %Y to context cell [%X]
MOV [DL],CL @77 00 B8 FE 66 00 Write %Y to context cell [%X]
IN BH @B8 FE 01 Input to %X from port %X
IN CH @B8 FE 02 Input to %X from port %X
IN DH @B8 FE 03 Input to %X from port %X
IN AL @B8 FE 04 Input to %X from port %X
IN BL @B8 FE 05 Input to %X from port %X
IN CL @B8 FE 06 Input to %X from port %X
IN DL @B8 FE 07 Input to %X from port %X
OUT BH,CH @B8 FE 21 Output %Y to port %X
OUT BH,DH @B8 FE 31 Output %Y to port %X
OUT BH,AL @B8 FE 41 Output %Y to port %X
OUT BH,BL @B8 FE 51 Output %Y to port %X
OUT BH,CL @B8 FE 61 Output %Y to port %X
OUT BH,DL @B8 FE 71 Output %Y to port %X
OUT CH,BH @B8 FE 12 Output %Y to port %X
OUT CH,DH @B8 FE 32 Output %Y to port %X
OUT CH,AL @B8 FE 42 Output %Y to port %X
OUT CH,BL @B8 FE 52 Output %Y to port %X
OUT CH,CL @B8 FE 62 Output %Y to port %X
OUT CH,DL @B8 FE 72 Output %Y to port %X
OUT DH,BH @B8 FE 13 Output %Y to port %X
OUT DH,CH @B8 FE 23 Output %Y to port %X
OUT DH,AL @B8 FE 43 Output %Y to port %X
OUT DH,BL @B8 FE 53 Output %Y to port %X
OUT DH,CL @B8 FE 63 Output %Y to port %X
OUT DH,DL @B8 FE 73 Output %Y to port %X
OUT AL,BH @B8 FE 14 Output %Y to port %X
OUT AL,CH @B8 FE 24 Output %Y to port %X
OUT AL,DH @B8 FE 34 Output %Y to port %X
OUT AL,BL @B8 FE 54 Output %Y to port %X
OUT AL,CL @B8 FE 64 Output %Y to port %X
OUT AL,DL @B8 FE 74 Output %Y to port %X
OUT BL,BH @B8 FE 15 Output %Y to port %X
OUT BL,CH @B8 FE 25 Output %Y to port %X
OUT BL,DH @B8 FE 35 Output %Y to port %X
OUT BL,AL @B8 FE 45 Output %Y to port %X
OUT BL,CL @B8 FE 65 Output %Y to port %X
OUT BL,DL @B8 FE 75 Output %Y to port %X
OUT CL,BH @B8 FE 16 Output %Y to port %X
OUT CL,CH @B8 FE 26 Output %Y to port %X
OUT CL,DH @B8 FE 36 Output %Y to port %X
OUT CL,AL @B8 FE 46 Output %Y to port %X
OUT CL,BL @B8 FE 56 Output %Y to port %X
OUT CL,DL @B8 FE 76 Output %Y to port %X
OUT DL,BH @B8 FE 17 Output %Y to port %X
OUT DL,CH @B8 FE 27 Output %Y to port %X
OUT DL,DH @B8 FE 37 Output %Y to port %X
OUT DL,AL @B8 FE 47 Output %Y to port %X
OUT DL,BL @B8 FE 57 Output %Y to port %X
OUT DL,CL @B8 FE 67 Output %Y to port %X
-->
ASCx0000 FF FF FF FF FF FF FF FF C7 C7 C7 C7 FF FF FF FF
ASCx0010 F8 F8 F8 F8 FF FF FF FF C0 C0 C0 C0 FF FF FF FF
ASCx0020 FF FF FF FF F8 F8 F8 F8 C7 C7 C7 C7 F8 F8 F8 F8
ASCx0030 F8 F8 F8 F8 F8 F8 F8 F8 C0 C0 C0 C0 F8 F8 F8 F8
ASCx0040 FF FF FF FF FF FF FF FF F3 F3 C0 D2 F3 F3 ED DE
ASCx0050 FF FF FF FF FF FF FF FF F3 E1 C0 F3 F3 F3 F3 F3
ASCx0060 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
ASCx0070 F7 F3 D1 C0 C0 D1 F3 F7 F3 F3 F3 F3 F3 C0 E1 F3
ASCx0080 FF FF FF FF C7 C7 C7 C7 C7 C7 C7 C7 C7 C7 C7 C7
ASCx0090 F8 F8 F8 F8 C7 C7 C7 C7 C0 C0 C0 C0 C7 C7 C7 C7
ASCx00A0 FF FF FF FF C0 C0 C0 C0 C7 C7 C7 C7 C0 C0 C0 C0
ASCx00B0 F8 F8 F8 F8 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0
ASCx00C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
ASCx00D0 FF FF FF FF FF FF FF FF F3 F3 F3 F3 F3 F3 F3 F3
ASCx00E0 FF FF FF C0 C0 FF FF FF FB F3 E2 C0 C0 E2 F3 FB
ASCx00F0 C7 DF DF D8 C2 FA FA FA FF FF FF FF FF FF FF FF
ASCx0100 FF FF FF FF FF FF FF FF FB FB FB FB FB FF FB FF
ASCx0110 F5 F5 F5 FF FF FF FF FF F5 F5 E0 F5 E0 F5 F5 FF
ASCx0120 FB F0 EB F1 FA E1 FB FF E7 E6 FD FB F7 EC FC FF
ASCx0130 FB F5 F5 F3 EA ED F2 FF F9 F9 FD FB FF FF FF FF
ASCx0140 FD FB F7 F7 F7 FB FD FF F7 FB FD FD FD FB F7 FF
ASCx0150 FF FB EA F1 EA FB FF FF FF FB FB E0 FB FB FF FF
ASCx0160 FF FF FF F3 F3 FB F7 FF FF FF FF E0 FF FF FF FF
ASCx0170 FF FF FF FF FF F3 F3 FF FF FE FD FB F7 EF FF FF
ASCx0180 F1 EE EC EA E6 EE F1 FF FB F3 FB FB FB FB F1 FF
ASCx0190 F1 EE FE F9 F7 EF E0 FF E0 FE FD F9 FE EE F1 FF
ASCx01A0 FD F9 F5 ED E0 FD FD FF E0 EF E1 FE FE EE F1 FF
ASCx01B0 F8 F7 EF E1 EE EE F1 FF E0 FE FD FB F7 F7 F7 FF
ASCx01C0 F1 EE EE F1 EE EE F1 FF F1 EE EE F0 FE FD E3 FF
ASCx01D0 FF F3 F3 FF FF F3 F3 FF F3 F3 FF F3 F3 FB F7 FF
ASCx01E0 FD FB F7 EF F7 FB FD FF FF FF E0 FF E0 FF FF FF
ASCx01F0 F7 FB FD FE FD FB F7 FF F1 EE FE FD FB FF FB FF
ASCx0200 F1 EE EC EA E8 EF F1 FF FB F5 EE EE E0 EE EE FF
ASCx0210 E1 EE EE E1 EE EE E1 FF F1 EE EF EF EF EE F1 FF
ASCx0220 E1 F6 F6 F6 F6 F6 E1 FF E0 EF EF E1 EF EF E0 FF
ASCx0230 E0 EF EF E1 EF EF EF FF F1 EE EF EF EC EE F0 FF
ASCx0240 EE EE EE E0 EE EE EE FF F1 FB FB FB FB FB F1 FF
ASCx0250 FE FE FE FE EE EE F1 FF EE ED EB E7 EB ED EE FF
ASCx0260 EF EF EF EF EF EE E0 FF EE E4 EA EA EE EE EE FF
ASCx0270 EE EE E6 EA EC EE EE FF F1 EE EE EE EE EE F1 FF
ASCx0280 E1 EE EE E1 EF EF EF FF F1 EE EE EE EA ED F2 FF
ASCx0290 E1 EE EE E1 EB ED EE FF F1 EE EF F1 FE EE F1 FF
ASCx02A0 E0 FB FB FB FB FB FB FF EE EE EE EE EE EE F1 FF
ASCx02B0 EE EE EE F5 F5 FB FB FF EE EE EE EA EA EA F5 FF
ASCx02C0 EE EE F5 FB F5 EE EE FF EE EE F5 FB FB FB FB FF
ASCx02D0 E0 FE FD F1 F7 EF E0 FF F1 F7 F7 F7 F7 F7 F1 FF
ASCx02E0 FF EF F7 FB FD FE FF FF F1 FD FD FD FD FD F1 FF
ASCx02F0 F1 EE FF FF FF FF FF FF FF FF FF FF FF FF E0 FF
ASCx0300 ED EA EA E2 EA EA ED FF FB F5 EE EE E0 EE EE FF
ASCx0310 E0 EF EF E1 EE EE E1 FF ED ED ED ED ED E0 FE FF
ASCx0320 F9 F5 F5 F5 F5 E0 EE FF E0 EF EF E1 EF EF E0 FF
ASCx0330 FB E0 EA EA E0 FB FB FF E0 EE EF EF EF EF EF FF
ASCx0340 EE EE F5 FB F5 EE EE FF EE EE EC EA E6 EE EE FF
ASCx0350 EA EE EC EA E6 EE EE FF EE ED EB E7 EB ED EE FF
ASCx0360 F8 F6 F6 F6 F6 F6 F6 FF EE E4 EA EA EE EE EE FF
ASCx0370 EE EE EE E0 EE EE EE FF F1 EE EE EE EE EE F1 FF
ASCx0380 E0 EE EE EE EE EE EE FF F0 EE EE F0 FA F6 EE FF
ASCx0390 E1 EE EE E1 EF EF EF FF F1 EE EF EF EF EE F1 FF
ASCx03A0 E0 FB FB FB FB FB FB FF EE EE EE F5 FB F7 EF FF
ASCx03B0 EE EA EA F1 EA EA EE FF E1 EE EE E1 EE EE E1 FF
ASCx03C0 EF EF EF E1 EE EE E1 FF EE EE EE E6 EA EA E6 FF
ASCx03D0 F1 EE EE F9 FE EE F1 FF EE EA EA EA EA EA E0 FF
ASCx03E0 F1 EE FE F8 FE EE F1 FF EA EA EA EA EA E0 FE FF
ASCx03F0 EE EE EE E0 FE FE FE FF C0 C0 C0 C0 C0 C0 C0 FF
ASCx0400 FF FF FF FF FF FF FF FF C7 C7 C7 C7 FF FF FF FF
ASCx0410 F8 F8 F8 F8 FF FF FF FF C0 C0 C0 C0 FF FF FF FF
ASCx0420 FF FF FF FF F8 F8 F8 F8 C7 C7 C7 C7 F8 F8 F8 F8
ASCx0430 F8 F8 F8 F8 F8 F8 F8 F8 C0 C0 C0 C0 F8 F8 F8 F8
ASCx0440 FF FF FF FF FF FF FF FF F3 F3 C0 D2 F3 F3 ED DE
ASCx0450 FF FF FF FF FF FF FF FF F3 E1 C0 F3 F3 F3 F3 F3
ASCx0460 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
ASCx0470 F7 F3 D1 C0 C0 D1 F3 F7 F3 F3 F3 F3 F3 C0 E1 F3
ASCx0480 FF FF FF FF C7 C7 C7 C7 C7 C7 C7 C7 C7 C7 C7 C7
ASCx0490 F8 F8 F8 F8 C7 C7 C7 C7 C0 C0 C0 C0 C7 C7 C7 C7
ASCx04A0 FF FF FF FF C0 C0 C0 C0 C7 C7 C7 C7 C0 C0 C0 C0
ASCx04B0 F8 F8 F8 F8 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0
ASCx04C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
ASCx04D0 FF FF FF FF FF FF FF FF F3 F3 F3 F3 F3 F3 F3 F3
ASCx04E0 FF FF FF C0 C0 FF FF FF FB F3 E2 C0 C0 E2 F3 FB
ASCx04F0 C7 DF DF D8 C2 FA FA FA FF FF FF FF FF FF FF FF
ASCx0500 FF FF FF FF FF FF FF FF FB FB FB FB FB FF FB FF
ASCx0510 F5 F5 F5 FF FF FF FF FF F5 F5 E0 F5 E0 F5 F5 FF
ASCx0520 FB F0 EB F1 FA E1 FB FF E7 E6 FD FB F7 EC FC FF
ASCx0530 FB F5 F5 F3 EA ED F2 FF F9 F9 FD FB FF FF FF FF
ASCx0540 FD FB F7 F7 F7 FB FD FF F7 FB FD FD FD FB F7 FF
ASCx0550 FF FB EA F1 EA FB FF FF FF FB FB E0 FB FB FF FF
ASCx0560 FF FF FF F3 F3 FB F7 FF FF FF FF E0 FF FF FF FF
ASCx0570 FF FF FF FF FF F3 F3 FF FF FE FD FB F7 EF FF FF
ASCx0580 F1 EE EC EA E6 EE F1 FF FB F3 FB FB FB FB F1 FF
ASCx0590 F1 EE FE F9 F7 EF E0 FF E0 FE FD F9 FE EE F1 FF
ASCx05A0 FD F9 F5 ED E0 FD FD FF E0 EF E1 FE FE EE F1 FF
ASCx05B0 F8 F7 EF E1 EE EE F1 FF E0 FE FD FB F7 F7 F7 FF
ASCx05C0 F1 EE EE F1 EE EE F1 FF F1 EE EE F0 FE FD E3 FF
ASCx05D0 FF F3 F3 FF FF F3 F3 FF F3 F3 FF F3 F3 FB F7 FF
ASCx05E0 FD FB F7 EF F7 FB FD FF FF FF E0 FF E0 FF FF FF
ASCx05F0 F7 FB FD FE FD FB F7 FF F1 EE FE FD FB FF FB FF
ASCx0600 EF F7 FB FF FF FF FF FF FF FF F1 ED ED ED F2 FF
ASCx0610 F7 F7 F1 F6 F6 F6 F1 FF FF FF F8 F7 F7 F7 F8 FF
ASCx0620 FE FE F8 F6 F6 F6 F8 FF FF FF F9 F6 F1 F7 F8 FF
ASCx0630 F9 F6 F7 E3 F7 F7 F7 FF FF FF F8 F6 F8 FE F1 FF
ASCx0640 F7 F7 F1 F6 F6 F6 F6 FF FD FF F9 FD FD FD F8 FF
ASCx0650 FE FF FE FE FE F6 F9 FF F7 F7 F6 F5 F3 F5 F6 FF
ASCx0660 F9 FD FD FD FD FD F8 FF FF FF E5 EA EA EA EA FF
ASCx0670 FF FF F1 F6 F6 F6 F6 FF FF FF F9 F6 F6 F6 F9 FF
ASCx0680 FF FF F1 F6 F6 F1 F7 FF FF FF F8 F6 F6 F8 FE FF
ASCx0690 FF FF F1 F6 F7 F7 F7 FF FF FF F8 F7 F9 FE F1 FF
ASCx06A0 F7 F7 E3 F7 F7 F6 F9 FF FF FF EE EE EE EE F1 FF
ASCx06B0 FF FF EE EE EE F5 FB FF FF FF EE EE EA EA F5 FF
ASCx06C0 FF FF EE F5 FD F5 EE FF FF FF F6 F6 F8 FE F1 FF
ASCx06D0 FF FF F0 FE F9 F7 F0 FF FE FD FD FB FD FD FE FF
ASCx06E0 F7 F7 F7 FF F7 F7 F7 FF EF F7 F7 FB F7 F7 EE FF
ASCx06F0 FF FF F7 F3 F0 FC FE FF F7 F3 E1 C0 E1 F3 FB FF
ASCx0700 FF FF ED EA E2 EA ED FF FF FF F1 FE F8 F6 F9 FF
ASCx0710 FF FF F8 F7 F1 F6 F1 FF FF FF ED ED ED ED E0 FE
ASCx0720 FF FF F9 F6 F8 FE F0 FF FF FF F9 F6 F1 F7 F8 FF
ASCx0730 FF FF FB F1 EA F1 FB FB FF FF F0 F7 F7 F7 F7 FF
ASCx0740 FF FF F6 F9 F9 F6 F6 FF FF FF F6 F6 F4 F2 F6 FF
ASCx0750 F9 FF F6 F6 F4 F2 F6 FF FF FF F6 F5 F3 F5 F6 FF
ASCx0760 FF FF FC FA F6 F6 F6 FF FF FF EE E4 EA EA EE FF
ASCx0770 FF FF F6 F6 F0 F6 F6 FF FF FF F9 F6 F6 F6 F9 FF
ASCx0780 FF FF F0 F6 F6 F6 F6 FF FF FF F8 F6 F8 FA F6 FF
ASCx0790 FF FF F1 F6 F1 F7 F7 F7 FF FF F8 F7 F7 F7 F8 FF
ASCx07A0 FF FF E0 FB FB FB FB FF FF FF F6 F6 F8 FE F1 FF
ASCx07B0 FF FF EA EA F1 EA EA FF FF FF F1 F6 F1 F6 F1 FF
ASCx07C0 FF FF F7 F7 F1 F6 F1 FF FF FF EE EE E6 EA E6 FF
ASCx07D0 FF FF F9 F6 FD FE F1 FF FF FF EA EA EA EA E0 FF
ASCx07E0 FF FF F1 FE F8 FE F1 FF FF FF D5 D5 D5 D5 C0 FE
ASCx07F0 FF FF F6 F6 F0 FE FE FF FF E7 E7 81 81 E7 E7 FF
</var>
<h2 id=Prelude style='position:absolute; top:0; left:40%; width:20%;'>Prepare…</h2>
<table id=Terminal style=display:none><tr valign=top>
<td colspan=2><pre style=position:absolute><br />
<textarea id=Assm rows=28 cols=108 style=visibility:hidden>
Intuitive clear mnemonic to quick memorize:
|Codes|Key|Elementary description__________
00 :Nil-Null of instructions queue / HLT
xA..xB:A/B-Add / Subtract
xC..xD:C/D-Conjunction / Disjunction
xE : E -Exclusive bitwise OR
A0..A7: A -Access to bytes
A8..AF:A/A-Access to ALU
B0..B7: B -Branches to nearest substitutes
B8..BF:B/F-Branches to near labels by flags
C0..C7: C -Increment
CA :RAL-Concatenate Access roll
CF :C/F-Complement for Carry Flag
D0..D7: D -Decrement
DA :RAR-Descended Access roll
DF :D/F-Data Formation by NOT
+EC/ED:Exclude operations by Counter/Data
F0..F9:F/x-Functions of BIOS-API
+FC/FD:Forcing operation by Counter/Data
FE :F/E-Fiction Execute / NOP
FF :F/F-Finalize the Function / RET
Simplest protection from errors in code:
Examples|Macros||Codes|Description
BE FF |RZ ||B2 FE|Microcode#4
BF FF |RNZ ||B2 FF|Microcode#5
BE FE |REPZ ||B3 FE|Microcode#6-
BF FE |REPNZ ||B6 FF|Microcode#14
CF BC FD|CLC ||B7 FE|Microcode#15
CF BD FD|STC ||B7 FF|Microcode#16
</textarea><br />
</pre><pre id='Instructions'></pre><pre id=Triggers style=position:absoluter></pre>
<input id=KeyBoard size=100 value='D000,36BF' type=text accessKey=K title='keyboard buffer [ALT+K]' onblur='cpu.watch.active=""' onfocus='cpu.watch.active="K"' /><span id=Context></span></td>
<!--pre id='commands'></pre></td-->
<td rowspan=2>
<pre id=Disassembly></pre>
<nobr><input id=Address size=13 style=color:cyan value='' type=text accessKey=P title='Pointer/Poking data [ALT+P]' onblur='cpu.watch.active=""' onfocus='cpu.watch.active="P"'
/><input id=Mnemonic size=27 style=color:lightgreen value='' type=text accessKey=T title='Translation/Translator [ALT+T]' onblur='cpu.watch.active=""' onfocus='cpu.watch.active="T"'
/><input id=Remark size=37 style=color:yellow value='' type=text accessKey=R title='Remark/Remote [ALT+R]' onblur='cpu.watch.active=""' onfocus='cpu.watch.active="R"' /></nobr>
<pre id=FILE:Xonix style=display:none>
ORG 0x0000
Xonix:
RET
</pre>
<pre id=FILE:Tetris style=display:none>
ORG 0x0000
Tetris:
RET</pre>
<pre id=BootSection style=display:none
alt='.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F'><!--
;F810:11 BF FF 11 BF 01 00 00 77 BF FF 77 BF 01
;F820:22 BF FF 22 BF 01 00 00 66 BF FF 66 BF 01
;F830:33 BF FF 33 BF 01 00 00 55 BF FF 55 BF 01
;F840:44 BF FF 44 BF 01 00 00
; Seq Blank X Y SX SY PX PY BELL SCREEN Mul78
;7650:00 00 00 00 00 00 41 19 08 03 F0 05 D0 76 E7 FD
; Val Page
;7660:DE FD CC FD 50 76
; ansistd outstd
;F800:A4 7F A5 02 5A
; F0
; 5A
; F0
; 5A
<!-- > ORG 0xFEFD
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP 7
NOP
NOP 1
HLT DL
MOV [0],AL
MOV [1],AL
NOP 2
MOV AL,[0]
MOV AL,[1]
NOP 3
MOV [7],AL
NOP 4
MOV AL,[7]
NOP 5
MOV [CL],AL
NOP 6
MOV AL,[AL]
<!--> DEBUG 0x00
<!-- ORG 0x0000
Zeroed: PUSH 0x0015
POP BX
MOV CL,0x09
LOOP CL
ADD BX,BX
MOV AL,0x01
LOOP 7
RCL AL
SKIP 3
DEC AL
DEC AL
DEC AL
DEC AL
NOP
ADD BX,BX
MOV AL,0x80
MOV CL,0x03
HLT CL
STR
MOV AL,0x81
MOV CL,0x03
HLT CL
STB
MOV AL,0x82
MOV CL,0x03
HLT CL
SKIP
INC AL
INC AL
INC AL
INC AL
MOV AL,0x83
MOV CL,0x03
HLT CL
SKIB
INC AL
INC AL
INC AL
INC AL
MOV AL,0x84
MOV CL,0x03
HLT CL
REP
INC AL
MOV AL,0x85
MOV CL,0x03
HLT CL
REB
INC AL
;;;;;;;;;;;;;;;;;
ORG 0xE000
INT_XX: NOP 1
NOP 2
NOP 3
NOP 4
NOP 5
NOP 6
NOP 7
SKIP 2
MOV AL,0x01
SKIP 1
SKIP 2
MOV AL,0x02
NOP
XCHG BX,[SP]
PUSH AX
MOV AL,[BX]
LOOP 4
RCR AL
BIA .basic
CMP AL,[BX]
BIF .basic
MOV AL,[BX+1]
SUB AL,0xF0
BIC .other
CMP AL,0x0A
BID .other
MOV AL,[BX]
INC BX
SKIP [AL]
NOP
JMP .memory
JMP .string
JMP .audio
JMP .data
JMP .unic
JMP .file
JMP .window
.basic: MOV AL,[BX]
SUB AL,0xF0
BIC .other
CMP AL,0x0A
BID .other
SKIP AL
JMP .x0
JMP .x1
JMP .x2
JMP .x3
JMP .x4
JMP .x5
JMP .x6
JMP .x7
JMP .x8
JMP .x9
.memory:NOP 1
.string:NOP 2
.audio: NOP 3
.data: NOP 4
.unic: NOP 5
.file: NOP 6
BIAS .exit
RET
.other: NOP
JMP .other
.window:MOV AL,[BX]
INC BX
SKIP [AL]
JMP .exit
JMP .putc
JMP .putxt
JMP .getc
JMP .exit
JMP .puthx
JMP .exit
JMP .exit
JMP .exit
JMP .exit
.putc: POP AX
XCHG BX,[SP]
PUSH BIOS.PutChr
RET
.putxt: HLT BX
PUSH BIOS.PutMsg
XCHG IP,[SP]
POP AX
XCHG BX,[SP]
RET
.getc: POP AX
XCHG BX,[SP]
PUSH BIOS.GetChar
RET
.puthx: POP AX
XCHG BX,[SP]
PUSH BIOS.PutHex
RET
.exit: NOP
JMP .exit
INTS: XCHG BX,[SP]
PUSH DX
PUSH AX
MOV DL,[BX]
AND DL,DL
BIE .halt
INC BX
MOV DH,DL
LOOP 4
RCR DH
CMP DL,DH
BIF .lo
AND DH,0x0F
CMP DH,0x08
BID .lo
MOV DL,[BX]
INC BX
.lo: CMP DL,0xFA
BID .hard
SUB DL,0xF0
BIC .hard
HLT DH
CALL .switch
DW .basic
DW .memory
DW .string
DW .audio
DW .data
DW .unic
DW .file
DW .window
.basic: NOP
.memory:NOP 1
.string:NOP 2
.audio: NOP 3
.data: NOP 4
.unic: NOP 5
.file: NOP 6
BASE .exit
RET
; 77+F0:
; 77+F1:
; 77+F2:AL=IsChar()
; 77+F3:AL=GetChr()
; 77+F4:
; 77+F5:PutHex(AL)
; 77+F6:
; 77+F7:
; 77+F8:PutMsg(BX)
; 77+F9:PutChr(CL)
.window:SKIP [DL]
JMP .exit
JMP ..putc
JMP ..putxt
JMP ..getc
JMP .exit
JMP .exit
JMP .exit
JMP .exit
..putc: POP AX,DX ; 77 F1
XCHG BX,[SP]
PUSH BIOS.PutChr
RET
..putxt:POP AX,DX ; 77 F2
HLT BX
PUSH BIOS.PutMsg
XCHG IP,[SP]
XCHG BX,[SP]
RET
..getc: POP AX,DX ; 77 F3
XCHG BX,[SP]
PUSH BIOS.GetChar
RET
.exit: POP AX,DX
XCHG BX,[SP]
RET
.hard: POP AX,DX
XCHG BX,[SP]
RET
.halt: POP AX,DX
INT 72
DB "\r\nHALT AT \0"
HLT BX
PUSH BIOS.PutPtr
XCHG IP,[SP]
PUSH BIOS.Prompt
RET
.switch:XCHG BX,[SP]
XCHG AL
ADD AL,AL
LEA BX,BX+AL
XCHG AL
PUSH [BX+0x00]
POP BX
XCHG BX,[SP]
RET
;;;;;;;;;;;;;;;;;;;;;;;
ORG 0x1000
;;;;;;;;;;;;;;;;;;;;;;;
ORG 0x0100
USER: ; USER API BY INT 0-9
RET
DEBUG 0x1
ORG 0xF7FF
NOP
;;;;;;;;;;;;;;;
ORG 0xF000
TIMER: MOV BH,0x77
MOV BL,0x1E
XCHG SP,BX
.x_____:MOV BL,0x30
._x____:MOV BH,0x30
.__x___:MOV CL,0x30
.___x__:MOV CH,0x30
.____x_:MOV DL,0x30
._____x:MOV DH,0x30
MOV AL,0xFF
.______:PUSH DX,CX
PUSH BX
POP [SP]
POP [SP]
POP [SP]
DEC AL
BIF .______
MOV AL,0x39
INC DH
CMP AL,DH
BID .______
INC DL
CMP AL,DL
BID ._____x
INC CH
CMP AL,CH
BID .____x_
INC CL
CMP AL,CL
BID .___x__
INC BH
CMP AL,BH
BID .__x___
INC BL
CMP AL,BL
BID ._x____
JMP .x_____
;;;;;;;;;;;;;;;
ORG 0xF600
SPEEDO: SKIP 5
MOV AL,CL
XOR AL,[BX]
MOV [BX],AL
DEC BX
CMP DH,BH
MOV DH,0x76
MOV DL,0xD4
XCHG SP,DX
.x___: MOV CL,0x30
._x__: MOV CH,0x30
.__x_: MOV BL,0x30
.___x: MOV BH,0x30
.____: XOR AL,AL
MOV DH,AL
MOV DL,AL
ADD DX,SP
PUSH BX,CX
MOV BH,0x7F
MOV BL,0xF3
MOV CL,0x7F
.loop: XOR AL,AL
;CMC
HLT 7
WAIT
NOP 5
CMP BH,DH
BIF .loop
POP CX,BX
MOV AL,0x39
INC BH
CMP AL,BH
BID .____
INC BL
CMP AL,BL
BID .___x
INC CH
CMP AL,CH
BID .__x_
INC CL
CMP AL,CL
BID ._x__
JMP .x___
;;;;;;;;;;;;;;;;;
ORG 0xF700
SPEEDY: MOV DH,0x76
MOV DL,0xD4
XCHG SP,DX
.x___: MOV CL,0x30
._x__: MOV CH,0x30
.__x_: MOV BL,0x30
.___x: MOV BH,0x30
.____: XOR AL,AL
MOV DH,AL
MOV DL,AL
ADD DX,SP
PUSH BX,CX
MOV BH,0x7F
MOV BL,0xF3
.loop: MOV AL,[BX]
XOR AL,0x7F
MOV [BX],AL
DEC BX
CMP BL,DL
BID .loop
CMP BH,DH
BIF .loop
POP CX,BX
MOV AL,0x39
INC BH
CMP AL,BH
BID .____
INC BL
CMP AL,BL
BID .___x
INC CH
CMP AL,CH
BID .__x_
INC CL
CMP AL,CL
BID ._x__
JMP .x___
;;;;;;;;;;;;;;;;;
ORG 0xF300
Help:
.List: DB "\n[A]BAC - CALCULATOR\r"
DB "\n[B]OOT - DOS-BOOTER\r"
DB "\n[C]OPY - COPY MEMORY\r"
DB "\n[D]UMP - DUMP OF MEMORY\r"
DB "\n[E]DIT - EDIT DUMP\r"
DB "\n[F]IND - FIND IN MEMORY\r"
DB "\n[G]OTO - GOTO ADDRESS\r"
DB "\n[I]DLE - STREAM ECHO\r"
DB "\n[J]OIN - JOIN\r"
DB "\n[K]EEP - KEEP\r"
DB "\n[L]IST - FILE LIST\r"
DB "\n[M]OVE - MOVE MEMORY DATA\r"
DB "\n[N]OTE - NOTE\r"
DB "\n[O]PEN - OPEN\r"
DB "\n[Q]UIT - REBOOT\r"
DB "\n[R]EAD - READ\r"
DB "\n[S]AVE - SAVE\r"
DB "\n[T]EXT - TEXT\r"
DB "\n[U]NIT - DEVICES LIST\r"
DB "\n[V]ANE - CPU FANS OUT\r"
DB "\n[W]AVE - WAVE\r"
DB "\n[X]TRA - EXTRA\r"
DB "\n[Y]AMP - Y-AMPLITUDE\r"
DB "\n[Z]ERO - CLEAR MEMORY\0"
ORG 0xF800
BIOS: MOV! BH,0x76
MOV BL,0xCE
XCHG SP,BX
PUSH 0x7600
POP BP
PUSH 0xE000
POP BX
MOV AL,0xF7
CMP AL,0xF0
MOV [AL],BL
ADD AL,0x08
;CMC
MOV [AL],BH
LOOP 4
INT 72
DB "\_X80-BIOS V0.1\0"
.prompt:
PUSH BX
MOV BH,0x76
MOV BL,0xCE
XCHG SP,BX
PUSH 0x7600
POP BP
;
MOV DH,0xFF
HLT DH
MOV DL,0xDB
MOV! AL,0x00
OUT DL,AL
IN DL
PUSH .OutDec
XCHG IP,[SP]
INT 72
DB "\r\n/>\0"
..cmd: INT 73
CMP AL,0x5B
BID ..cmd
MOV CL,AL
SUB AL,0x41
BIC ..cmd
HLT CL
INT 71
PUSH .words
POP BX
ADD AL,AL
ADD AL,AL
MOV DL,AL
XOR DH,DH
LEA BX,DX+BX
PUSH [BX+2]
PUSH [BX+0]
POP BX
MOV CL,0x03
..loop: MOV AL,BH
ROR AL
ROR AL
AND AL,0x1F
ADD AL,0x40
HLT AL
INT 71
LOOP 5
ADD BX,BX
DEC CL
BIF ..loop
POP DI
HLT AL
MOV AL,0x20
INT 71
PUSH ..hexas
POP SI
XOR CH,CH
MOV CL,0x01
..hexa: PUSH [SI+0x00]
POP BX
MOV AL,CH
AND AL,CL
ADD AL,0xFF
PUSH .GetHex
XCHG IP,[SP]
SBB DL,DL
CMP AL,0x0D
BIE ..next
CMP AL,0x1B
BIE .prompt
CMP AL,0x7F
BIF ..next
NOT! CH
OR CH,CL
NOT CH
RAR CL
AND CL,CL
;JZ .prompt
;CMP CL,0x01
BIE ..hexa
MOV AL,CH
AND AL,CH
BIE ..clr
MOV AL,0x08
HLT AL
INT 72
DB "\< \<\0";>
CMP CL,0x01
BIE ..hexa
..clr: XCHG SI,BX
DEC BX
DEC BX
XCHG SI,BX
BIF ..hexa
..next: HLT AL
INT 71
ADD DL,DL
BID ..next1
PUSH BX
POP [SI+0x00]
XCHG SI,BX
INC BX
INC BX
XCHG SI,BX
OR CH,CL
..next1:ADD CL,CL
CMP AL,0x0D
BIF ..hexa
..exec: PUSH ..hexas
POP SI
PUSH [SI+0x04]
PUSH [SI+0x02]
PUSH [SI+0x00]
MOV DL,0xDB
MOV AL,0xFF
OUT DL,AL
MOV AL,CH
ADD AL,CL
ADD AL,CL
POP BX,DX
POP CX
PUSH DI
XCHG IP,[SP]
XOR AL,AL
BIE .prompt
NOP 7
SBB DL,DL
CMP AL,0x7F
XOR AL,AL
BIE .prompt
INT 71
PUSH 0x76D0
PUSH 0x78FF
POP DX,BX
PUSH! .HexDmp
XCHG IP,[SP]
PUSH .hello
POP BX
PUSH .PutMsg
HLT BX
XCHG IP,[SP]
PUSH .PutPtr
XCHG IP,[SP]
; MOV DL,0x08
; MOV DH,0x06
; INT 71
; INT 9S
; HLT 3
..hexas:DW 0x0000
DW 0x0000
DW 0x0000
DW 0x0000
DW 0x0000
DW 0x0000
DW 0x0000
DW 0x0000
.loopy: PUSH .PutChr
PUSH .GetChar
XCHG IP,[SP]
HLT AL
XCHG IP,[SP]
CMP AL,0x60
;JZ .stop
CMP AL,0x0D
BIF .loopy
INT 72
DW 0x0808
DW 0x0808
DB 0x08
DB ":\0"
PUSH TX
POP BX
PUSH .PutPtr
XCHG IP,[SP]
JMP .loopy
.stop: PUSH? BIOS.API.fn
XCHG IP,[SP]
HLT
HLT
NOP 5
.hello: DB "\h\^\^BIOS\r\n/>\0"
.words: DW 0x0823,..none ;ABAC
DW 0x3DF4,..none ;BOOT
DW 0x3E19,..none ;COPY
DW 0x55B0,.HexDmp ;DUMP
DW 0x1134,..none ;EDIT
DW 0x25C4,..none ;FIND
DW 0x3E8F,..Goto ;GOTO
DW 0x1590,..Help ;HELP
DW 0x1185,..Idle ;IDLE
DW 0x3D2E,..none ;JOIN
DW 0x14B0,..none ;KEEP
DW 0x2674,..List ;LIST
DW 0x3EC5,..none ;MOVE
DW 0x3E85,..none ;NOTE
DW 0x40AE,..none ;OPEN
DW 0x3039,..none ;PLAY
DW 0x5534,0xF800 ;QUIT
DW 0x1424,..none ;READ
DW 0x06C5,..none ;SAVE
DW 0x1714,..none ;TEXT
DW 0x3934,..none ;UNIT
DW 0x05C5,..none ;VANE
DW 0x06C5,..none ;WAVE
DW 0x5241,..xtra ;XTRA
DW 0x06F0,..pan ;YAwP
DW 0x164F,..Zero ;ZERO
..pan: SKIP 5
MOV DL,AL
MOV AL,[BX]
MOV [BX],DL
ADD BX,CX
CMC
WAIT
INT 50
MOV BH,0x7F
MOV BL,0XF3
MOV CH,0xFF
MOV CL,0xB2
...loop:PUSH BX
MOV DH,0x4E
...rows:PUSH DX,BX
MOV DH,0x1E
HLT DH
WAIT
INT 0
POP BX,DX
DEC BX
DEC DH
JNZ ...rows
POP BX
JMP ...loop
;;;;;;;;;;;;;;;;;;;;;;;;;
..Edit: INT 72
DB "\r\n"
..Goto: PUSH BX
RET
..Help: PUSH! Help.List
POP BX
HLT BX
PUSH BIOS.PutMsg
RET
..none: INT 72
DB "\n!!! RESERVED DIRECTIVE\0"
RET
..xtra: XCHG! SP,BX
LOOP DL
PUSH EX
XCHG SP,BX
RET
..List: PUSH .FileIn
RET
..Zero:
..Idle: INT 73
CMP AL,0x1B
RZ
HLT AL
INT 71
BIF ..Idle
.GetHex:PUSH CX
SBB CH,CH
BIC ..addr
..inkey:INT 73
CMP AL,0x08
BIE ..back
CMP AL,0x20
BIE ..addr
CMP AL,0x30
BIE ..exit
CMP AL,0x7F
BIE ..clear
CMP AL,0x47
BID ..exit
CMP AL,0x3A
BIC ..nibble
CMP AL,0x41
BIC ..exit
SUB AL,0x07
..nibble:AND AL,0x0F
LOOP 4
ADD BX,BX
OR BL,AL
..addr: AND CH,CH
BIE ..ptr
INT 72
DB "\<\<\<\<\0";>
..ptr: HLT BX
PUSH .PutPtr
XCHG IP,[SP]
OR CH,0xFF
BIF ..inkey
..exit: ADD CH,CH
POP CX
RET
..clear:ADD CH,CH
POP CX
RNC
INT 72
DB "\< \<\< \<\< \<\< \<\0";>
AND AL,AL
RET
..back: HLT BH
XCHG
HLT BL
XCHG
XCHG BL,BH
LOOP 4
ADD BX,BX
XCHG BL,BH
HLT BH
XCHG
HLT BL
XCHG
AND BL,BL
JMP ..addr
.OutDec:;;;;;;;;;;;;;;;;;;
PUSH AX
PUSH CX
XCHG AL
HLT CL
MOV CL,0x09
MOV CH,CL
INC CH
WAIT
ADD AL,0x9C
ADD AL,0x64
SUB CH,CL
ADD CH,0x30
HLT CH
CALL .PutChr
HLT CL
MOV CL,0x09
MOV CH,CL
INC CH
WAIT
ADD AL,0xF6
ADD AL,0x0A
SUB CH,CL
ADD CH,0x30
HLT CH
CALL .PutChr
CALL .PutHex.nibble
POP CX
POP AX
RET
;;;;;;;;;;;;;;;;;;
.MulBxD:
;;;;;;;;;;;;;;;;;;
.TestBX:CMP BL,DL
RNZ
CMP BH,DH
RET
.HexDmp:PUSH BX
PUSH AX
..addr: HLT BX
CALL .PutPtr
AND BL,0xF0
..loop: MOV AL,0x20
HLT AL
CALL .PutChr
MOV AL,[BX]
CALL .PutHex
CALL .TestBX
BIE ..end
INC BX
MOV AL,BL
AND AL,0x0F
BIF ..loop
MOV AL,0x0D
CALL .PutChr
MOV AL,0x0A
CALL .PutChr
BIE ..addr
..end: POP AX
POP BX
RET
.PutMsg:PUSH BX
PUSH AX
PUSH
POP BX
HLT AL
..loop: MOV AL,[BX]
INC BX
AND AL,AL
CIF .PutChr
BIF ..loop
POP AX
XCHG BX,[SP]
POP
RET
.PutPtr:PUSH BX
PUSH AX
PUSH
POP BX
HLT AL
PUSH .PutHex
PUSH [SP+0x00]
MOV AL,BH
XCHG IP,[SP]
MOV AL,BL
XCHG IP,[SP]
POP AX
POP BX
RET
.PutHex:PUSH AX
PUSH .PutChr.reada
XCHG AL
PUSH AX
LOOP 4
RAR AL
CALL ..nibble
POP AX
..nibble:AND AL,0x0F
CMP AL,0x0A
BIC ..number
ADD AL,0x07
..number:ADD AL,0x30
HLT AL
.PutChr:PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH BP
XCHG CL
PUSH [BP+0x64]
POP BP
MOV CH,[BP+0x0]
AND CH,CH
CALL ..main
PUSH BX
POP [BP+0x4]
PUSH [BP+0x8]
POP DX
ADD BX,DX
PUSH [BP+0xC];3
POP DX;1
DEC AL;1
DEC DX;1
XCHG BX,DX ;2
MOV AL,DL ;2
..exit: MOV [BX],AL ;1
DEC BX ;1
MOV [BX],DH ;1
..leave:MOV AL,CH
..ready:MOV [BP+0x0],AL
POP BP
POP DX
POP CX
POP BX
..reada:POP AX
RET
..main: PUSH [BP+0x4]
POP BX
PUSH [BP+0x6]
POP DX
BIF ..ansi
MOV AL,CL
CMP AL,0x1B
BIF ..out
MOV [BP+0xFF],CH
DEC CH
RET
..left: DEC BL
RNS
MOV BL,DL
DEC BL
..up: DEC BH
RNS
MOV BH,DH
DEC BH
RET
..right:INC BL
CMP BL,DL
RC
XOR BL,BL
..down: INC BH
CMP BH,DH
RC
XOR BH,BH
RET
..clrscr:XOR CL,CL
MOV BH,CL
MOV BL,CL
INC BH
...loop:CALL ..put
BIF ...loop
DEC DL
..home: XOR BH,BH
..return:MOV AL,0x20
..set_x:SUB AL,0x20
...loop:MOV BL,AL
SUB AL,DL
BID ...loop
XOR CH,CH
RET
..quit: BE ..exit
..out: CMP AL,0x0A
BIE ..scroll
CMP AL,0x0D
BIE ..return
CMP AL,0x08
BIE ..left
CMP AL,0x18
BIE ..right
CMP AL,0x19
BIE ..up
CMP AL,0x1A
BIE ..down
CMP AL,0x0C
BIE ..home
PUSH [BP+0x12]
RET
;..clear:JZ ..clrscr
..put: PUSH BX
PUSH CX
PUSH [BP+0xE]
XCHG IP,[SP]
POP CX
MOV AL,[BP+0x3]
ADD AL,CL
MOV [BX],AL
POP BX
INC BL
..tab: CMP BL,DL
RC
XOR BL,BL
..scroll:INC BH
CMP BH,DH
RC
MOV BH,DH
DEC BH
PUSH BX
XOR BL,BL
PUSH BX
PUSH [BP+0xE]
XCHG IP,[SP]
XCHG BX,[SP]
INC BH
PUSH [BP+0xE]
XCHG IP,[SP]
POP CX
SUB CX,BX
;SKIP 5
...rows:FIX! 50
ADD BX,CX
CMC
MOV DL,AL
MOV AL,[BX]
MOV [BX],DL
HLT 2
CMC!
;INT 50
; DEC DH
; JNZ ...rows
HLT DH
...cols:PUSH DX
PUSH BX
MOV AL,[BP+0x3]
FLY 0
POP BX
POP DX
INC BX
DEC DL
BIF ...cols
POP BX
MOV CH,DL
RET
..ansi: MOV AL,CL
CMP CH,0xF3
BID ..code
DEC CH
CMP CH,0xF0
BIE ..set_x
BID ..set_y
INC CH
PUSH [BP+0xE]
RET
..code: MOV AL,CL
CMP AL,0x3A
BID ..set_y.call
SUB AL,0x30
BIC ..set_y.call
MOV CL,AL
POP AX
MOV BL,CH
XOR BH,BH
ADD BX,BP
MOV AL,[BX]
ADD AL,AL
ADD AL,AL
ADD AL,[BX]
ADD AL,AL
ADD AL,CL
XOR DH,DH
BIE ..quit
..outstd:PUSH ..clrscr
CMP CL,0x1F
RZ
CMP CL,0x09
BIE ...tab
POP [SP+0]
PUSH ..put
RET
...std: MOV CH,0xF2
CMP AL,0x59
RZ
XOR CH,CH
RET
...tab: POP [SP+0x00]
OR BL,0x07
INC BL
BIF ..tab
..set_y:SUB AL,0x20
...loop:MOV BH,AL
SUB AL,DH
BID ...loop
RET
...call:PUSH [BP+0x10]
XCHG IP,[SP]
PUSH [BP+0x4]
POP BX
RET
..mul78:PUSH [BP+0x8]
POP CX
ADD BX,CX
MOV AL,BL
MOV BL,BH
XOR BH,BH
ADD BX,BX
MOV CH,BH
MOV CL,BL
ADD BX,BX
ADD BX,BX
ADD BX,CX
ADD BX,BX
ADD BX,BX
ADD BX,BX
SUB BX,CX
XOR CH,CH
MOV CL,AL
ADD BX,CX
PUSH [BP+0xC]
POP CX
ADD BX,CX
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DL = Port Index[7F:PortIn]
; AL = Data
; DBG 0x01
; BRK 0x01
.PortIO:PUSH DX
CMP DL,0x80
SBB DH,DH
ADD DL,0x81
BIE ..input
XCHG SP,DX
DEC SP
BIB ..lower
INC SP
MOV [SP+127],AL
BIA ..ready
..lower:MOV [SP+128],AL
BIB ..ready
..input:CMP AL,0x80
SBB DH,DH
ADD AL,0x81
MOV DL,AL
XCHG SP,DX
BIE ..ready
BIA ..higher
DEC SP
MOV AL,[SP+128]
BIB ..ready
..higher:MOV AL,[SP+127]
..ready:XCHG SP,DX
POP DX
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CX - Register Index
; DX - Register Data
.CPU_In:PUSH CX
PUSH BX
XOR BH,BH
MOV BL,BH
DEC BX
XCHG SP,BX
.loop: POP DX
DEC CX
MOV AL,CL
OR AL,CH
BIF .loop
XCHG SP,BX
POP BX
POP CX
RET
;;;;;;;;;;;;;;;;;;;;;;
.PortIn:PUSH BX
BIAS ..input
POP BX
MOV BL,AL
XCHG BP,BX
..input:MOV AL,[BP+0]
XCHG BP,BX
POP BX
RET
;;;;;;;;;;;;;;;;;;;;;;
.WaitOut:PUSH BX,CX;DL = Data
XCHG CL
BIAS ..input
POP BX
MOV BL,AL
XCHG BP,BX
SUB AL,AL
HLT CL
WAIT
..input:MOV [BP+0],DL
ADD CL,0xFF
XCHG BP,BX
POP CX,BX
RET
.WordOut:
;;;;;;;;;;;;;;;;;;;;;;
.OutByte:PUSH DX,AX;XH = Time, XL = Port, AL = Byte
PUSH
POP DX
CALL ..next
POP AX,DX
RET
..next: PUSH AX
LOOP 4
RCR AL
CALL ..loop
POP AX
..loop: AND AL,0x0F
ADD AL,0xC0
.Output:PUSH DX,BX;XH = Time, XL = Port, AL = Data
PUSH
POP DX
BIAS ..loop
POP BX
MOV BL,DL
XCHG BP,BX
SUB DL,DL
HLT DH
WAIT
..loop: MOV [BP+0],AL
ADD DH,0xFF
XCHG BP,BX
POP BX,DX
RET
;;;;;;;;;;;;;;;;;;;;;;
.FileIn:INT 72
DB "\r\nFILE LIST - \0"
MOV! DL,0xFD
MOV DH,0x02
HLT DX
MOV AL,0x00
CALL .OutByte
MOV AL,0x00
CALL .OutByte
MOV AL,0xD3
CALL! .Output
CALL .WaitIn
..loop: PUSH AX
INT 72
DB "\r\n#\0"
HLT AL
PUSH BIOS.PutHex
XCHG IP,[SP]
INT 72
DB " - \0"
MOV AL,0xFD
MOV CL,0x02
MOV DL,0x00
HLT CL
CALL .WaitOut
CALL .WaitOut
CALL .WaitOut
MOV DL,[SP+0]
AND DL,0x0F
OR DL,0xC0
CALL .WaitOut
MOV DL,0xD1
CALL .WaitOut
..print:CALL .WaitIn
HLT AL
INT 71
BIC ..print
HLT
;;;;;;;;;;;;;;;;;;;;;;
.WaitIn:PUSH BX,CX
XCHG CL
BIAS ..input
POP BX
MOV BL,AL
XCHG BP,BX
SUB AL,AL
HLT CL
WAIT
..input:MOV! AL,[BP+0]
ADD CL,0xFF
XCHG BP,BX
POP CX,BX
RET
;;;;;;;;;;;;;;;;;;;;;;
.GetChar:XOR AL,AL
..loop: CALL .Inkey
BID ..loop
PUSH AX
PUSH CX
MOV CL,0x50
MOV CH,0xF0;01;0xF0
XOR AL,AL
CE .beep
POP CX
POP AX
RET
.Inkey: PUSH DX
MOV AL,0x7F
MOV DL,0xFD
MOV DH,0x80
HLT! DH
IN DL
MOV AL,DL
;;;;;;; PUSH BIOS.WaitIn
;;;;;;; XCHG IP,[SP]
POP DX
RET
.beep: PUSH DX
MOV DL,0x0A
MOV AL,CL
PUSH .PortIO
XCHG IP,[SP]
MOV AL,CH
LOOP AL
NOP
PUSH .PortIO
XCHG IP,[SP]
POP DX
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-->
ORG 0xFEFA
KERM: NOP 1
NOP 1
NOP 1
NOP 1
NOP 1
NOP 1
ORG 0xFEFE
KERN: MOV [0],AL
JMP .overhead ; Запрос к стандартному API
JMP .acclaim ; Обращение к программным прерываниям INT 0-79
JMP .buffer ; Буферная зона - прослойка диспетчера памяти
JMP .context_next ; Диспетчер переключения контекста процессов
JMP .device ; Запрос ко внешнему устройству ввода/вывода
JMP .error ; Обработчик программных/аппаратных ошибок
JMP .force ; Внешние форсированные события/прерывания
.garret:MOV DL,0x00 ; Загрузочная область поверхностного уровня
MOV DH,0xD0
MOV BX,DX
XCHG SP,DX
..scan: XOR AL,AL
MOV [SP+AL-1],BH
MOV CH,[SP+AL-1]
MOV CL,0xF0
MOV CH,0xF8
PUSH BX
..load: INC AL
ADD BL,0x10
MOV [0],AL
MOV DL,[BX]
MOV DH,[BX+1]
MOV [CL],DL
MOV [CH],DH
OR DL,DH
JNZ ..load
MOV AL,0x80
POP BX
.context:PUSH AX
PUSH BX
.context_next:
..next: INC AL
ADD BL,0x10
MOV DL,[BX+2]
MOV DH,[BX+3]
MOV [6],DL
MOV [7],DH
MOV CL,[BX]
MOV CH,[BX+1]
OR CL,CH
JNZ KERN
POP BX
POP AX
JMP .context
.device:JC ..write
PUSH AX
XOR AL,AL
MOV [0],AL
POP AL
MOV CH,0xFF
HLT CH
IN AL
PUSH AL
SBB CH,CH
POP AX
CMP AL,CH
JMP KERN
..write:PUSH AX
XOR AL,AL
MOV [0],AL
POP AL
MOV CL,AL
POP AL
MOV CH,0xFF
HLT CH
OUT CL,AL
POP AX
JMP KERN
.overhead:
.acclaim:
.buffer:
.error:
.force: PUSH BX,AX
MOV BH,0x7F
MOV BL,0xEE
MOV AL,[BX]
INC AL
MOV [BX],AL
POP AX,BX
CMP AL,AL
CMC
JMP KERN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0x7650
DW 0x0000 ; Value .Sequency
DW 0x0000 ; Page .Blank
DW 0x0000 ; PosY .PosX
DW 0x1E48;0x1E4E; 0x1940 ; Rows .Columns
DW 0x0000;0x0308 ; FromY .FromX
DW 0x05F0 ; Bell .Tone
DW 0x76D0
DW BIOS.PutChr.mul78
DW BIOS.PutChr.OutStd.std
DW BIOS.PutChr.OutStd
DW 0x7650
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0xD000
PROCESS:DW 0x0000,0x0000 ;#0
DW 0xF800,0xFFFF ;#1
DW 0xF000,0x000 ;#2
DW 0x0000,0x0000
ORG 0xD000
DW 0x0000,0x0000
DB " "
DW 0xF800,0xFFFF
DB " "
DW 0x0000,0x0000
DB " "
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0xFF00
; NOP
; NOP 1
; RIE
ORG 0x0000
SCRO: PUSH 0x76D0
POP DX
SCROLL: MOV SP,DX
XCHG BX,[SP]
INC DX
CMP DH,0x80
JNZ SCROLL
JMP SCRO
;<!-- -->
</pre>
</td>
<td rowspan='2'><pre>
Rebused Instructions Set Computer Emulator
</pre><hr /><pre>
F1: Step / ^Cycle / $Stop
F3: ^Push IP / $Pop IP
F4: Start/Stop / $Start
F5: Assembly / ^Reset
F6: Rewind IP/Speed/Cycles
F7: Toggle switch
F8: Forward IP/Speed/Cycles
F9:
Break: Toggle break-point
</pre><hr /><pre>
$ - Shift+
^ - Ctrl+
@ - Alt+
</pre><hr /><pre>
Intuitive clear mnemonic to quick memorize
|Codes|Key|Elementary description_________
00 :Nil-Null of instruction queue / HLT
xA..xB:A/B-Add / Subtract
xC..xD:C/D-Conjunction / Disjunction
xE : E -Exclusive bitwise OR
A0..A7: A -Access to bytes
A8..AF:A/A-Access to ALU
B0..B7: B -Branches to nearest substitutes
B8..BF:B/F-Branches to near labels by flag
C0..C7: C -Increment
CA :RAL-Concatenate Access roll
CF :C/F-Carry Flag complement
D0..D7: D -Decrement
DA :RAR-Descended Access roll
DF :D/F-Data Formation by NOT
EE :E/E-Exchange
F0..F9:F/x-Functions of BIOS-API
FE :F/E-Fiction Execute / NOP
FF :F/F-Finalize the Function / RET
+EC/ED:Exclude operations by Counter/Data
+FC/FD:Forcing operation by Counter/Data
+EF :E/F-Enter register Feature
+FF :F/F-Flush register Feature
Simplest protection from errors in code:
Examples|Macros
CF BC FD|CLC ; Clear the Carry Flag
CF BD FD|STC ; Store the Carry Flag
BE FF |RZ ; Return by Zero Flag
BF FF |RNZ ; Return by no Zero Flag
</pre>
</td>
</tr>
<tr valign=top><td><canvas id=Display style=position:absolute onblur='cpu.watch.active=""' onfocus='cpu.watch.active="S"'></canvas><pre id=Screen style=width:40em></pre>
<span style='background-color:silver; display:inline-block; color:black; height:33em'>
</span>
</td>
<td style='background-color:silver; color:black'>
<select id=Selector></select><button id=Action value=Files></button><br />
<select id=Repeats>
<option value='0x0000'>No Loop</option>
<option value='0x2000'>Loop+</option>
<option value='0x3000'>Wait+</option>
</select>
<select id=Prefixes>
<option value='-1'>Auto Prefix</option>
<option value='0x0000'>Regular</option>
<option value='0x0100'>11+</option>
<option value='0x0200'>22+</option>
<option value='0x0300'>33+</option>
<option value='0x0400'>44+</option>
<option value='0x0500'>55+</option>
<option value='0x0600'>66+</option>
<option value='0x0700'>77+</option>
<option value='0x4800'>00+</option>
<option value='0x00FE'>+FE</option>
<option value='0x00FF'>+FF</option>
</select>
<pre id=state></pre>
</td>
</tr></table>
<textarea id='Files' cols='80' rows='50'>
FILE XONIX
ORG 0x0100
Xonix: PUSH 0xF800
POP BX
RET
;NEXT-FILE;
FILE TETRIS
ORG 0x0100
Tetris: INC BX
RET
</textarea>
<!--
i8275 CRT-Controller: Simply version
00000000:
000000nn:
000001nn:
00001nnn:
0001nnnn:
0010nnnn:
0100nnnn: Lines [1..16]-1
01nnnnnn: Rows [16..64]-1
1000nnnn:
1nnnnnnn: Cols [16..80]-1
1101nnnn:
1110nnnn:
1111nnnn:
40..4F: Set Lines [1..16]
50..7F: Set Rows [16..64]
90..CF: Set Cols [16..80]
=== PORTS ===
SP:0000
[SP-1] =FFFF -> Port $FF
[SP-128]=FF80 -> Port $80
SP:FFFF
[SP+1] =0000 -> Port $00
[SP+127]=007E -> Port $7E
;;;;;;;;
; DL = Port Index[7F:PortIn]
; AL = Data
PortIO: PUSH DX
CMP DL,128
SBB DH,DH
ADD DL,129
JZ .input
XCHG SP,DX
JNS .lower
MOV [SP+127],AL
JS .ready
.lower: MOV [SP-128],AL
JNS .ready
.input: CMP AL,128
SBB DH,DH
ADD AL,129
MOV DL,AL
JZ .ready
XCHG SP,DX
JS .higher
MOV AL,[SP-128]
JNS .ready
.higher:MOV AL,[SP+127]
.ready: XCHG SP,DX
POP DX
RET
;;;;;;;;;;;;;;;;;;;;;;;;;
Port #253 #0xFD #-3 : Keyboard Code
;;;;;;;;;;;;;;;;;;;;;;;;;
x0 x1 x2 x3 x4 x5 x6 x7
-- BP SI DI SP BX CX DX
55 76 -> PREFIX BX + MOV CL,DL -> PREFIX BX + MOV CX,DX -> LEA BX,[CX+DX]
55 21 -> PREFIX BX + MOV BH,CH -> PREFIX BX + MOV BP,SI -> LEA BX,[BP+SI]
55 10 -> PREFIX BX + MOV [BX],BH -> PREFIX BX + MOV XX,BP -> LEA BX,[[SP]+BP]
/////////////////////////////////////////////////////////////////////////////
Service Registers:
==================
1. Select the service segment:
1.1. Set SP to 0x0001
1.2. Set APR (one of BX,CX,DX) to wanted index
1.3. Do PUSH instruction of this APR
2. Select the service register:
2.1. Set SP to 0x0000
2.2. Set AL to wanted index
2.3. Do PUSH AX
2.4. If wanted index greater than 256, repeat the step #2.3 many times
3. Write to service register:
3.1. Set SP to 0x0000
3.2. Do PUSH instruction with any of APR (BX,CX,DX)
4. Read the service register:
4.1. Set SP to 0xFFFF
4.2. Do POP instruction with any of APR (BX,CX,DX)
-F80..-FFF: Service Layer #1
0000..00FF: Service Layer #0
0100..01FF: 6502-Stack Mode
0200..FDFF: Regular Stack
FE00..FEFF: Service Layer #2
FF00..FFFF: Service Layer #3
+000..+07E: Service Layer #1
00000000XXXXXXXX: Service Layer #0
00000001XXXXXXXX: 6502-Stack Layer
XXXXXXXXXXXXXXXX: Regulat Stack Layer
11111110XXXXXXXX: Service Layer #2
11111111XXXXXXXX: Service Layer #3
┌───┬───┬───┬───┬───┬───┬───┬───┐┌───┬───┬───┬───┬───┬───┬───┬───┐┌───┬───┬───┬───┬───┬───┬───┬───┐
│ - - - - - - - - ││ 0 └──SRC──┘ 0 └──DST──┘ ││ - - - - - - - - │:
└───────────────────────────────┘└───────────────────────────────┘└───────────────────────────────┘
SPCZ
0000
0001
0010
0011
0100
0110
1000
1010
1100
1110
0###sP?Z| Parity Zero:
0###Sp?Z| Signed Zero:Skip # instructions
0###SP?Z| Spouts Zero:Loop instruction # times
1###sP?Z| Parity Zero:
1###Sp?Z| Signed Zero:Skip # instructions
1###SP?Z| Spouts Zero:Loop instruction # times
LOOP :
LOOP n:Loop instruction n-times |FX=0nnn11?1
LOOP R:Loop instruction R-n time|FX=1rrr11?1
MOV R:Using R-register |FX=1rrr????
NOP n:Skip n instructions |FX=0nnn10?1
Bx nn: 0000..007F FF80..FFFF
11 Bx nn: 0100..017F 0080..00FF
22 Bx nn: 0200..027F 0180..01FF
33 Bx nn: 0300..037F 0280..02FF
44 Bx nn: Services
55 Bx nn: FD00..FD7F FC80..FCFF
66 Bx nn: FE00..FE7F FD80..FDFF
77 Bx nn: FF00..FF7F FE80..FEFF
Fn: |Basic library:
11 Fn: |Memory library:
22 Fn: "|String library:
33 Fn: #|Sound library:
44 Fn: D|Data process:
55 Fn: U|
66 Fn: f|File system:
77 Fn: w|Window service:
////////////////////////////////////////////////////////////////////////////////
EX-Register
__ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
00:Ячейки управления распределением страниц памяти|RAM Dispatcher
10:Ячейки управления распределением страниц памяти|RAM Dispatcher
20:Ячейки управления ловушками в процессе отладки-|Debug Managing
30:Счётчики тактов, циклов, прерываний и т.д.-- --|Process Counters
40:JP>>LO>> ++ .. -- -- -- JP>>HI>> ++ .. -- -- --|JP-File
50:SP>>LO>> ++ .. -- -- -- SP>>HI>> ++ .. -- -- --|SP-File
60:BP>>LO>> ++ .. -- -- -- BP>>HI>> ++ .. -- -- --|BP-File
70:IP>>LO>> ++ .. -- -- -- IP>>HI>> ++ .. -- -- --|IP-File
80:SI>>LO>> ++ .. -- -- -- SI>>HI>> ++ .. -- -- --|SI-File
90:DI>>LO>> ++ .. -- -- -- DI>>HI>> ++ .. -- -- --|DI-File
A0:AL>>LO>>Стек истории -- AH>>HI>> ++ .. -- -- --|AX-File
B0:BL>>LO>>модификации- -- BH>>HI>> ++ .. -- -- --|BX-File
C0:CL>>LO>>всех РОН- -- -- CH>>HI>> ++ .. -- -- --|CX-File
D0:DL>>LO>> ++ .. -- -- -- DH>>HI>> ++ .. -- -- --|DX-File
E0:Стек конвейера с историей исполненных операций-|Execution Pipeline
F0:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|Execution Pipeline
+0:Зона особого назначения ???????????????????????|Service context
EX-Регистр - хранит контекст процессора.
Ячейками с 50h по DFh непосредственно связаны все РОН в режиме стекового файла с
глубиной до 8 уровней. Тем самым, когда какой-либо регистр изменяется, автоматом
история его изменений циклически сдвигается от ячейки с x0h/x8h к ячейке x7h/xFh
соответственно. Это позволяет в отладчике частично прокрутить историю исполнения
кода в обратном направлении. Так, ячейки 0-FFh доступны программе в произвольном
доступе. Ячейка +0 - это 256 управляющая ячейка управления переключением страниц
контекста, доступная только операционной системе, хранящая маску доступности для
остальных ячеек +1..+7 (257..263).
Битами этих сервисных ячеек можно "заморозить" историю контекста, чтобы получить
произвольный и точный доступ ко всем доступным моментам или сохранить контекст и
подготовить его для переключения к следующей задаче.
////////////////////////////////////////////////////////////////////////////////
Порты: Доступ к устройствам ввода/вывода
========================================
Пользовательский уровень:
Доступ к устройствам операционной среды достигается префикс-инструкц
0###sP?Z| Parity Zero:Пропускать следующие инструкции на период декрементации;
0###Sp?Z| Signed Zero:Повторять следующую инструкцию в периоде декрементации;
0###SP?Z| Spouts Zero:Повторять следующую инструкцию в ожидании декрементации;
1###sP?Z| Parity Zero:
1###Sp?Z| Signed Zero:Skip # instructions
1###SP?Z| Spouts Zero:Loop instruction # times
////////////////////////////////////////////////////////////////////////////////
-->
<pre id='List'>
</pre>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment