@@ -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
10791201FADD:
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:
110212291$: 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:
111212382$: 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
1134126022$: 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
117513007$: 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:
1189131450$: 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:
119413238$: TST R0
11951324 BGT 9$
@@ -1219,9 +1348,10 @@ FADD:
12191348 CLR R1
1220134912$: 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
12501382FMUL:
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 из стека
13291463FMUL$X: JMP @#000000 ; возврат, адрес подставляется в начале
13301464;
0 commit comments