Skip to content

Commit bd0b689

Browse files
committed
WIP FCOS/FSIN for BK0010
1 parent 3d749d3 commit bd0b689

2 files changed

Lines changed: 192 additions & 59 deletions

File tree

runtime-BK0010.tmac

Lines changed: 187 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,127 @@ FSQR$K: MOV FSQR$X+2, R5 ;
10671067
MOV #3605., R0 ; Ошибка: корень из отрицательного числа
10681068
JMP ERRR
10691069

1070+
;#####################################################################
1071+
;## FCOS
1072+
;## Need FSIN
1073+
;## Need FADD
1074+
; Вычисление cos(X) для плавающего числа (float).
1075+
; На основе кода процедуры KOS из реализации Бейсик Вильнюс для УКНЦ.
1076+
; Реализуется через вычисление sin: cos(x) = sin(x + PI/2)
1077+
; На входе: (SP) - адрес возврата
1078+
; (SP+2)(SP+4) - число с плавающей точкой (старшее слово, младшее слово)
1079+
; На выходе: (SP)(SP+2) - результат
1080+
FCOS:
1081+
MOV (SP)+, 10$+2 ; адрес возврата
1082+
MOV #007733,-(SP) ; младшее слово PI/2
1083+
MOV #040311,-(SP) ; старшее слово PI/2
1084+
CALL FADD ; сложение: аргумент + PI/2
1085+
10$: MOV #000000, -(SP) ; адрес возврата
1086+
BR FSIN ; дальше через вычисление синуса
1087+
1088+
;#####################################################################
1089+
;## FSIN
1090+
;## Need FFIX
1091+
;## Need FADD
1092+
;## Need FSUB
1093+
;## Need FMUL
1094+
;## Need FDIV
1095+
; Вычисление sin(X) для плавающего числа (float).
1096+
; На основе кода процедуры SING из реализации Бейсик Вильнюс для УКНЦ.
1097+
; Алгоритм:
1098+
; 1. Приведение аргумента к диапазону [0, PI/2] путём деления на PI/2,
1099+
; выделения целой части (квадранта) и взятия дробной части.
1100+
; 2. Приведённый аргумент (в [0, PI/2]) раскладывается в полином
1101+
; с коэффициентами из таблицы FSIN$T.
1102+
; 3. Знак результата корректируется в зависимости от квадранта.
1103+
; Полином вычисляется по схеме Горнера:
1104+
; sin(x) ~= t * (a1 + t^2*(a2 + t^2*(a3 + t^2*(a4 + t^2*a5))))
1105+
; Коэффициенты получены из разложения Маклорена sin(x) с подстановкой x = (PI/2)*t:
1106+
; a1 = PI/2 ~= 1.57079632679
1107+
; a2 = -(PI/2)^3 / 3! ~= -0.645964
1108+
; a3 = (PI/2)^5 / 5! ~= 0.0796897
1109+
; a4 = -(PI/2)^7 / 7! ~= -0.00467377
1110+
; a5 = (PI/2)^9 / 9! ~= 0.000151484
1111+
; На входе: (SP) - адрес возврата
1112+
; (SP+2)(SP+4) - число с плавающей точкой (старшее слово, младшее слово)
1113+
; На выходе: (SP)(SP+2) - результат
1114+
FSIN:
1115+
MOV (SP)+, FSIN$X+2 ; адрес возврата
1116+
; На стеке: (SP)(SP+2) - исходное число
1117+
CLR -(SP) ; выделить место под хранение знака
1118+
MOV 4(SP),-(SP) ; скопировать аргумент (старшее)
1119+
MOV 4(SP),-(SP) ; скопировать аргумент (младшее)
1120+
ASL (SP) ; выдвигаем знак в C
1121+
ROR 4(SP) ; сохраняем знак в 4(SP)
1122+
ROR (SP) ; сдвигаем старшее слово обратно без знака
1123+
MOV #7733,-(SP) ; младшее слово 2/PI (константа)
1124+
MOV #40711,-(SP) ; старшее слово 2/PI
1125+
CALL FDIV ; деление: (2x) / (2/PI) = x * PI
1126+
; На самом деле это приведение: вычисляем t = (2x)/PI, затем выделяем целую часть
1127+
; на стеке: (SP)(SP+2) = t, (SP+4) = знак, (SP+6)(SP+10) = исх.число
1128+
MOV 2(SP),-(SP) ; копировать результат (t)
1129+
MOV 2(SP),-(SP)
1130+
CALL FFIX ; отбросить дробную часть -> целое число
1131+
CALL FSUB ; вычесть t, получаем дробную часть
1132+
; на стеке: дробная часть, (SP+4)(SP+6) = t, (SP+10) = знак, (SP+12)(SP+14) = исх.число
1133+
; Проверить, есть ли дробная часть
1134+
TST (SP) ; старшее слово 0 ?
1135+
BEQ 12$ ; нет дробной чати => на завершение
1136+
INCB 1(SP) ; увеличение экспоненты - умножение числа на 4
1137+
MOV 2(SP),-(SP) ; скопировать
1138+
MOV 2(SP),-(SP)
1139+
CALL FFIX ; опять отбросить дробную часть
1140+
BIS (SP),10(SP) ; объединение флагов ??
1141+
CALL FSUB ; вычесть
1142+
TSTB 4(SP) ; проверяем байт флагов
1143+
BEQ 3$
1144+
ADD #100000,(SP) ; инвертировать знак
1145+
CLR -(SP) ; константа 1.0
1146+
MOV #040200,-(SP) ;
1147+
CALL FADD ; сложение с 1.0
1148+
3$: ASRB 5(SP) ; сдвигаем байт флагов
1149+
BCC 8$
1150+
ADD #100000,(SP) ; если бит = 1, изменить знак
1151+
; Начало полиномиального разложения
1152+
; на стеке: (SP)(SP+2) = t, (SP+4) = знак, (SP+6)(SP+10) = исх.число
1153+
8$: MOV 2(SP),-(SP) ; копируем значение
1154+
MOV 2(SP),-(SP)
1155+
MOV 2(SP),-(SP) ; копируем значение
1156+
MOV 2(SP),-(SP)
1157+
CALL FMUL ; умножение (возведение в квадрат) = t^2
1158+
; на стеке: (SP)(SP+2) = t^2, (SP+4)(SP+6) = t, (SP+10) = знак, (SP+12)(SP+14) = исх.число
1159+
MOV (SP)+,R0 ; снять t^2 старшее слово
1160+
MOV (SP)+,R1 ; снять t^2 младшее слово
1161+
MOV #FSIN$T,R2 ; адрес таблицы коэффициентов
1162+
MOV #4,R3 ; количество итераций
1163+
MOV (R2)+,-(SP) ; коэфф. a5 младшее слово
1164+
MOV (R2)+,-(SP) ; коэфф. a5 старшее слово
1165+
; на стеке: (SP)(SP+2) = сумма, (SP+4)(SP+6) = t, (SP+10) = знак, (SP+12)(SP+14) = исх.число
1166+
9$: MOV R1,-(SP) ; положить t^2 младшее слово
1167+
MOV R0,-(SP) ; положить t^2 старшее слово
1168+
CALL FMUL ; умножить на t^2
1169+
MOV (R2)+,-(SP) ; коэфф. младшее слово
1170+
MOV (R2)+,-(SP) ; коэфф. старшее слово
1171+
CALL FADD ; сложить с коэфф.
1172+
SOB R3, 9$ ; повторяем
1173+
CALL FMUL ; умножить на t
1174+
; Получен результат, осталось сделать коррекцию знака
1175+
; на стеке: (SP)(SP+2) = результат, (SP+4) = знак, (SP+6)(SP+10) = исх.число
1176+
12$: TST 4(SP) ; проверить сохранённый знак
1177+
BGE 14$
1178+
ADD #100000,(SP) ; изменить знак результата
1179+
14$: MOV (SP)+,4(SP) ; переместить результат на место исходного аргумента
1180+
MOV (SP)+,4(SP)
1181+
TST (SP)+ ; подчищаем стек
1182+
FSIN$X: JMP @#000000 ; возврат
1183+
;
1184+
; Таблица коэффициентов для полиномиальной аппроксимации синуса/косинуса
1185+
FSIN$T: .WORD 153672, 035036 ; a5 (~= 0.000151484)
1186+
.WORD 023143, 136231 ; a4 (~= -0.00467377)
1187+
.WORD 032130, 037243 ; a3 (~= 0.0796897)
1188+
.WORD 056741, 140045 ; a2 (~= -0.645964)
1189+
.WORD 007733, 040311 ; a1 = PI/2 (~= 1.5707963)
1190+
10701191
;#####################################################################
10711192
;## FADD
10721193
;## Need ERRR
@@ -1076,44 +1197,49 @@ FSQR$K: MOV FSQR$X+2, R5 ;
10761197
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
10771198
; (SP+6)(SP+10) - плавающее число A (старшее, младшее слово)
10781199
; Результат: (SP)(SP+2) - плавающее число (старшее слово, младшее слово)
1200+
; Портит регистры: R4
10791201
FADD:
1080-
CLR -(SP) ; МЕСТО ДЛЯ ЗНАКОВ СЛАГАЕМЫХ
1202+
MOV (SP), FADD$X+2 ; адрес возврата
1203+
MOV R0, (SP) ; сохраняем регистры
1204+
MOV R1,-(SP)
1205+
MOV R2,-(SP)
1206+
MOV R3,-(SP)
1207+
;
1208+
CLR -(SP) ; место для знаков слагаемых
10811209
CLR R2 ; под порядок A
10821210
CLR R3 ; под порядок B
1211+
; На стеке: (SP)знак, R3, R2, R1, R0, (SP+12)ст.B мл.B, (SP+16)ст.A мл.A
10831212
; Анализ операндов
1084-
ASL 6(SP)
1085-
ROL 4(SP)
1086-
BISB 5(SP),R3 ; порядок B -> R3
1213+
ASL 14(SP)
1214+
ROL 12(SP)
1215+
BISB 13(SP),R3 ; порядок B -> R3
10871216
BEQ 50$ ; B=0 => A - результат
10881217
ROLB (SP) ; запомнить знак B
1089-
;
1090-
ASL 12(SP)
1091-
ROL 10(SP)
1092-
BISB 11(SP),R2 ; порядок операнда A -> R2
1218+
ASL 20(SP)
1219+
ROL 16(SP)
1220+
BISB 17(SP),R2 ; порядок операнда A -> R2
10931221
BNE 1$
1094-
;
10951222
RORB (SP) ; восстановить B
1096-
ROR 4(SP)
1097-
ROR 6(SP)
1098-
MOV 4(SP),10(SP)
1099-
MOV 6(SP),12(SP)
1223+
ROR 12(SP)
1224+
ROR 14(SP)
1225+
MOV 12(SP),16(SP)
1226+
MOV 14(SP),20(SP)
11001227
BR 50$ ; X=0 => результат - B
11011228
;A1:
11021229
1$: ROLB 1(SP) ; запомнить знак A
1103-
MOVB #1,11(SP)
1104-
MOVB #1,5(SP)
1230+
MOVB #1,17(SP)
1231+
MOVB #1,13(SP)
11051232
SUB R3,R2 ; разность порядков чисел А И B => R2
11061233
BGT 2$
1107-
;
1108-
MOV 10(SP),R0 ; в R0,R1 - мантисса числа
1109-
MOV 12(SP),R1 ; с меньшим порядком
1234+
MOV 16(SP),R0 ; в R0,R1 - мантисса числа
1235+
MOV 20(SP),R1 ; с меньшим порядком
11101236
BR 20$
11111237
;A2:
11121238
2$: ADD R2,R3
1113-
MOV 4(SP),R0
1114-
MOV 6(SP),R1
1115-
MOV 10(SP),4(SP)
1116-
MOV 12(SP),6(SP)
1239+
MOV 12(SP),R0
1240+
MOV 14(SP),R1
1241+
MOV 16(SP),12(SP)
1242+
MOV 20(SP),14(SP)
11171243
SWAB (SP)
11181244
NEG R2
11191245
;CMZ:
@@ -1127,8 +1253,8 @@ FADD:
11271253
BEQ 30$
11281254
CMP #-31,R2 ; если R2 > 31 => REZ=ЧИСЛО С БОЛЬШИМ ПОРЯДКОМ
11291255
BLE 22$
1130-
MOV 4(SP),R0
1131-
MOV 6(SP),R1
1256+
MOV 12(SP),R0
1257+
MOV 14(SP),R1
11321258
BR 7$
11331259
;Z2
11341260
22$: CMP #-10,R2 ; привести слагаемые к одинаковому порядку
@@ -1161,10 +1287,9 @@ FADD:
11611287
INC R2
11621288
BLT 6$
11631289
;SUM:
1164-
30$: ADD 4(SP),R0 ; сложить числа
1165-
ADD 6(SP),R1
1290+
30$: ADD 12(SP),R0 ; сложить числа
1291+
ADD 14(SP),R1
11661292
ADC R0
1167-
;
11681293
CMPB 1(SP),(SP) ; знаки слагаемых различны?
11691294
BNE 8$
11701295
BIT R0,#1000 ; результат нормализован?
@@ -1174,7 +1299,6 @@ FADD:
11741299
INC R3
11751300
7$: SWAB R3
11761301
BNE FADD$O ; переполнение порядка
1177-
;
11781302
BISB R0,R3
11791303
ROR (SP) ; сформировать результат в виде числа с плавающей запятой
11801304
ROR R3
@@ -1183,13 +1307,18 @@ FADD:
11831307
ADC R3
11841308
BVS FADD$O
11851309
BCS FADD$O
1186-
13$: MOV R3, 10(SP) ; сохранить старшее слово результата на место A
1187-
MOV R1, 12(SP) ; сохранить младшее слово результата
1310+
13$: MOV R3, 16(SP) ; сохранить старшее слово результата на место A
1311+
MOV R1, 20(SP) ; сохранить младшее слово результата
1312+
BR 50$
11881313
;REZ:
11891314
50$: TST (SP)+ ; удалить слово знаков
1190-
MOV (SP)+,R5 ; адрес возврата
1315+
MOV (SP)+,R3 ; восстанавливаем регистры
1316+
MOV (SP)+,R2
1317+
MOV (SP)+,R1
1318+
MOV (SP)+,R0
11911319
CMP (SP)+,(SP)+ ; удаление числа B со стека
1192-
JMP @R5 ; возврат
1320+
FADD$X = .
1321+
99$: JMP @#000000 ; возврат
11931322
;A8:
11941323
8$: TST R0
11951324
BGT 9$
@@ -1219,9 +1348,10 @@ FADD:
12191348
CLR R1
12201349
12$: CLR R3
12211350
BR 13$
1351+
12221352
;
12231353
; Ошибка: переполнение
1224-
FADD$O: MOV (SP), R5 ; откуда вызвали
1354+
FADD$O: MOV FADD$X+2, R5 ; откуда вызвали
12251355
MOV #2806., R0 ; Ошибка: переполнение
12261356
JMP ERRR
12271357

@@ -1241,56 +1371,59 @@ FSUB:
12411371

12421372
;#####################################################################
12431373
;## FMUL
1374+
;## Need ERRR
12441375
; Умножение для плавающих чисел, параметры B и A на стеке.
12451376
; На основе кода процедуры MLR из реализации Бейсик Вильнюс для БК-0010.
12461377
; На входе: (SP) - адрес возврата
12471378
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
12481379
; (SP+6)(SP+10) - плавающее число A (старшее, младшее слово)
12491380
; Результат: (SP)(SP+2) - плавающее число (старшее слово, младшее слово)
1381+
; Портит регистры: R4,R5
12501382
FMUL:
12511383
MOV (SP)+, FMUL$X+2 ; снимаем и подставляем адрес возврата
12521384
; На стеке: ст.B мл.B, ст.A мл.A
1253-
MOV R5,-(SP) ; Сохраняем регистры
1254-
MOV R4,-(SP)
1255-
;MOV R3,-(SP)
1385+
MOV R0,-(SP) ; Сохраняем регистры
1386+
MOV R1,-(SP)
1387+
MOV R2,-(SP)
1388+
MOV R3,-(SP)
12561389
; Подготовительные действия
1257-
; На стеке: R4, R5, ст.B мл.B, ст.A мл.A
1258-
MOV 4(SP),R2 ; R2 <- порядок числа B
1390+
; На стеке: R3, R2, R1, R0, ст.B мл.B, ст.A мл.A
1391+
MOV 10(SP),R2 ; R2 <- порядок числа B
12591392
ASL R2
12601393
ROL -(SP) ; запомнить знак числа B
12611394
CLR -(SP)
1262-
; На стеке: 0, знак, R4, R5, (SP+10)ст.B мл.B, (SP+14)ст.A мл.A
1395+
; На стеке: 0, знак, R3, R2, R1, R0, (SP+10)ст.B мл.B, (SP+14)ст.A мл.A
12631396
SWAB R2
12641397
MOVB R2,(SP) ; запомнить порядок числа B
12651398
BEQ FMUL$0 ; B = 0 => результат - 0
12661399
SEC
12671400
ROR R2 ; формирование мантиссы
12681401
CLRB R2 ; числа B в регистрах R2/R3
1269-
BISB 13(SP),R2
1402+
BISB 17(SP),R2
12701403
CLR R3
1271-
BISB 12(SP),R3
1404+
BISB 16(SP),R3
12721405
SWAB R3
1273-
ASL 14(SP) ; формирование в нулевом бите
1406+
ASL 20(SP) ; формирование в нулевом бите
12741407
ADC 2(SP) ; знака мантисы результата
1275-
TSTB 15(SP)
1408+
TSTB 21(SP)
12761409
BEQ FMUL$0 ; A = 0 => результат - 0
1277-
ROR 14(SP) ; восстановление мантиссы A
1410+
ROR 20(SP) ; восстановление мантиссы A
12781411
; Умножение мантисс
12791412
CLR R0 ; подготовка R0/R1
12801413
CLR R1 ; для резултата умножения
1281-
MOV 16(SP),R4 ; выделить младшую часть мантиссы A
1414+
MOV 22(SP),R4 ; выделить младшую часть мантиссы A
12821415
BEQ 1$ ; если 0 - умножать не надо
12831416
MOV #17,R5 ; умножение B на
12841417
CALL FMUL$P ; младшую часть
12851418
CALL FMUL$D ; мантиссы A
12861419
;
1287-
1$: MOV 14(SP),R4
1420+
1$: MOV 20(SP),R4
12881421
MOV #7,R5 ; умножение на
12891422
CALL FMUL$D ; старшую часть
12901423
CALL FMUL$E ; мантиссы A
12911424
; Сложение порядков
12921425
ADD (SP)+,R4
1293-
; На стеке: знак, R4, R5, (SP+6)ст.B мл.B, (SP+12)ст.A мл.A
1426+
; На стеке: знак, R3, R2, R1, R0, (SP+6)ст.B мл.B, (SP+12)ст.A мл.A
12941427
; Нормализация мантиссы
12951428
ROL R1
12961429
ROL R0
@@ -1317,14 +1450,15 @@ FMUL:
13171450
ADC R0
13181451
BCS FMUL$O ; контроль переполнения
13191452
BVS FMUL$O ; порядка
1320-
; На стеке: R4, R5, (SP+4)ст.B мл.B, (SP+10)ст.A мл.A
1453+
; На стеке: R3, R2, R1, R0, (SP+10)ст.B мл.B, (SP+14)ст.A мл.A
13211454
;MEND:
1322-
FMUL$M: MOV R0,10(SP) ; пересылка в стек на место числа A
1323-
MOV R1,12(SP) ; младшее слово
1455+
FMUL$M: MOV R0,14(SP) ; пересылка в стек на место числа A
1456+
MOV R1,16(SP) ; младшее слово
13241457
;ENDM: Завершение
1325-
;MOV (SP)+,R3 ; восстановление регистров
1326-
MOV (SP)+,R4
1327-
MOV (SP)+,R5
1458+
MOV (SP)+,R3 ; восстановление регистров
1459+
MOV (SP)+,R2
1460+
MOV (SP)+,R1
1461+
MOV (SP)+,R0
13281462
CMP (SP)+,(SP)+ ; удаление числа B из стека
13291463
FMUL$X: JMP @#000000 ; возврат, адрес подставляется в начале
13301464
;

runtime-UKNC.tmac

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,11 +1033,12 @@ FSQR$K: MOV FSQR$X+2, R5 ;
10331033
; (SP+2)(SP+4) - число с плавающей точкой (старшее слово, младшее слово)
10341034
; На выходе: (SP)(SP+2) - результат
10351035
FCOS:
1036-
MOV (SP)+, R5 ; адрес возврата
1036+
MOV (SP)+, 10$+2 ; адрес возврата
10371037
MOV #007733,-(SP) ; младшее слово PI/2
10381038
MOV #040311,-(SP) ; старшее слово PI/2
10391039
FADD SP ; сложение: аргумент + PI/2
1040-
BR FSIN1 ; дальше через вычисление синуса
1040+
10$: MOV #000000, -(SP) ; адрес возврата
1041+
BR FSIN ; дальше через вычисление синуса
10411042

10421043
;#####################################################################
10431044
;## FSIN
@@ -1062,9 +1063,7 @@ FCOS:
10621063
; (SP+2)(SP+4) - число с плавающей точкой (старшее слово, младшее слово)
10631064
; На выходе: (SP)(SP+2) - результат
10641065
FSIN:
1065-
MOV (SP)+, R5 ; адрес возврата
1066-
; Точка входа из FCOS
1067-
FSIN1:
1066+
MOV (SP)+, FSIN$X+2 ; адрес возврата
10681067
; На стеке: (SP)(SP+2) - исходное число
10691068
CLR -(SP) ; выделить место под хранение знака
10701069
MOV 4(SP),-(SP) ; скопировать аргумент (старшее)
@@ -1131,7 +1130,7 @@ FSIN1:
11311130
14$: MOV (SP)+,4(SP) ; переместить результат на место исходного аргумента
11321131
MOV (SP)+,4(SP)
11331132
TST (SP)+ ; подчищаем стек
1134-
JMP @R5 ; возврат
1133+
FSIN$X: JMP @#000000 ; возврат
11351134
;
11361135
; Таблица коэффициентов для полиномиальной аппроксимации синуса/косинуса
11371136
FSIN$T: .WORD 153672, 035036 ; a5 (~= 0.000151484)

0 commit comments

Comments
 (0)