makro parameter type
Moderators: David Barker, Jerry Messina
makro parameter type
Is there a way to recognise type of parameter passed to makro? Size of the parameter may be determined with sizeOf or checkParam, but how to differentiate integer from word or longint from longword?
-
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Re: makro parameter type
I'm not aware of a way to tell if it's a signed/unsigned type.
Re: makro parameter type
Oh well, I'll have to have 2 macros instead of one then. Just thought that if it's possible to get from the compiler info about variable being declared a float and not a longword then there could as well be a way to recognize signed type.
- David Barker
- Swordfish Developer
- Posts: 1214
- Joined: Tue Oct 03, 2006 7:01 pm
- Location: Saltburn by the Sea, UK
- Contact:
Re: makro parameter type
You can use overloaded inline subs. There is an assignment cost but without knowing what you are trying to do, I don't know if it's worth it...
Re: makro parameter type
Thank you David - I already have ideas to use this feature in other cases. I've built own math library to avoid some shortcomings (from my point of view) of the present one and to add diagnostics. Thanks to the effectiveness of macros in SF it produces no unnecessary overhead though obviously it will not be as convenient in use as internal math library. On the other hand, beside the built-in diagnostics and more predictable behaviour at range limits, it's faster on average, and in some cases produces results even much faster - and I need that speed advantage.
An example macro looks like thisSF compiler nicely takes care of adjusting to the resulting type and one may mix types of arguments with additional time savings in cases like
where 16-bit multiplication routine is used instead of 32-bit one as it already produces 32-bit result.
An example macro looks like this
Code: Select all
// integer multiplication y=x1*x2
public macro mul(y,x1,x2)
if checkparam(y,cpInteger) and checkparam(x1,cpInteger) and checkparam(x2,cpInteger) then
if sizeof(x1)=1 and sizeof(x2)=1 then
y=x1*x2
elseif sizeof(x1)=4 or sizeof(x2)=4 then
D0.asLongword=x1
D4.asLongword=x2
Mul_32x32_U
y=D0.asLongword
elseif sizeof(x1)=2 or sizeof(x2)=2 then
D0.asWord=x1
D4.asWord=x2
Mul_16x16_U()
y=D0.asLongword
end if
else
checkparam(etError, "Every parameter of mul must be an integer!")
end if
end macro {mul(y,x1,x2)}
Code: Select all
mul(longword_var,word_var,word_var)
-
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Re: makro parameter type
Most of the multi-byte multiply routines in the library use a 'loop and add' algorithm instead of the hdw multiplier.where 16-bit multiplication routine is used instead of 32-bit one...
I'm not sure what the original rational for using a 32-bit multiply for 16x16 was since the library has code for a 16x16=32 that uses the MUL instruction, but it's been that way for a looong time. Maybe to (potentially) save code space??
A quick glance at the 16x16 MUL routine looks like it's correct. The only thing I see as a potential issue is that the two routines use different system registers for input/output. I'll take a closer look at it.
Re: makro parameter type
So I've noticed. Additionally, signed 16-bit multiplication uses 32x32-bit routine and it takes 810 cycles to finish while specialised routine with hardware multiplication does it in 47 cycles (just an example for some numbers). That's the most excessive example for my need of optimisation though. Other comparisons are not nearly that bad.Jerry Messina wrote: ↑Tue Sep 06, 2022 11:16 amMost of the multi-byte multiply routines in the library use a 'loop and add' algorithm instead of the hdw multiplier.
It certainly saves space if one routine is used for different arguments but with PIC18 processors it seems unnecessary. Anyway, one may always force the compiler to use routines for one type of variables with typecasting.I'm not sure what the original rational for using a 32-bit multiply for 16x16 was since the library has code for a 16x16=32 that uses the MUL instruction, but it's been that way for a looong time. Maybe to (potentially) save code space??
If you need some help (if not with coding then with testing) then I'm willing.A quick glance at the 16x16 MUL routine looks like it's correct. The only thing I see as a potential issue is that the two routines use different system registers for input/output. I'll take a closer look at it.
I've noticed that the unsigned 16-bit division routine can easily be optimised (I've replaced the SB_SVx variables with the short Dx ones):
Code: Select all
// D0,1/D4,5 -> D0(W),1 remainder in D6,7
sub DVD16X16()
asm
CLRF D7
CLRF D6
MOVLW 16
MOVWF D16
DVD16X16LP:
RLCF D1,W
RLCF D6,F
RLCF D7,F
MOVF D4,W
SUBWF D6,F
MOVF D5,W
//BTFSS STATUS,C
//INCFSZ D5,W
//SUBWF D7,F
SUBWFB D7,F
BC DVD16X16LP2
MOVF D4,W
ADDWF D6,F
MOVF D5,W
//BTFSC STATUS,C
//INCFSZ D5,W
//ADDWF D7,F
ADDWFC D7,F
BCF STATUS,C
DVD16X16LP2:
RLCF D0,F
RLCF D1,F
DECFSZ D16,F
BRA DVD16X16LP
MOVF D0,W
end asm
end sub {DVD16X16}
-
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Re: makro parameter type
Thanks for that Janni.
If there's anything else you care to share we'll be doing an update soon to add the "const data at address" feature, so now's a good time.
If there's anything else you care to share we'll be doing an update soon to add the "const data at address" feature, so now's a good time.
Saving space is usually a good thing, but in this case it's quite a bit slower, and it's only a handful of bytes anyway. I'll look at switching it over to use MUL.It certainly saves space if one routine is used for different arguments but with PIC18 processors it seems unnecessary
Re: makro parameter type
That depends on how big changes are you willing to make . More seriously, as I doubted you'd be making any, I stopped mimicking present internal math routines so my library is not a simple replacement. To tell the truth, I got a bit carried away and, exploiting the possibilities of SF macros, I've added even more detailed routines, like 16x8 and 32x8 bit multiplication. And, besides diagnostic flags, an exception mechanism that forces program to jump to a predetermined place in case of error .Jerry Messina wrote: ↑Wed Sep 07, 2022 11:06 amIf there's anything else you care to share we'll be doing an update soon to add the "const data at address" feature, so now's a good time.
Anyway, I can share the whole library and help in adjusting what you find applicable if you agree at least to preserve the diagnostic option (as an option, i.e. activated with appropriate define). SF already uses internal variable in floating-point routines so I used the same byte for statuses (last three bits are prepared to accommodate my version of floating-point math lib and may be skipped).
Code: Select all
dim FM_stat as D24 // math statuses
const
_FM_IOV=0,
_FM_FOV=1,
_FM_FDZ=2,
_FM_NAN=3,
_FM_DOM=4,
_FM_FUN=5,
_FM_RND=6,
_FM_SAT=7
Note that to reduce code I have most of signed routines using the unsigned ones, like
Code: Select all
//-------------- Division, 8-bit unsigned
// Input: D0, D4 (D13)
// Output: D0, remainder in D8
// Uses: D12, D13
// D13 bits: 0 - result to be negated
// 2 - remainder to be negated (negative dividend)
// 7 - signed division
public sub Div_8x8_U()
asm-
CLRF D13 // unsigned
// entry for signed division
CLRF D8
MOVF D4,F // divisor is zero?
BNZ Div_8x8_UL1 // ...no
MOVF D0,F // dividend is zero, as well?
end asm
#ifdef FM_FLAGS
asm-
BTFSC STATUS,Z
BSF FM_stat,_FM_NAN// ...yes, set NAN flag
BZ $+6
BSF FM_stat,_FM_FDZ// ...no, set FDZ flag
BSF FM_stat,_FM_FOV
end asm
#endif
asm-
MOVLW 0x7F // set max value according
BTFSC D13,2 // to sign of dividend, if signed
MOVLW 0x80
BTFSS D13,7 // or to FF, if unsigned
MOVLW 0xFF
MOVWF D0
end asm
#ifdef FM_EXCEPTIONS
asm-
goto GoFMerror
end asm
#else
asm-
RETURN
end asm
#endif
asm-
Div_8x8_UL1:
MOVF D0,W // dividend is zero?
BTFSC STATUS,Z
RETLW 0
MOVLW 8 // actual division
MOVWF D12
RLCF D0,W
RLCF D8,F
MOVF D4,W
SUBWF D8,F
BC $+6
ADDWF D8,F
BCF STATUS,C
RLCF D0,F
DECFSZ D12,F
BRA $-18
BTFSS D13,7 // signed?
RETURN // ...no
BTFSC D13,2 // remainder supposed to be negative?
NEGF D8
BTFSS D13,0 // result supposed to be negative?
BRA $+6
NEGF D0
RETURN
BTFSS D0,7 // overflow (-128/-1)?
RETURN
DECF D0,F // ...yes, set max positive value
// (remainder is zero)
end asm
#ifdef FM_FLAGS
asm-
BSF FM_stat,_FM_IOV// ...set IOV flag
end asm
#endif
#ifdef FM_EXCEPTIONS
asm-
goto GoFMerror
end asm
#endif
end sub {Div_8x8_U}
//-------------- Division, 8-bit signed (short)
// Input: D0, D4
// Output: D0, remainder in D8
// Uses: D12, D13
// D13 bits: 0 - result to be negated
// 2 - remainder to be negated (negative dividend)
// 7 - signed division
public sub Div_8x8_S()
asm-
CLRF D13
BSF D13,7
BTFSS D0,7 // negative dividend?
BRA $+8
NEGF D0
INCF D13,F
BSF D13,2 // ...yes, remainder to be negated
BTFSS D4,7 // negative divisor?
BRA $+6
NEGF D4
INCF D13,F // if D13.0=1 then result to be negated
goto Div_8x8_U+2
end asm
BEGIN_SB_COMMENT_BLOCK() // force compiler to include Div_16x16_U
addressof(Div_8x8_U)
END_SB_COMMENT_BLOCK()
end sub {Div_8x8_S}
-
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Re: makro parameter type
check your PM