Mercurial > hg > index.cgi
view src/number.s @ 80:bb50ac9fdf37
Checkpoint with very basic integer and floating point arithmetic, untested
This commit has implementations for floating point add, subtract, multiply,
and divide, along with 32 bit signed integer equivalents. These can probably
be optimized and they are untested.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 07 Oct 2023 02:56:59 -0600 |
parents | df86e6d64ce2 |
children | f959c92bc329 |
line wrap: on
line source
*pragmapush list *pragma list ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Arithmetic package ; ; This section contains routines that handle floating point and integer arithmetic. It mostly delegates to int.s and ; fps.s. ; ; Most routines take a pointer to a value accumulator in X. Some take two pointers with the second in U. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Match operands for a numeric calculation. This works as follows: ; ; * If both operands are the same, ensure the type is numeric and return ; * If one operand is floating point, convert the other to floating point, as long as it is numeric ; * If one or both operands are not numeric, raise a type mismatch ; The operands are in (X) and (U) val_matchtypes ldb val.type,x ; get the type of first argument cmpb #valtype_int ; is it integer? beq val_matchtypes0 ; brif so cmpb #valtype_float ; is it floating point? beq val_matchtypes1 ; brif so TMERROR ldb #err_tm ; raise a type mismatch jmp ERROR val_matchtypes0 ldb val.type,u ; get type of second operand cmpb #valtype_int ; is it integer? bne val_matchtypes2 ; brif not val_matchtypes3 rts ; both types int - we're good so return val_matchtypes2 cmpb #valtype_float ; is it floating point? bne TMERROR ; brif not - raise error pshs x ; save X which may be clobbered leay ,x ; point to input operand as destination for conversion jsr fps_fromint32 ; convert first argument to floating point puls x,pc ; restore second operand pointer and return val_matchtypes1 ldb val.type,u ; get second argument type cmpb #valtype_float ; is it floating point? beq val_matchtypes3 ; brif so - we're good cmpb #valtype_int ; is it integer? bne TMERROR ; brif not - invalid type combination pshs x ; save X which mill be clobbered leax ,u ; convert (U) to floating point leay ,u jsr fps_fromint32 puls x,pc ; restore argument pointer and return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Addition and subtraction of values; must enter with values of matching types and the result type already set ; to the correct type. ; ; Calculates (X) + (U) -> (Y) (addition) ; Calculates (X) - (U) -> (Y) (subtraction) val_add ldb val.type,x ; get type of left operand cmpb valtype_int ; is it integer? lbeq int32_add ; brif so - do integer addition cmpb #valtype_float ; floating point? lbeq fps_add ; brif so - do floating point addition jmp TMERROR ; we have a type we don't understand val_sub ldb val.type,x ; get type of left operand cmpb valtype_int ; is it integer? lbeq int32_sub ; brif so - do integer addition cmpb #valtype_float ; floating point? lbeq fps_sub ; brif so - do floating point addition jmp TMERROR ; we have a type we don't understand ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Multiplication ; ; Calculates (X) × (U) -> (Y) ; ; The result might overflow the integer type. In this case, an actual overflow error will occur. val_mul ldb val.type,x ; get type of left operand cmpb #valtype_int ; integer? lbeq int32_mul ; brif so - do integer multiplication cmpb #valtype_float ; is it float? lbeq fps_mul ; brif so - do floating point multiplication jmp TMERROR ; have an unhandled type - bail on it ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Division ; ; Calculates (X) ÷ (U) -> (Y) ; ; The integer operation simply truncates the result ("rounds toward zero") val_div ldb val.type,x ; get type of left operand cmpb #valtype_int ; integer? lbeq int32_div ; brif so - do integerdivision cmpb #valtype_float ; floating point? lbeq fps_div ; brif so - do floating point division jmp TMERROR ; unsupported type if 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Modulus - note that this is a division operator returning effectively the remainder, not an absolute value as is ; sometimes meant by "modulus". ; ; Calculates (X) <MOD> (U) -> (Y) ; ; Note: modulus will have the same sign as the quotient so that (U) * [(X) / (U)] + [(X) MOD (U)] gives (X) (integer) ; Note2: the modulus can be calculated on floating point values in which case it will represent the fraction part ; of the quotient multiplied by the divisor, again with the same sign as the quotient val_mod ldb val.type,x ; get type of left operand cmpb #valtype_int ; integer? lbeq int32_mod ; do integer modulus cmpb #valtype_float ; floating point? lbeq fps_mod ; floating point modulus jmp TMERROR ; unsupported type endc *pragmapop list