mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-04-06 22:37:05 +00:00
Added library file for FLPT format.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@17 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
816bf713f2
commit
ffabea98c1
@ -4,10 +4,15 @@
|
||||
lib_cbm_c64_float_a = 1
|
||||
|
||||
; Here are some definitions to help you call the floating-point functions of the
|
||||
; C64's BASIC ROM. They work using two structures in zero page, called fac1 and
|
||||
; fac2 (floating-point accumulator 1 and 2, located at $61 and $69).
|
||||
; C64's BASIC ROM. They work on "float registers", which are actually just
|
||||
; structures in zero page:
|
||||
fac1_base = $61 ; base address of floating-point accumulator 1
|
||||
fac2_base = $69 ; base address of floating-point accumulator 2
|
||||
; There is really no need to use these addresses directly when calling the ROM
|
||||
; functions. You'd only need the addresses when using <cbm/flpt.a>.
|
||||
|
||||
!source <cbm/mflpt.a> ; include macro to store floats in MFLPT format
|
||||
!source <cbm/flpt.a> ; include macro to store floats in six-byte FLPT format
|
||||
!source <cbm/mflpt.a> ; include macro to store floats in five-byte MFLPT format
|
||||
|
||||
; convenience macros:
|
||||
|
||||
@ -72,24 +77,26 @@ fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
|
||||
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
|
||||
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
|
||||
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
|
||||
fac1_memAY_minus_fac1 = $b850
|
||||
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
|
||||
fac1_fac2_minus_fac1 = $b853
|
||||
fac1_add_memAY = $b867
|
||||
fac1_add_memAY = $b867 ; add mflpt value
|
||||
fac1_add_fac2 = $b86a
|
||||
fac1_log = $b9ea ; LOG()
|
||||
fac1_times_memAY = $ba28
|
||||
fac2_read_memAY = $ba8c ; load value from memory into fac2
|
||||
fac1_times_memAY = $ba28 ; multiply by mflpt value
|
||||
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
|
||||
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
|
||||
fac1_times_10 = $bae2
|
||||
fac1_divide_by_10 = $bafe
|
||||
fac1_divide_memAY_by_fac1 = $bb0f
|
||||
fac1_read_memAY = $bba2 ; load value from memory into fac1
|
||||
fac1_to_memXY = $bbd4 ; store fac1 to memory
|
||||
fac1_divide_memAY_by_fac1 = $bb0f ; divide mflpt value by fac1 value
|
||||
fac1_read_memAY = $bba2 ; load mflpt value from memory into fac1
|
||||
fac1_read_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
|
||||
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
|
||||
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
|
||||
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
|
||||
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
|
||||
fac1_sgn = $bc39 ; SGN()
|
||||
fac1_abs = $bc58 ; ABS()
|
||||
fac1_compare_to_memAY = $bc5b
|
||||
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
|
||||
fac1_to_signed32 = $bc9b
|
||||
fac1_int = $bccc ; INT()
|
||||
fac1_print_unsignedXA = $bdcd
|
||||
|
93
ACME_Lib/cbm/flpt.a
Normal file
93
ACME_Lib/cbm/flpt.a
Normal file
@ -0,0 +1,93 @@
|
||||
;ACME 0.94.5
|
||||
|
||||
!ifdef lib_cbm_flpt_a !eof
|
||||
lib_cbm_flpt_a = 1
|
||||
|
||||
; CAUTION! The Commodore BASIC interpreter uses two different formats for
|
||||
; handling floating-point values, so do not confuse them:
|
||||
; The "float registers" fac1 and fac2 (actually structures in zero page) use a
|
||||
; six-byte format commonly known as "flpt" (floating point).
|
||||
; When storing values in variables (or reading values from ROM), a compressed
|
||||
; five-byte format is used, commonly known as "mflpt" (memory floating point).
|
||||
|
||||
; This file contains a macro for writing floating point numbers in the six-byte
|
||||
; "flpt" format, where the sign bit occupies the sixth byte.
|
||||
; There are no interpreter functions to use this format, so you will have to
|
||||
; write you own functions for "copy-mem-to-fac1", "copy-fac2-to-mem" etc.
|
||||
|
||||
; Use the macro like this:
|
||||
; +flpt 3.1415926 ; each use will take up six bytes of memory
|
||||
|
||||
|
||||
; now for the technical stuff (stop reading right now if you value your sanity)
|
||||
|
||||
; six-byte layout in memory:
|
||||
; eeeeeeee 1mmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm sxxxxxxx ; eight bits exponent, 32 bits mantissa with leading '1', sign byte
|
||||
|
||||
; exponent byte:
|
||||
; exponent has a bias of 128 (128 means the decimal point is right before the mantissa's leading digit)
|
||||
; if exponent is zero, number value is considered to be zero, regardless of mantissa
|
||||
; exponents 1..128 are for values < 1
|
||||
; exponents 129..255 are for values >= 1
|
||||
|
||||
; mantissa:
|
||||
; mantissa is stored big-endian(!)
|
||||
; the mantissa's leading digit is always '1' (unless the whole value represents zero)
|
||||
|
||||
; sign byte:
|
||||
; most significant bit is sign: 0 means positive number, 1 means negative number
|
||||
; the seven lower bits are unused
|
||||
|
||||
; so logically, this is equivalent to:
|
||||
; + .1mmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm * 2^(eeeeeeee - 128) if sign bit is 0
|
||||
; - .1mmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm * 2^(eeeeeeee - 128) if sign bit is 1
|
||||
|
||||
|
||||
|
||||
; this is ugly, but it gets the job done
|
||||
; (if it's stupid, but it works, then it's not stupid)
|
||||
!macro flpt .value {
|
||||
!set .float = float(.value) ; make sure to do passes until value is defined
|
||||
!ifndef .float {
|
||||
!by $ff, $ff, $ff, $ff, $ff, $ff ; six place holder bytes
|
||||
} else {
|
||||
; value is defined, so split up into sign and non-negative value
|
||||
!if .float < 0 {
|
||||
!set .sign = $80
|
||||
!set .float = -.float
|
||||
} else {
|
||||
!set .sign = $00
|
||||
}
|
||||
!if .float = 0 {
|
||||
!by 0, 0, 0, 0, 0, 0 ; six zeroes (zero is represented by all bits zero)
|
||||
} else {
|
||||
; split up into exponent and mantissa
|
||||
!set .exponent = 128 + 32 ; 128 is cbm's bias, 32 is this algo's bias
|
||||
; if mantissa is too large, shift right and adjust exponent
|
||||
!do while .float >= (2.0 ^ 32.0) {
|
||||
!set .float = .float >> 1
|
||||
!set .exponent = .exponent + 1
|
||||
}
|
||||
; if mantissa is too small, shift left and adjust exponent
|
||||
!do while .float < (2.0 ^ 31.0) {
|
||||
!set .float = .float << 1
|
||||
!set .exponent = .exponent - 1
|
||||
}
|
||||
!if .exponent < 1 {
|
||||
!warn "FLPT underflow, using zero instead"
|
||||
!set .float = 0
|
||||
!set .exponent = 0
|
||||
!set .sign = 0
|
||||
}
|
||||
!if .exponent > 255 {
|
||||
!error "FLPT overflow"
|
||||
}
|
||||
!by .exponent
|
||||
!by 255 & int(.float >> 24)
|
||||
!by 255 & int(.float >> 16)
|
||||
!by 255 & int(.float >> 8)
|
||||
!by 255 & int(.float)
|
||||
!by .sign
|
||||
}
|
||||
}
|
||||
}
|
@ -3,20 +3,28 @@
|
||||
!ifdef lib_cbm_mflpt_a !eof
|
||||
lib_cbm_mflpt_a = 1
|
||||
|
||||
; here's a macro for writing floating point numbers in the "mflpt" format used by BASIC.
|
||||
; "mflpt" stands for "memory floating point", where the sign bit is packed into the mantissa.
|
||||
; CAUTION! The Commodore BASIC interpreter uses two different formats for
|
||||
; handling floating-point values, so do not confuse them:
|
||||
; The "float registers" fac1 and fac2 (actually structures in zero page) use a
|
||||
; six-byte format commonly known as "flpt" (floating point).
|
||||
; When storing values in variables (or reading values from ROM), a compressed
|
||||
; five-byte format is used, commonly known as "mflpt" (memory floating point).
|
||||
|
||||
; to use it, write:
|
||||
; This file contains a macro for writing floating point numbers in the five-byte
|
||||
; "mflpt" format, where the sign bit is packed into the mantissa.
|
||||
; Several interpreter functions use this format (see <cbm/c64/float.a>).
|
||||
|
||||
; Use the macro like this:
|
||||
; +mflpt 3.1415926 ; each use will take up five bytes of memory
|
||||
|
||||
|
||||
; now for the technical stuff (stop reading right now if you value your sanity)
|
||||
|
||||
; five-byte layout in memory:
|
||||
; eeeeeeee smmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm ; eight bits exponent, 32 bits mantissa with sign bit overlay
|
||||
; eeeeeeee smmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm ; eight bits exponent, 32 bits mantissa with sign bit overlay
|
||||
|
||||
; exponent byte:
|
||||
; exponent has a bias of 128 (128 means the decimal point is right before the mantissa's leading zero)
|
||||
; exponent has a bias of 128 (128 means the decimal point is right before the mantissa's leading digit)
|
||||
; if exponent is zero, number value is considered to be zero, regardless of mantissa
|
||||
; exponents 1..128 are for values < 1
|
||||
; exponents 129..255 are for values >= 1
|
||||
@ -36,7 +44,7 @@ lib_cbm_mflpt_a = 1
|
||||
!macro mflpt .value {
|
||||
!set .float = float(.value) ; make sure to do passes until value is defined
|
||||
!ifndef .float {
|
||||
!by $ff, $ff, $ff, $ff, $ff ; place holder
|
||||
!by $ff, $ff, $ff, $ff, $ff ; five place holder bytes
|
||||
} else {
|
||||
; value is defined, so split up into sign and non-negative value
|
||||
!if .float < 0 {
|
||||
@ -46,7 +54,7 @@ lib_cbm_mflpt_a = 1
|
||||
!set .sign = $00
|
||||
}
|
||||
!if .float = 0 {
|
||||
!by 0, 0, 0, 0, 0 ; zero is represented as all bits zero
|
||||
!by 0, 0, 0, 0, 0 ; five zeroes (zero is represented by all bits zero)
|
||||
} else {
|
||||
; split up into exponent and mantissa
|
||||
!set .exponent = 128 + 32 ; 128 is cbm's bias, 32 is this algo's bias
|
||||
|
Loading…
x
Reference in New Issue
Block a user