Skip to content

Commit e1695dd

Browse files
committed
WIP FADD/FSUB for BK0010
1 parent 3e9ff25 commit e1695dd

3 files changed

Lines changed: 167 additions & 22 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ VARIA: .WORD 0 ; A%
9696
Так же, как и в оригинале Бейсик Вильнюс:
9797
- Один оператор на строку.
9898
- Имена переменных опознаются по двум первым буквам + тип.
99+
- Булевого типа нет, вместо него используется целый тип. Результат логических операторов (`=`, `<>`, `>`, `<` и т.п.) это либо -1 ("истина") либо 0 ("ложь").
99100

100101
Отличия от оригинала:
101102
- Ключевые слова нужно писать полностью, сокращения НЕ допускаются.
@@ -104,7 +105,7 @@ VARIA: .WORD 0 ; A%
104105
- Под оператором `IF` в `THEN`/`ELSE` НЕ допускается ставить операторы `FOR`/`NEXT`/`DIM`/`DATA`
105106
- Аргумент функций `CSRLIN` и `POS` необязательный, но если есть, то вычисляется (если он не константный), но результат вычисления не используется.
106107
- `ON .. GOTO/GOSUB`: отрицательное значение выражения под `ON` не приводит к ошибке, просто переходим на строку, следующую после этого оператора.
107-
- Добавлена функция `IIF` с тремя аргументами: `X=IIF(<ЛОГ.ВЫРЖЕНИЕ>,<АРИФМ.ВЫРАЖЕНИЕ>,<АРИФМ.ВЫРАЖЕНИЕ>)`. Вычисляется первый аргумент; если он ненулевой (т.е. TRUE), то результатом будет значение второго выражения, иначе (для FALSE) - значение третьего выражения. Вычисляется только то выражение, результат которого нам нужен. Тип результата зависит от типов второго и третьего аргументов: если они оба Integer, то и результат Integer; если хотя бы один из них Single, то и результат Single.
108+
- Добавлена функция `IIF` с тремя аргументами: `X=IIF(<ЛОГ.ВЫРАЖЕНИЕ>,<АРИФМ.ВЫРАЖЕНИЕ>,<АРИФМ.ВЫРАЖЕНИЕ>)`. Вычисляется первый аргумент; если он ненулевой (т.е. TRUE), то результатом будет значение второго выражения, иначе (для FALSE) - значение третьего выражения. Вычисляется только то выражение, результат которого будет использоваться. Тип результата зависит от типов второго и третьего аргументов: если они оба Integer, то и результат Integer; если хотя бы один из них Single, то и результат Single.
108109
- Команды/операторы, которые не реализованы и НЕ БУДУТ реализованы в будущем:
109110
- `RUN`, `CONT`
110111
- `KEY` (переназначение функциональных клавиш)

runtime-BK0010.tmac

Lines changed: 165 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ FCMP:
500500
BLT 5$
501501
2$: CMP R1,R2 ; сравнить старшие слова
502502
BNE 3$
503-
CMP 4(SP),@SP ; сравнить младшие слова
503+
CMP 4(SP),(SP) ; сравнить младшие слова
504504
BNE 3$
505505
CLR R0 ; равны
506506
3$: ROR R0 ; знак в старший бит
@@ -570,7 +570,7 @@ FUNPK:
570570
; После обработки R2 будет содержать истинную экспоненту (со знаком),
571571
; а R0 и R1 - мантиссу (R0 - старшие 16 бит, R1 - младшие 16 бит).
572572
ROL R0 ; сдвигаем старшее слово, чтобы извлечь знак
573-
ROR @SP ; знак (C) помещается в младший бит слова, на которое указывает SP
573+
ROR (SP) ; знак (C) помещается в младший бит слова, на которое указывает SP
574574
; (это сохранённое значение 7, используется как флаг)
575575
SWAB R0 ; меняем байты местами, чтобы ст.байт (эксп-та+мантисса) оказался в младшем
576576
BISB R0,R2 ; R2 получает ст.байт исходного R0 (экспонента + старшие биты мантиссы)
@@ -647,12 +647,12 @@ KLIOP: CALL APVAL ;
647647
BLT 1$ ; если цифр меньше -1, пропускаем
648648
CMP R5,6(SP) ; сравниваем с 7
649649
BGT 1$ ; если больше 7, пропускаем
650-
CLRB @SP ; сбрасываем флаг (слово на вершине стека)
650+
CLRB (SP) ; сбрасываем флаг (слово на вершине стека)
651651
ADD R5,R2 ; корректируем указатель
652652
1$: SUB #4,10(SP) ; уменьшаем указатель конца буфера на 4 (резервируем место)
653653
E: ADD 10(SP),R2 ; R2 = R2 + конец буфера (теперь R2 указывает на позицию для цифр)
654654
MOV R2,R3 ; R3 - текущий указатель в буфере
655-
TSTB @SP ; проверяем флаг (был ли установлен особый формат)
655+
TSTB (SP) ; проверяем флаг (был ли установлен особый формат)
656656
BNE 1$ ; если флаг установлен, переход к другой ветке
657657
TST R5 ; проверяем количество цифр
658658
BLE TRUP ; если цифр <= 0, идём на TRUP
@@ -671,7 +671,7 @@ PNUL: CMP R3,10(SP) ;
671671
MOVB #60,(R3)+ ; заполняем нулями
672672
BR PNUL
673673
SKAITM: MOV R2,R3 ; восстанавливаем указатель
674-
TSTB @SP ; проверяем флаг
674+
TSTB (SP) ; проверяем флаг
675675
BEQ 1$
676676
DEC R3 ; коррекция
677677
BR OPA
@@ -702,7 +702,7 @@ VIENZ: ADD #72,R5 ;
702702
VISKA1: MOV R3,R2 ; сохраняем конечный указатель
703703
VISKAS: MOVB #40,(R2)+ ; записываем пробел
704704
MOV (SP)+,R5 ; восстанавливаем R5
705-
MOV (SP)+,@SP ; восстанавливаем SP ??
705+
MOV (SP)+,(SP) ; восстанавливаем SP ??
706706
SUB 4(SP),R2 ; вычисляем длину строки
707707
MOV R2,2(SP) ; сохраняем длину
708708

@@ -725,7 +725,7 @@ IRDAR: CALL DL4 ;
725725
DARSYK: CALL DALYT2 ; разделить на 2 (теперь всего деление на 8 от исходного)
726726
ADD 2(SP),R1 ; прибавить сохранённое (исходное/2) к текущему
727727
ADC R0
728-
ADD @SP,R0 ; прибавить старшее слово (исходное/2)
728+
ADD (SP),R0 ; прибавить старшее слово (исходное/2)
729729
NEG R4 ; изменить знак счётчика (управление циклами)
730730
BLT DARSYK ; если R4 отрицательный, повторить внутренний цикл
731731
DEC R4 ; иначе уменьшить счётчик
@@ -768,7 +768,7 @@ DAUG8: MOV #3,-(SP) ;
768768
DG2: ASL R1 ; сдвиг влево младшего слова (умножение на 2)
769769
ROL R0 ; сдвиг влево среднего слова с переносом из младшего
770770
ROL R4 ; сдвиг влево старшего байта с переносом из среднего
771-
DEC @SP ; уменьшаем счётчик
771+
DEC (SP) ; уменьшаем счётчик
772772
BGT DG2 ; повторяем 3 раза - всего умножение на 2^3 = 8
773773
TST (SP)+ ; удаляем счётчик из стека
774774
RETURN
@@ -834,10 +834,10 @@ ZENKL: MOV R3,14(SP) ;
834834
; На выходе: в буфер вставляется десятичная точка, дробные цифры,
835835
; возможно, округление; R3 становится указателем на следующий свободный байт.
836836
FORMSK: MOV R2,-(SP) ; сохраняем R2 (указатель на начало целой части)
837-
DEC @SP ; уменьшаем его на 1 (для удобства сравнений)
837+
DEC (SP) ; уменьшаем его на 1 (для удобства сравнений)
838838
CMP #12,R4 ; сравниваем R4 с 10.
839839
BGT NEDVIZ ; если цифра >10, пропускаем вставку десятичной точки
840-
MOV R3,@SP ; иначе сохраняем текущий указатель в стеке
840+
MOV R3,(SP) ; иначе сохраняем текущий указатель в стеке
841841
MOVB #61,(R3)+ ; записываем символ '=' - возможно, десятичная точка?
842842
SUB #12,R4 ; вычитаем 10 из R4 (коррекция для следующего шага)
843843
NEDVIZ: CMP R2,R3 ; сравниваем указатель начала целой части и текущий
@@ -847,7 +847,7 @@ NETASK: CMP 14(SP),R3 ;
847847
BLOS GRIZT ; если R3 <= конец буфера, выходим
848848
TST R4 ; проверяем, есть ли цифра для вывода
849849
BEQ 1$ ; если нет, пропускаем
850-
MOV R3,@SP ; сохраняем указатель
850+
MOV R3,(SP) ; сохраняем указатель
851851
1$: ADD #60,R4 ; преобразуем цифру (0?9) в ASCII-символ
852852
MOVB R4,(R3)+ ; записываем цифру
853853
CLR R4 ; обнуляем R4 (цифра использована)
@@ -863,30 +863,175 @@ GRIZT: MOV (SP)+,R3 ;
863863

864864
;#####################################################################
865865
;## FADD
866-
; Сложение для float, эмуляция FIS, параметры B и A на стеке
866+
;## Need ERRR
867+
; Сложение для плавающих чисел, эмуляция FIS, параметры B и A на стеке.
868+
; На основе кода процедуры ADR из реализации Бейсик Вильнюс для БК-0010.
867869
; На входе: (SP) - адрес возврата
868870
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
869871
; (SP+6)(SP+10) - плавающее число A (старшее, младшее слово)
870872
; Результат: (SP)(SP+2) - плавающее число (старшее слово, младшее слово)
871873
FADD:
872-
873-
;TODO
874-
RETURN ;STUB
874+
CLR -(SP) ; МЕСТО ДЛЯ ЗНАКОВ СЛАГАЕМЫХ
875+
CLR R2 ; под порядок A
876+
CLR R3 ; под порядок B
877+
; Анализ операндов
878+
ASL 6(SP)
879+
ROL 4(SP)
880+
BISB 5(SP),R3 ; порядок B -> R3
881+
BEQ 50$ ; B=0 => A - результат
882+
ROLB (SP) ; запомнить знак B
883+
;
884+
ASL 12(SP)
885+
ROL 10(SP)
886+
BISB 11(SP),R2 ; порядок операнда A -> R2
887+
BNE 1$
888+
;
889+
RORB (SP) ; восстановить B
890+
ROR 4(SP)
891+
ROR 6(SP)
892+
MOV 4(SP),10(SP)
893+
MOV 6(SP),12(SP)
894+
BR 50$ ; X=0 => РЕЗУЛЬТАТ - B
895+
;A1:
896+
1$: ROLB 1(SP) ; запомнить знак A
897+
MOVB #1,11(SP)
898+
MOVB #1,5(SP)
899+
SUB R3,R2 ; РАЗНОСТЬ ПОРЯДКОВ ЧИСЕЛ А И B => R2
900+
BGT 2$
901+
;
902+
MOV 10(SP),R0 ; В R0,R1 - МАНТИССА ЧИСЛА
903+
MOV 12(SP),R1 ; С МЕНЬШИМ ПОРЯДКОМ
904+
BR 20$
905+
;A2:
906+
2$: ADD R2,R3
907+
MOV 4(SP),R0
908+
MOV 6(SP),R1
909+
MOV 10(SP),4(SP)
910+
MOV 12(SP),6(SP)
911+
SWAB (SP)
912+
NEG R2
913+
;CMZ:
914+
20$: CMPB 1(SP),(SP) ; ЕСЛИ ЗНАКИ ЧИСЕЛ НЕ=
915+
BEQ 21$ ; ИЗМЕНИТЬ ЗНАК МЕНЬШЕГО ЧИСЛА
916+
NEG R1
917+
ADC R0
918+
NEG R0
919+
;Z1:
920+
21$: TST R2 ; ЕСЛИ R2 = 0 - выполнить сложение
921+
BEQ 30$
922+
CMP #-31,R2 ; ЕСЛИ R2 > 31 => REZ=ЧИСЛО С БОЛЬШИМ ПОРЯДКОМ
923+
BLE 22$
924+
MOV 4(SP),R0
925+
MOV 6(SP),R1
926+
BR 7$
927+
;Z2
928+
22$: CMP #-10,R2 ; ПРИВЕСТИ СЛАГАЕМЫЕ К ОДИНАКОВОМУ
929+
BLE 6$ ; ПОРЯДКУ
930+
CLR R4
931+
TST R0
932+
BPL 3$
933+
COM R4
934+
;A3:
935+
3$: CMP #-20,R2
936+
BLT 4$
937+
MOV R0,R1
938+
MOV R4,R0
939+
ADD #20,R2
940+
BEQ 30$
941+
4$: CMP #-10,R2
942+
BLE 6$
943+
ADD #20,R2
944+
5$: ASL R1
945+
ROL R0
946+
ROL R4
947+
DEC R2
948+
BGT 5$
949+
MOV R0,R1
950+
MOV R4,R0
951+
BR 30$
952+
;A6:
953+
6$: ASR R0
954+
ROR R1
955+
INC R2
956+
BLT 6$
957+
;SUM:
958+
30$: ADD 4(SP),R0 ; СЛОЖИТЬ ЧИСЛА
959+
ADD 6(SP),R1
960+
ADC R0
961+
;
962+
CMPB 1(SP),(SP) ; ЗНАКИ СЛАГАЕМЫХ РАЗЛИЧНЫ ?
963+
BNE 8$
964+
BIT R0,#1000 ; РЕЗУЛЬТАТ НОРМАЛИЗОВАН?
965+
BEQ 7$
966+
ASR R0
967+
ROR R1
968+
INC R3
969+
7$: SWAB R3
970+
BNE FADD$O ; переполнение порядка
971+
;
972+
BISB R0,R3
973+
ROR (SP) ; СФОРМИРОВАТЬ РЕЗ-Т В ВИДЕ ЧИСЛА
974+
ROR R3 ; С ПЛАВАЮЩЕЙ ЗАПЯТОЙ
975+
ROR R1
976+
ADC R1
977+
ADC R3
978+
BVS FADD$O
979+
BCS FADD$O
980+
13$: MOV R3, 10(SP) ; сохранить старшее слово результата на место A
981+
MOV R1, 12(SP) ; сохранить младшее слово результата
982+
;REZ:
983+
50$: TST (SP)+ ; удалить слово знаков
984+
MOV (SP)+,R5 ; адрес возврата
985+
CMP (SP)+,(SP)+ ; удаление числа B со стека
986+
JMP @R5 ; возврат
987+
;A8:
988+
8$: TST R0
989+
BGT 9$
990+
BEQ 10$
991+
NEG R0 ; ИЗМЕНИТЬ ЗНАК РЕЗУЛЬТАТА
992+
NEG R1
993+
SBC R0
994+
SWAB (SP)
995+
;A9:
996+
9$: BIT R0,#400 ; НОРМАЛИЗОВАТЬ МАНТИССУ РЕЗУЛЬТАТА
997+
BNE 11$
998+
DEC R3
999+
ASL R1
1000+
ROL R0
1001+
BR 9$
1002+
;A10:
1003+
10$: TST R1
1004+
BEQ 12$
1005+
SWAB R1 ; НОРМАЛИЗОВАТЬ МАНТИССУ РЕЗУЛЬТАТА
1006+
BISB R1,R0
1007+
CLRB R1
1008+
SUB #10,R3
1009+
BR 9$
1010+
;A11:
1011+
11$: TST R3
1012+
BGT 7$
1013+
CLR R1
1014+
12$: CLR R3
1015+
BR 13$
1016+
;
1017+
; Ошибка: переполнение
1018+
FADD$O: MOV (SP), R5 ; откуда вызвали
1019+
MOV #2806., R0 ; Ошибка: переполнение
1020+
JMP ERRR
8751021

8761022
;#####################################################################
8771023
;## FSUB
8781024
;## Need FADD
8791025
; Вычитание для float, эмуляция FIS, параметры B и A на стеке.
880-
; На основе кода процедуры $DSUB$ из реализации Бейсик Вильнюс для БК-0010.
8811026
; На входе: (SP) - адрес возврата
8821027
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
8831028
; (SP+6)(SP+10) - плавающее число A (старшее, младшее слово)
8841029
; Результат: (SP)(SP+2) - плавающее число (старшее слово, младшее слово)
8851030
FSUB:
886-
TST 2(SP) ; ZERO?
887-
BEQ FADD ; YES, SO IT CAN'T BE NEGATED
888-
ADD #100000,2(SP) ; NEGATE SIGN OF B ON STACK
889-
BR FADD ; FALL THROUGH AND DO AN ADDITION (A-B=A+(-B))
1031+
TST 2(SP) ; проверяем старше слово
1032+
BEQ 1$ ; ноль =>
1033+
ADD #100000,2(SP) ; изменить знак операнда
1034+
1$: JMP FADD ; идём на сложение: A-B = A+(-B)
8901035

8911036
;#####################################################################
8921037
;## FMUL

runtime-UKNC.tmac

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,6 @@ RNDSAV: .WORD 040101, 027076 ;
978978
; На основе кода процедуры SQRG из реализации Бейсик Вильнюс для УКНЦ.
979979
; Для отрицательных чисел выдаётся ошибка; для 0.0 результат 0.0.
980980
; Алгоритм: итерационный метод Ньютона с начальным приближением
981-
; На основе кода процедуры SQRG из реализации Бейсик Вильнюс для УКНЦ.
982981
; На входе: (SP) - адрес возврата
983982
; (SP+2)(SP+4) - число с плавающей точкой (старшее слово, младшее слово)
984983
; На выходе: (SP)(SP+2) - результат

0 commit comments

Comments
 (0)