;; ;; Copyright (c) 2019 Marco Granati ;; ;; Permission to use, copy, modify, and distribute this software for any ;; purpose with or without fee is hereby granted, provided that the above ;; copyright notice and this permission notice appear in all copies. ;; ;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ;; ;; project: c16 floating point unit ;; name: fplib.inc ;; purpose: virtual fp co-processor interface ;; revision: 1.0 ;; date: 2019/04/01 ;----------------------------------------------------------------------------- ; FLOATING POINT STATIC LIBRARY INTERFACE ; ; Floating point/integer routines for string/numeric and numeric/string ; conversion, and for move compact float point to/from virtual fp ; co-processor register's are statically linked at fixed addresses. ; These functions should be called by 'jsl' instructions. ; ; If a functions need some parameters on entry, they should be passed ; either by register or by stack: in the last case functions follow ; 'pascal convention' (parameters pushed on stack left-to-right). ; ; Stack cleanup is automatic when function exit. ; ; Below equates for easy call functions by symbolic name. ; ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; int2str - convert an integer to asciiz string (decimal or hexadecimal) ; ; this function should be called with "jsl" instruction ; ; function prototype: ; ; result = int2str(lpInt, nSize, nPrec, cFormat, nFlags) ; ; stack param's: ; ; : 1) long pointer to a buffer that hold the integer ; if the page pointer (lpInt<8..23>) is not zero ; 2) virtual math register (fr# 0..7) if the page ; pointer is zero (fr# = lpInt<0..7>) ; ; : integer size (1, 2, 3, 4, 8 or 16 bytes) ; if the integer source is a virtual math register ; this param is ignored and the size is taken from fr# ; ; : requested precision (minimum number of digits) ; : output format char: 'x', 'X', 'p', 'P', 'd' (see below) ; : additional formattation flags ; <7>: alternate format ; <6>: group thousands ; <5>: signed integer (ignored for fr# reg.) ; <1>: emit a sign '+' rather than a blank ; if bit 0 = 1 ; <0>: prefix positive decimal with '+' or blank ; prefix hexadecimal with '$' (or '0x' or ; with '0X' if alternate format flag is set) ; ; return: c = address of result string in bank 0 ; x = y = size of result string ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ; The integer parameter stored in memory or in fr# will be converted according ; to the format specifier and the requested precision, formatting the output ; ascii string null-terminated: ; ; p,P format: the integer is interpreted as long pointer (24 bits) and ; formatted as 6 hexadecimal digits prepended by '$' (or by ; '0x' or '0X' if alternate format was specified) and if ; nFlags<0> = 1; precision ignored. ; ; x,X format: the integer is converted as unsigned and formatted as ; sequence of hexadecimal digits prepended by '$' (or by ; '0x' or '0X' if alternate format was specified) and if ; nFlags<0> = 1. ; ; d format: the integer is converted according to the integer type ; either as signed or unsigned integer, and ; formatted as sequence of decimal digits. ; If nFlags<6>, thousands are grouped 3 digits by 3 digits, ; separated by a comma. ; ; The precision, if any, gives the minimum number of digits that must appear; ; if the converted value requires fewer digits, it is padded on the left ; with zeros (precision is ignored for pP format). ; ;----------------------------------------------------------------------------- int2str .equ $f80000 ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; str2int - convert the initial portion of the source string to ; an unsigned or signed integer (8, 16, 24, 32, 64 or 128 bits). ; ; function prototype: ; ; status = str2int(lpStr, lpRes, nSize, nSign, lpEnd, nBase) ; ; this function should be called with "jsl" instruction ; ; stack param's: ; ; : long pointer to source string ; : pointer to buffer for store result: ; 1) long pointer to a buffer that hold the integer ; if the page pointer (lpRes<8..23>) is not zero ; 2) virtual math register (fr# 0..7) if the page ; pointer is zero (fr# = lpRes<0..7>) ; : integer size (1, 2, 3, 4, 8 or 16 bytes) ; size = 3 force base to hexadecimal (pointer type) ; : flag: signed integer ($80) or unsigned ($00) ; hex conversion is forced unsigned ; : long pointer to 4 bytes buffer to store the address ; of the first invalid char in the given base, and ; minimum number of bytes that can hold the integer ; : numeric base for conversion: 10 (decimal), 16 (hex) ; or 0; if nBase = 0, conversion is done in base 16 ; if string start with '$' or '0x' or '0X' prefix, ; otherwise is done in base 10 ; ; return: status register affected by operation ; cf set if input string is invalid (return integer = 0) ; vf set if conversion cause overflow for given size ; nf set if number is negative ; zf set if number is zero ; result is stored or in one fr register (0..7), or in ; memory buffer ; ; if lpEnd is not null, the address of the first invalid ; char for the given base is stored in a 4 bytes buffer ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ; Conversion start parsing source string from left toward right, skipping any ; leading blank and/or tab: if initial portion of string begin with '$', ; or '0x', or '0X' (base=0), or the given base is 16, the conversion is done ; in base 16, otherwise in base 10. ; In decimal conversion an optional single sign '+' or '-' can precede first ; decimal digit, while in hexadecimal conversion just hexadecimal's digits ; (both lower/upper case) can follow the initial optional '$' or '0x'. ; Conversion stop at the end of the string or at the first character that ; does not produce a valid digit in the given base, and lpEnd (if not null) ; hold the long pointer to this character. ; ;----------------------------------------------------------------------------- str2int .equ $f80003 ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; fp2str - convert a quadruple precision floating point to asciiz string ; ; this function should be called with "jsl" instruction ; ; function prototype: ; ; result = fp2str(lpFloat, nPrec, cFormat, nFlags) ; ; stack param's: ; ; : 1) long pointer to a buffer that hold the packed fp ; if the page pointer (lpFloat<8..23>) is not zero ; 2) virtual math register (fr# 0..7) if the page ; pointer is zero (fr# = lpFloat<0..7>) ; : requested precision/count of decimal digits ; : output format char: format: e,E,f,F,g,G,a,A,k,K ; : additional formattation flags ; <7>: alternate format ; <6>: not discriminate +0.0 from -0.0 ; <5>: if lpFloat point to a user buffer and ; this bit is set, the user buffer is ; treated as unpacked float (20 bytes) ; <1>: emit a sign '+' rather than a blank ; if bit 0 = 1 ; <0>: prefix positive decimal with '+' or blank ; prefix hexadecimal with '$' (or '0x' or ; with '0X' if alternate format flag is set) ; ; return: c = address of result string in bank 0 ; x = y = size of result string ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ; The formatted decimal string is either the f/F format: ; [sign]ddd.ddd ; or the e/E format: ; [sign]d.ddde+|-[d][d]dd ; where the number of digits after the decimal-point character is equal to ; precision specification. The exponent in E format always contains at least ; two digits; if the value is zero, the exponent is 00. ; In the G format, precision specifies the number of significant digits: if ; it is zero, is teeated as 1. G format can format decimal string in E style ; or F style: style E is used if the exponent from its conversion is less ; than -4 or greater than or equal to the precision. ; Trailing decimal points are usually suppressed, as also are trailing ; fraction zeroes in the G/g format. If bit 7 of additional flag is 1 ; then trailing decimal dot remain, and G/g format will not trim zeroes. ; The format a/A format an hexadecimal string that contain 32 hexadecimal ; digits (the content of the 128 bits mantissa), followed by the biased ; exponent (introduced by literal 'p' or 'P'), or-ed at bit 15 with sign of ; the float. Hexadecimal string is prepended either by '$' or '0x' or '0X'. ; The no-standard format k/K format an hexadecimal string that contain the 32 ; hexadecimal digits of the packed float (ieee format). ; ; The result formatted string can have at max. 80 characters: if the ; requested format & precision cannot fit into this limit, the format is ; switched to 'E' and limited in size. ; ;----------------------------------------------------------------------------- fp2str .equ $f80006 ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; str2fp - convert the initial portion of the source string to ; a 128 bits binary floating point. ; ; function prototype ; ; status = str2fp(lpStr, lpRes, lpEnd) ; ; this function should be called with "jsl" instruction ; ; stack param's: ; ; : long pointer to source string ; : pointer to result buffer: ; 1) long pointer to a buffer that hold the integer ; if the page pointer (lpRes<8..23>) is not zero ; 2) virtual math register (fr# 0..7) if the page ; pointer is zero (fr# = lpRes<0..7>) ; : long pointer to 3 bytes buffer to store the address ; of the first invalid char that stop the conversion ; : if lpRes is a memory buffer, this param, if not zero, ; cause store the result unpacked (20 bytes) as in fr# ; ; return: status register affected by operation status ; cf set if conversion return a nan/inf ; vf set if conversion return inf, else vf = 0 ; nf set if number is negative ; zf set if number is zero ; invalid input string give result=nan (cf = 1, vf = 0) ; ; result is stored unpacked in fr# reg. or ; rounded, packed and stored in memory ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ; Conversion start parsing source string from left toward right, skipping any ; leading blank and/or tab. ; The expected form of the input string is either: ; ; +o an hexadecimal ascii string beginning with '$' or '0x' or '0X', ; followed by exactly 32 hexadecimal digits (case don't care) for ; the significand, followed by a 'p' or a 'P', followed by 4 ; hexadecimals digits for the biased exponent. Significand sign ; should be ored with msb of the biased exponent. ; Example: ; $80000000000000000000000000000000pbfff = -1.0 ; $80000000000000000000000000000000p3fff = +1.0 ; $00000000000000000000000000000000p0000 = +0.0 ; Number 0.0 can be expressed either by significand=0 and/or ; exponent=0. ; ; +o an hexadecimal ascii string beginning with '$' or '0x' or '0X', ; followed by exactly 32 hexadecimal digits (case don't care) for ; the input string seen as a packed standard ieee quadruple format. ; Example: ; $bfff0000000000000000000000000000 = -1.0 ; $3fff0000000000000000000000000000 = +1.0 ; $00000000000000000000000000000000 = +0.0 ; ; +o a decimal ascii string, beginning with an optional single '+' ; or '-' sign, followed by a decimal significand consisting of a ; sequence of decimal digits optionally containing a decimal-point ; character, '.'. The significand may be optionally followed by an ; exponent. An exponent consists of an 'E' or 'e' followed by an ; optional plus or minus sign, followed by a sequence of decimal ; digits; the exponent indicates the power of 10 by which the ; significand should be scaled. ; ; +o a string "+INF", "-INF", "+NAN", "-NAN", where the sign '+' or ; '-' is optional (case don't care). ; ; Conversion stop at the end of the string or at the first character that ; does not produce a valid digit in the given base and buffer pointed by lpEnd ; hold the long pointer to this character (if lpEnd not null). ; ;----------------------------------------------------------------------------- str2fp .equ $f80009 ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; fmovedp - move dp used by fp module in a memory buffer in bank 0 ; ; this function should be called with "jsl" instruction ; ; entry: c = destination address ; ; exit: none (dp page used by fp unit is moved to user buffer) ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ;----------------------------------------------------------------------------- fmovedp .equ $f8000c ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ; frestdp - restore dp used by fp module from a memory buffer in bank 0 ; ; this function should be called with "jsl" instruction ; ; entry: c = source address ; ; exit: none ; ; note: all registers are used ; this function can be called with both cpu regs. size ; ;----------------------------------------------------------------------------- frestdp .equ $f8000f ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; end of file ;-----------------------------------------------------------------------------