Skip to content

Commit 0c5b4a6

Browse files
committed
WIP FINT/FDIV for BK0010
1 parent cd315e9 commit 0c5b4a6

2 files changed

Lines changed: 172 additions & 6 deletions

File tree

BasicCompiler-VS2022.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
108108
<ConformanceMode>true</ConformanceMode>
109109
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
110+
<LanguageStandard>stdcpp17</LanguageStandard>
110111
</ClCompile>
111112
<Link>
112113
<SubSystem>Console</SubSystem>

runtime-BK0010.tmac

Lines changed: 171 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ IMULOV: MOV (SP), R5 ;
225225
MOV #1706., R0 ; Ошибка: переполнение
226226
JMP ERRR
227227
;
228-
; DAUG ? умножение двух 16-разрядных положительных чисел (R1 * R0).
228+
; DAUG - умножение двух 16-разрядных положительных чисел (R1 * R0).
229229
; Вход: R1, R0 ? положительные числа (0..32767).
230230
; Выход: результат в R5 (старшее слово) и R1 (младшее).
231231
; Если результат не помещается в 32 бита (переполнение), возвращает R5 = -1.
@@ -441,6 +441,41 @@ FFIX:
441441
;
442442
JMP @R5 ; возврат
443443

444+
;#####################################################################
445+
;## FINT
446+
;## Need FFIX
447+
;## Need FCMP
448+
; Для плавающего числа (float) получает целое, меньшее чем аргумент.
449+
; Для положительных чисел идёт к нулю, для отрицательных чисел идёт от нуля.
450+
; На основе кода процедуры INT из реализации Бейсик Вильнюс для УКНЦ.
451+
; На входе: (SP) - адрес возврата
452+
; (SP+2)(SP+4) - плвающее число (старшее слово, младшее слово)
453+
; Результат: (SP)(SP+2) - плвающее число (старшее слово, младшее слово)
454+
FINT:
455+
TST 2(SP) ; проверить знак числа (старшее слово)
456+
BPL FFIX ; положительное или 0 => так же как FIX
457+
; Отрицательное число: нужно округлить вниз, от нуля
458+
CMP -(SP),-(SP) ; резервируем место на стеке
459+
MOV 10(SP),-(SP) ; дублируем исходное число на стек
460+
MOV 10(SP),-(SP)
461+
MOV 2(SP),-(SP) ; дублируем исходное число ещё раз
462+
MOV 2(SP),-(SP)
463+
; На стеке: исх.число, исх.число, (SP+10)(SP+12) резерв, адрес возврата, исх.число
464+
CALL FFIX ; отбрасываем дробную часть
465+
MOV (SP),10(SP) ; копируем результат FIX в зарезерв. место на стеке
466+
MOV 2(SP),12(SP)
467+
CALL FCMP ; сравниваем два floats на стеке, снимает 4 слова
468+
; На стеке: результат FIX, адрес возврата, исходное число
469+
BEQ 1$ ; числа равны => нет дробной части
470+
CLR -(SP) ; младшее слово константы 1.0
471+
MOV #40200,-(SP) ; старшее слово константы 1.0
472+
CALL FSUB ; вычитаем 1.0 из результата FIX
473+
1$:
474+
; На стеке: результат INT, (SP+4) адрес возврата, (SP+6)(SP+10) исходное число
475+
MOV (SP)+,4(SP) ; копируем результат поверх исходного числа
476+
MOV (SP)+,4(SP) ; и сдвигаем указатель стека
477+
RETURN ; возврат
478+
444479
;#####################################################################
445480
;## FINT
446481
;## Need FFIX
@@ -712,7 +747,7 @@ VISKAS: MOVB #40,(R2)+ ;
712747
MOV R5, (SP) ; адрес возврата
713748
JMP WRSTR1 ; выводим полученную строку R0, R2 = длина
714749
;
715-
; DG4DL5 ? умножение 24-битного числа (R1:R0) на 4/5 (0.8)
750+
; DG4DL5 - умножение 24-битного числа (R1:R0) на 4/5 (0.8)
716751
; путём многократного деления на 2 и сложения с исходным значением.
717752
; Используется для извлечения десятичных цифр при выводе чисел.
718753
; Вход: R0 ? старшее слово, R1 ? младшее слово (24-битное число).
@@ -1035,7 +1070,7 @@ FSUB:
10351070

10361071
;#####################################################################
10371072
;## FMUL
1038-
; Умножение для плавающих чисел, параметры B и A на стеке
1073+
; Умножение для плавающих чисел, параметры B и A на стеке.
10391074
; На основе кода процедуры MLR из реализации Бейсик Вильнюс для БК-0010.
10401075
; На входе: (SP) - адрес возврата
10411076
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
@@ -1163,10 +1198,140 @@ FMUL$P: ASR R4
11631198

11641199
;#####################################################################
11651200
;## FDIV
1166-
; Деление для float, эмуляция FIS, параметры B и A на стеке
1201+
; Деление для плавающих чисел, параметры B и A на стеке.
1202+
; На основе кода процедуры DVR из реализации Бейсик Вильнюс для БК-0010.
1203+
; На входе: (SP) - адрес возврата
1204+
; (SP+2)(SP+4) - плавающее число B (старшее, младшее слово)
1205+
; (SP+6)(SP+10) - плавающее число A (старшее, младшее слово)
1206+
; Результат: (SP)(SP+2) - плавающее число (старшее слово, младшее слово)
11671207
FDIV:
1168-
;TODO
1169-
RETURN ;STUB
1208+
MOV (SP)+, FDIV$X+2 ; снимаем и подставляем адрес возврата
1209+
MOV R5,-(SP) ; сохранение регистров
1210+
MOV R4,-(SP)
1211+
; Подготовительные действия
1212+
CLR R0 ; Подготовить место
1213+
CLR R1 ; для мантиссы
1214+
CLR -(SP) ; и знака результата
1215+
ASL 12(SP) ; Запомнить в стеке
1216+
ROL (SP) ; знак A
1217+
CLR -(SP) ; Выделить место для порядка результата
1218+
TST 10(SP) ; делитель 0 - ошибка
1219+
BNE 2$
1220+
TRAP 11.
1221+
2$: BISB 15(SP),(SP) ; запомнить знак A
1222+
BEQ FDIV$0 ; A = 0 => результат 0
1223+
BISB 14(SP),R0
1224+
SWAB R0 ; заслать в R0-R1
1225+
SEC ; мантиссу A,
1226+
ROR R0 ; присоединив спереди
1227+
BISB 17(SP),R0 ; значащий разряд
1228+
BISB 16(SP),R1
1229+
SWAB R1
1230+
CLR R2 ; подготовить место
1231+
CLR R3 ; для мантиссы делителя
1232+
ASL 10(SP) ; сформировать знак
1233+
ADC 2(SP) ; результата
1234+
BISB 11(SP),R2 ; подсчитать порядок
1235+
SUB R2,(SP) ; результата
1236+
CLR R2
1237+
BISB 10(SP),R2
1238+
SWAB R2 ; заслать в R2-R3
1239+
SEC ; мантиссу B
1240+
ROR R2
1241+
BISB 13(SP),R2
1242+
BISB 12(SP),R3
1243+
SWAB R3
1244+
; Переход на деление мантисс
1245+
CMP R0,R2 ; если A > B,
1246+
BCS FDIV$Z ; начинать вычитывать B
1247+
BHI FDIV$M ; с первого разряда A
1248+
CMP R1,R3 ; если A < B,
1249+
BHI FDIV$M ; начинать вычитывать
1250+
BNE FDIV$Z ; cо второго разряда A
1251+
CLR 14(SP) ; если A = B,
1252+
INC (SP) ; подготовить
1253+
CLR R5 ; формирование результата
1254+
BR FDIV$D ; c мантиссой 1
1255+
;
1256+
;REZ0: Подготовка формирования результата 0
1257+
FDIV$0: CMP (SP)+,(SP)+
1258+
BR FDIV$N
1259+
;
1260+
;EPERP: Обработка переполнения
1261+
FDIV$O: TRAP 6
1262+
;
1263+
; Обработка исчезновения порядка
1264+
EISNYK: TST (SP)+
1265+
;NUL: Формирование результата 0
1266+
FDIV$N: CLR 10(SP)
1267+
CLR 12(SP)
1268+
BR FDIV$E
1269+
;
1270+
;DAUG: Деление мантисс
1271+
FDIV$M: ROR R0 ; погашение
1272+
ROR R1 ; начального сдвига
1273+
INC (SP) ; подпрограммы DALYT
1274+
;MAZIAU:
1275+
FDIV$Z: MOV #11,R4 ; сформирование
1276+
CALL FDIV$T ; старшей части
1277+
MOVB R5,14(SP) ; мантиссы результата
1278+
TST R4 ; если мантиссы не сравнялись,
1279+
BEQ 20$ ; продолжать деление
1280+
CLR R5 ; младшая часть мантиссы
1281+
BR FDIV$D ; результата = 0
1282+
20$: MOV #20,R4 ; продолжение деления
1283+
CALL FDIV$T
1284+
;
1285+
;END: Формирование результата
1286+
FDIV$D: MOV (SP)+,R4 ; формирование порядка
1287+
ADD #200,R4
1288+
BLE EISNYK ; исчезновение порядка?
1289+
CMP #377,R4
1290+
BLT FDIV$O ; переполнение?
1291+
MOVB R4,13(SP) ; Присоединение порядка к мантиссе результата
1292+
ROR (SP)+ ; присоединение знака
1293+
ROR 10(SP)
1294+
ROR R5
1295+
ADC R5 ; округление
1296+
MOV R5,12(SP)
1297+
ADC 10(SP)
1298+
BCS FDIV$O ; переполнение?
1299+
BVS FDIV$O
1300+
;ENDD:
1301+
;ENDM: Завершение
1302+
FDIV$E: MOV (SP)+,R4 ; восстановление регистров
1303+
MOV (SP)+,R5
1304+
CMP (SP)+,(SP)+ ; удаление числа B из стека
1305+
FDIV$X: JMP @#000000 ; возврат
1306+
;
1307+
;DALYT: Подпрограмма деления мантисс
1308+
FDIV$T: ASL R5 ; сдвиг результата
1309+
ASL R1 ; и мантиссы A
1310+
ROL R0
1311+
BCS 30$ ; C=1 => A > B => вычитать
1312+
CMP R2,R0 ; сравнить A и B
1313+
BHI 32$ ; B > A => сдвинуть A
1314+
BCS 30$ ; B < A => вычитать B
1315+
CMP R3,R1 ; сравнить младшие
1316+
BHI 32$ ; части
1317+
BEQ 36$ ; A = B => окончить
1318+
;ATIMT:
1319+
30$: SUB R3,R1 ; вычитание A-B
1320+
SBC R0 ; сравнить A и B
1321+
SUB R2,R0
1322+
INC R5 ; Формирование единицы в результате
1323+
;SLINKT:
1324+
32$: DEC R4 ; результат сформирован?
1325+
BGT FDIV$T ; нет - продолжить
1326+
RETURN ; нет - окончить
1327+
;LYGU:
1328+
36$: INC R5 ; делимое и делитель
1329+
BR 41$ ; сравнились
1330+
40$: ASL R5 ; заполнить
1331+
41$: DEC R4 ; конец результата
1332+
BGT 40$ ; нолями
1333+
INC R4 ; признак окончания деления
1334+
RETURN
11701335

11711336
;#####################################################################
11721337
;## STCP

0 commit comments

Comments
 (0)