; Differential probe for the unmodified Borland Real48 core in TDKPIN.EXE. ; Assemble from original/ so INCBIN addresses the authoritative target bytes. bits 16 org 0x100 jmp main integer_inputs: dd 0, 1, -1, 2, 0x7fffffff, 0x80000000, 123456789, -123456789 integer_input_count equ ($ - integer_inputs) / 4 round_inputs: db 0x80,0,0,0,0,0 ; +0.5 db 0x80,0,0,0,0,0x80 ; -0.5 db 0x7f,0xff,0xff,0xff,0xff,0x7f ; largest value below +0.5 db 0x81,0,0,0,0,0x40 ; +1.5 db 0x81,0xff,0xff,0xff,0xff,0x3f ; largest value below +1.5 db 0xa0,0,0,0,0,0 ; +2^31, overflow db 0xa0,0,0,0,0,0x80 ; -2^31 db 0xa0,0,1,0,0,0x80 ; below -2^31, overflow round_input_count equ ($ - round_inputs) / 6 arithmetic_pairs: db 0x81,0,0,0,0,0, 0x81,0,0,0,0,0 ; 1, 1 db 0x81,0,0,0,0,0x40, 0x80,0,0,0,0,0 ; 1.5, 0.5 db 0x81,0,0,0,0,0x40, 0x80,0,0,0,0,0x80 ; 1.5, -0.5 db 0x01,0,0,0,0,0, 0x80,0,0,0,0,0 ; minimum, 0.5 db 0xff,0xff,0xff,0xff,0xff,0x7f, 0xff,0xff,0xff,0xff,0xff,0x7f db 0x81,0,0,0,0,0x40, 0x82,0,0,0,0,0 ; 1.5, 2 arithmetic_pair_count equ ($ - arithmetic_pairs) / 12 part_inputs: db 0x80,0,0,0,0,0 ; +0.5 db 0x81,0,0,0,0,0x60 ; +1.75 db 0x81,0,0,0,0,0xe0 ; -1.75 db 0x01,0,0,0,0,0 ; minimum positive db 0xa8,0x55,0xaa,0x55,0xaa,0x55 ; already wholly integral part_input_count equ ($ - part_inputs) / 6 sqrt_inputs: db 0,0,0,0,0,0 db 0x81,0,0,0,0,0 ; 1 db 0x82,0,0,0,0,0 ; 2 db 0x83,0,0,0,0,0 ; 4 db 0x81,0,0,0,0,0x40 ; 1.5 sqrt_input_count equ ($ - sqrt_inputs) / 6 atan_series_inputs: db 0,0,0,0,0,0 db 0x7f,0,0,0,0,0 ; 0.25 db 0x80,0,0,0,0,0 ; 0.5 db 0x7f,0xe7,0xcf,0xcc,0x13,0x54 ; sqrt(2)-1 atan_series_input_count equ ($ - atan_series_inputs) / 6 arctan_inputs: db 0,0,0,0,0,0 db 0x7e,0,0,0,0,0 ; 0.125 db 0x80,0,0,0,0,0 ; 0.5 db 0x81,0,0,0,0,0 ; 1 db 0x82,0,0,0,0,0 ; 2 db 0x81,0,0,0,0,0x80 ; -1 arctan_input_count equ ($ - arctan_inputs) / 6 ln_inputs: db 0x80,0,0,0,0,0 ; 0.5 db 0x81,0,0,0,0,0 ; 1 db 0x82,0,0,0,0,0 ; 2 db 0x81,0,0,0,0,0x40 ; 1.5 db 0x84,0,0,0,0,0x20 ; 10 ln_input_count equ ($ - ln_inputs) / 6 exp_inputs: db 0x82,0,0,0,0,0x80 ; -2 db 0x81,0,0,0,0,0x80 ; -1 db 0x80,0,0,0,0,0x80 ; -0.5 db 0,0,0,0,0,0 db 0x80,0,0,0,0,0 ; 0.5 db 0x81,0,0,0,0,0 ; 1 db 0x82,0,0,0,0,0 ; 2 db 0x84,0,0,0,0,0x20 ; 10 exp_input_count equ ($ - exp_inputs) / 6 trig_inputs: db 0,0,0,0,0,0 db 0x80,0x6a,0xc1,0x91,0x0a,0x06 ; pi/6 db 0x81,0x21,0xa2,0xda,0x0f,0x49 ; pi/2 db 0x82,0x21,0xa2,0xda,0x0f,0x49 ; pi db 0x83,0x21,0xa2,0xda,0x0f,0x49 ; 2*pi db 0x81,0x21,0xa2,0xda,0x0f,0xc9 ; -pi/2 db 0x81,0,0,0,0,0 ; 1 trig_input_count equ ($ - trig_inputs) / 6 probe_output: times integer_input_count * 6 db 0 round_output equ $ times round_input_count * 5 db 0 arithmetic_output equ $ times arithmetic_pair_count * 28 db 0 part_output equ $ times part_input_count * 12 db 0 sqrt_output equ $ times sqrt_input_count * 6 db 0 atan_series_output equ $ times atan_series_input_count * 6 db 0 arctan_output equ $ times arctan_input_count * 6 db 0 ln_output equ $ times ln_input_count * 6 db 0 exp_output equ $ times exp_input_count * 6 db 0 sin_output equ $ times trig_input_count * 6 db 0 cos_output equ $ times trig_input_count * 6 db 0 probe_output_end: output_name db 'R48.OUT',0 arithmetic_input_cursor dw arithmetic_pairs arithmetic_output_cursor dw arithmetic_output arithmetic_remaining db arithmetic_pair_count part_input_cursor dw part_inputs part_output_cursor dw part_output part_remaining db part_input_count sqrt_input_cursor dw sqrt_inputs sqrt_output_cursor dw sqrt_output sqrt_remaining db sqrt_input_count atan_series_input_cursor dw atan_series_inputs atan_series_output_cursor dw atan_series_output atan_series_remaining db atan_series_input_count arctan_input_cursor dw arctan_inputs arctan_output_cursor dw arctan_output arctan_remaining db arctan_input_count ln_input_cursor dw ln_inputs ln_output_cursor dw ln_output ln_remaining db ln_input_count exp_input_cursor dw exp_inputs exp_output_cursor dw exp_output exp_remaining db exp_input_count trig_input_cursor dw trig_inputs sin_output_cursor dw sin_output cos_output_cursor dw cos_output trig_remaining db trig_input_count ; Code5 file offset 108800 + 0x0cd0. Keeping the slice contiguous preserves ; every near displacement among the conversion/compare core routines. It is ; also placed at its original CS offset so absolute table references 1191.. ; 1435 used by the transcendental helpers continue to address original bytes. times (0x0bd0 - ($ - $$)) db 0 real48_core: incbin "TDKPIN.EXE", 112080, 0x7d4 real48_i32_to_registers equ real48_core + (0x0f3b - 0x0cd0) real48_registers_to_i32 equ real48_core + (0x0f77 - 0x0cd0) real48_add_registers equ real48_core + (0x0cd4 - 0x0cd0) real48_subtract_registers equ real48_core real48_multiply_registers equ real48_core + (0x0d97 - 0x0cd0) real48_divide_registers equ real48_core + (0x0e9a - 0x0cd0) real48_integer_part equ real48_core + (0x1059 - 0x0cd0) real48_fractional_part equ real48_core + (0x10aa - 0x0cd0) real48_sqrt equ real48_core + (0x10be - 0x0cd0) real48_arctan_series equ real48_core + (0x1436 - 0x0cd0) real48_arctan equ real48_core + (0x1307 - 0x0cd0) real48_ln equ real48_core + (0x11bb - 0x0cd0) real48_exp equ real48_core + (0x1264 - 0x0cd0) real48_sin equ real48_core + (0x1130 - 0x0cd0) real48_cos equ real48_core + (0x111d - 0x0cd0) %macro probe_arithmetic 1 mov bp, [arithmetic_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] mov cx, [bp + 6] mov si, [bp + 8] mov di, [bp + 10] call %1 pushf mov di, [arithmetic_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx pop ax and al, 1 mov [di + 6], al add word [arithmetic_output_cursor], 7 %endmacro %macro probe_trig 2 mov bp, [trig_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call %1 mov di, [%2] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [%2], 6 %endmacro %macro probe_exp 0 mov bp, [exp_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call real48_exp mov di, [exp_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [exp_output_cursor], 6 %endmacro %macro probe_ln 0 mov bp, [ln_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call real48_ln mov di, [ln_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [ln_output_cursor], 6 %endmacro %macro probe_arctan 0 mov bp, [arctan_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call real48_arctan mov di, [arctan_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [arctan_output_cursor], 6 %endmacro %macro probe_atan_series 0 mov bp, [atan_series_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] call real48_arctan_series mov di, [atan_series_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [atan_series_output_cursor], 6 %endmacro %macro probe_sqrt 0 mov bp, [sqrt_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call real48_sqrt mov di, [sqrt_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [sqrt_output_cursor], 6 %endmacro %macro probe_part 1 mov bp, [part_input_cursor] mov ax, [bp] mov bx, [bp + 2] mov dx, [bp + 4] push cs call %1 mov di, [part_output_cursor] mov [di], ax mov [di + 2], bx mov [di + 4], dx add word [part_output_cursor], 6 %endmacro main: push cs pop ds push cs pop es mov si, integer_inputs mov di, probe_output mov cx, integer_input_count .integer_loop: mov ax, [si] mov dx, [si + 2] push cx call real48_i32_to_registers pop cx stosw ; exponent/low fraction mov ax, bx stosw ; middle fraction mov ax, dx stosw ; high fraction/sign add si, 4 loop .integer_loop mov si, round_inputs mov di, round_output mov bp, round_input_count .round_loop: mov ax, [si] mov bx, [si + 2] mov dx, [si + 4] mov ch, 1 ; Borland Round entry mode call real48_registers_to_i32 stosw mov ax, dx stosw mov byte [di], 0 jnc .round_no_overflow inc byte [di] .round_no_overflow: inc di add si, 6 dec bp jnz .round_loop .arithmetic_loop: probe_arithmetic real48_add_registers probe_arithmetic real48_subtract_registers probe_arithmetic real48_multiply_registers probe_arithmetic real48_divide_registers add word [arithmetic_input_cursor], 12 dec byte [arithmetic_remaining] jnz .arithmetic_loop .part_loop: probe_part real48_integer_part probe_part real48_fractional_part add word [part_input_cursor], 6 dec byte [part_remaining] jnz .part_loop .sqrt_loop: probe_sqrt add word [sqrt_input_cursor], 6 dec byte [sqrt_remaining] jnz .sqrt_loop .atan_series_loop: probe_atan_series add word [atan_series_input_cursor], 6 dec byte [atan_series_remaining] jnz .atan_series_loop .arctan_loop: probe_arctan add word [arctan_input_cursor], 6 dec byte [arctan_remaining] jnz .arctan_loop .ln_loop: probe_ln add word [ln_input_cursor], 6 dec byte [ln_remaining] jnz .ln_loop .exp_loop: probe_exp add word [exp_input_cursor], 6 dec byte [exp_remaining] jnz .exp_loop .trig_loop: probe_trig real48_sin, sin_output_cursor probe_trig real48_cos, cos_output_cursor add word [trig_input_cursor], 6 dec byte [trig_remaining] jnz .trig_loop mov dx, output_name xor cx, cx mov ah, 0x3c ; create/truncate int 0x21 jc .failure mov bx, ax mov dx, probe_output mov cx, probe_output_end - probe_output mov ah, 0x40 int 0x21 mov ah, 0x3e int 0x21 mov ax, 0x4c00 int 0x21 .failure: mov ax, 0x4c01 int 0x21