
%if 0

lDebug RN command - Register dump of FPU registers

Copyright (C) 1995-2003 Paul Vojta
Copyright (C) 2008-2023 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif


		; The layout for FSAVE/FRSTOR depends on mode and 16-/32-bit.

%if 0
	struc FPENV16
.cw:	resw 1	; 00h
.sw:	resw 1	; 02h
.tw:	resw 1	; 04h
.fip:	resw 1	; 06h IP offset
.opc:		; 08h RM: opcode (0-10), IP 16-19 in high bits
.fcs:	resw 1	; 08h PM: IP selector
.fop:	resw 1	; 0Ah operand pointer offset
.foph:		; 0Ch RM: operand pointer 16-19 in high bits
.fos:	resw 1	; 0Ch PM: operand pointer selector
	endstruc; 0Eh

	struc FPENV32
.cw:	resd 1	; 00h
.sw:	resd 1	; 04h
.tw:	resd 1	; 08h
.fip:	resd 1	; 0Ch ip offset (RM: bits 0-15 only)
.fopcr:		; 10h (dword) RM: opcode (0-10), ip (12-27)
.fcs:	resw 1	; 10h PM: ip selector
.fopcp:	resw 1	; 12h PM: opcode (bits 0-10)
.foo:	resd 1	; 14h operand pointer offset (RM: bits 0-15 only)
.fooh:		; 18h (dword) RM: operand pointer (12-27)
.fos:	resw 1	; 18h PM: operand pointer selector
	resw 1	; 1Ah PM: not used
	endstruc; 1Ch
%endif


	usesection lDEBUG_DATA_ENTRY

		; dumpregsFPU - Dump Floating Point Registers
fregnames:
	db "CW", "SW", "TW"
	db "OPC=", "IP=", "DP="
msg.empty:	db "empty"
	endarea msg.empty
msg.nan:	db "NaN"
	endarea msg.nan


	usesection lDEBUG_CODE

dumpregsFPU:
%if _RN_AUX
	extcallcall guard_auxbuff
	mov es, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
			; => auxbuff
	xor di, di	; -> auxbuff
%else
	mov di, rn_rm_buffer
internaldatarelocation
%endif
	mov cx, 128
	xor ax, ax
	rep stosw	; initialise auxbuff
%if _RN_AUX
 %if _AUXBUFFSIZE < (128 * 2)
  %error auxbuff not large enough for dumpregsFPU
 %endif
%endif
	mov di, relocated(line_out)
linkdatarelocation line_out
	mov si, fregnames
internaldatarelocation
%if _RN_AUX
	xor bx, bx	; es:bx -> auxbuff
	_386_o32
	fnsave [es:bx]

		; display CW, SW and TW
	push ss
	pop es		; es:di -> line_out
%else
	mov bx, rn_rm_buffer
internaldatarelocation
	_386_o32
	fnsave [bx]
%endif

	mov cx, 3
.nextfpr:
	movsw
	mov al, '='
	stosb
	xchg si, bx
%if _RN_AUX
	 mov ds, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
			; ds:si -> auxbuff entry
%endif
	_386_o32	; lodsd
	lodsw
%if _RN_AUX
	 push ss
	 pop ds		; ds:si -> fregnames entry
%endif
	xchg si, bx
	push ax
	extcallcall hexword
	mov al, 32
	stosb
	loop .nextfpr

		; display OPC
		; in 16-bit PM, there's no OPC
		; in 32-bit PM, there's one, but the location differs from RM
	push bx
%if _PM
	extcallcall ispm
	jnz .notpm_opc
	add bx, byte 2		; location of OPC in PM differs from RM
_no386	add si, byte 4		; no OPC in 16-bit PM
_no386	jmp short .no_opc
.notpm_opc:
%endif
	movsw
	movsw
	xchg si, bx
%if _RN_AUX
	 mov ds, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
				; ds:si -> auxbuff entry
%endif
	_386_o32	; lodsd
	lodsw			; skip word/dword
	lodsw
%if _RN_AUX
	 push ss
	 pop ds			; ds:si -> fregnames entry
%endif
	xchg si, bx
	and ax, 07FFh		; bits 0-10 only
	extcallcall hexword
	mov al, 32
	stosb
.no_opc:
	pop bx

		; display IP and DP
	mov cl, 2
.nextfp:
	push cx
%if _RN_AUX
	 push ss
	 pop ds			; ds:si -> fregnames entry
%endif
	movsw
	movsb
	xchg si, bx
%if _RN_AUX
	 mov ds, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
				; ds:si -> auxbuff entry
%endif
	_386_o32	; lodsd
	lodsw
	_386_o32	; mov edx, eax
	mov dx, ax
	_386_o32	; lodsd
	lodsw
	xchg si, bx
%if _RN_AUX
	 push ss
	 pop ds			; ds:si -> fregnames entry
%endif
%if _PM
	extcallcall ispm
	jnz .notpm_ipdp
	extcallcall hexword
	mov al, ':'
	stosb
	jmp short .fppm
.notpm_ipdp:
%endif
	mov cl, 12
	_386_o32	; shr eax, cl
	shr ax, cl
_386	extcallcall hexword
_386	jmp short .fppm
	extcallcall hexnyb
.fppm:
	_386_PM_o32	; mov eax, edx
	mov ax, dx
_386_PM	extcallcall ispm
_386_PM	jnz .notpm_fppm
_386_PM	extcallcall hexword_high
.notpm_fppm:
	extcallcall hexword
	mov al, 32
	stosb
	pop cx
	loop .nextfp

	xchg si, bx
%if _RN_AUX
	 push ss
	 pop ds			; ds = es = ss
%endif
	extcallcall trimputs

		; display ST0..7
	pop bp			; TW
	pop ax			; SW
	pop dx			; CW (discarded here)

	mov cl, 10
	shr ax, cl		; move TOP to bits 1..3
	and al, 1110b		; separate TOP
	mov cl, al
	ror bp, cl		; adjust TW

	mov cl, '0'
.nextst:
	mov di, relocated(line_out)
linkdatarelocation line_out
	push cx
	mov ax, "ST"
	stosw
	mov al, cl
	mov ah, '='
	stosw
	push di
	test al, 1
	mov al, 32
	mov cx, 22
	rep stosb
	jz .oddst
	mov ax, 10<<8|13
	stosw
.oddst:
	mov al, 0
	stosb			; make it an ASCIZ string
	pop di

	mov ax, bp
	ror bp, 1
	ror bp, 1
	and al, 3		; 00b = valid, 01b = zero, 10b = NaN, 11b = empty
	jz .isvalid
	push si
%if _RN_AUX
	 push ss
	 pop ds			; ds = es = ss
%endif
	mov si, msg.empty
internaldatarelocation
	mov cl, msg.empty_size
	cmp al, 3
	je .gotst
	mov si, msg.nan
internaldatarelocation
	mov cl, msg.nan_size
	cmp al, 2
	je .gotst
	mov al, '0'
	stosb
	xor cx, cx
.gotst:
	rep movsb
	pop si
	jmp short .regoutdone

.isvalid:
%if _RN_AUX
	 mov ds, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
				; ds:si -> auxbuff entry
	testopt [ss:relocated(options)], hexrn
linkdatarelocation options, -3
%else
	testopt [relocated(options)], hexrn
linkdatarelocation options, -3
%endif
	jnz .hex
	push di			; -> buffer (first parameter; in es = ss)
	push ds
	push si			; -> auxbuff entry (second parameter)
	dualcall FloatToStr
	jmp short .regoutdone

.hex:
	mov ax, word [si+8]
	extcallcall hexword
	mov al, '.'
	stosb
	mov ax, word [si+6]
	extcallcall hexword
	mov ax, word [si+4]
	extcallcall hexword
	mov ax, word [si+2]
	extcallcall hexword
	mov ax, word [si+0]
	extcallcall hexword

.regoutdone:
	mov dx, relocated(line_out)
linkdatarelocation line_out
%if _RN_AUX
	 push ss
	 pop ds			; ds = es = ss
%endif
	extcallcall putsz
	pop cx

	add si, byte 10		; -> next ST
	inc cl
	cmp cl, '8'
	jne .nextst
%if _RN_AUX
	 mov es, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
				; es => auxbuff
	_386_o32
	frstor [es:0]
%else
	_386_o32
	frstor [rn_rm_buffer]
internaldatarelocation
%endif
	retn
