Could it be that the function __builtin_frac is not implemented although it is in the documentation (c.pdf)? I get an error "unknown identifier _builtin_frac used in function call" when trying to do something like
__builtin_frac was supposed to be a builtin keyword to C, but somehow it's missing from the C keywords table. I will fix that in the next release (it's fixed in github now). Thanks for catching this!
In the meantime you can work around this by defining a function like:
unsigned myfrac(unsigned a, unsigned b) {
unsigned r = 0;
__asm {
setq a
qdiv r, b
getqx r
}
return r;
}
which should usually expand to the same code as the builtin, at least on P2 (the builtin will also work in some other environments).
@"Christof Eb." said:
Hi,
is there something wrong with _cogstop() ? (version 7.4.1)
I had crashes with it, while
__asm {
cogstop tos
} ;
works.
_cogstop is defined with the same inline assembly, so it should generate the exact same code. Do you have an example where it doesn't? (You can always look at the .p2asm file, or the listing file id -l is given). Any details of the context or surrounding code?
Just playing around the other day, blinking an LED in its own cog. Cogstop didn't behave as expected, the LED started blinking erratically. This was FlexBasic.
@Mickster @"Christof Eb." Do either of you have any examples of these problems? cpustop works in the examples I've tried, so it's not obviously broken. Whatever problem you're having is somehow context dependent, and I don't have enough information to debug it.
#define TOS PR0
....
// scaling: ( cos*10000 -- degrees*10000 )
TOS= (int)(572957.795130823*acos((1.0*(int)TOS)/10000.0)); // works
// TOS= (int)(572957.795130823*acos((1.0*TOS)/10000.0)); // did only work for positive arguments
Why is this (int) before TOS needed?
I have for cogstop:
/*
PRIMI(cogstop) { // ( COGnr -- ) stop the cog -- does not work
_cogstop(TOS);
_drop();
}
*/
PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
__asm {
cogstop tos
} ;
_drop();
}
@"Christof Eb." To answer "why does this work but that not" questions like that, grab the .p2asm file the compiler generates for both versions and run them through a diff tool.
@Wuerfel_21 said:
@"Christof Eb." To answer "why does this work but that not" questions like that, grab the .p2asm file the compiler generates for both versions and run them through a diff tool.
Yes, I could dive into this question. At the moment I am busy doing other things. I do mostly not understand, how the compiler works or it's floating point library. It's a tool for me. So I would have to invest ???? time.
My question was on another level. I asked (myself), why this (int) does change anything, as TOS alias PR0 already is a signed int32. In my opinion up to now (allways learning ), this (int) should not be necessary.
Christof
@ersmith said:
@Mickster @"Christof Eb." Do either of you have any examples of these problems? cpustop works in the examples I've tried, so it's not obviously broken. Whatever problem you're having is somehow context dependent, and I don't have enough information to debug it.
Oh, naturally it started to work now
const _clkfreq = 280_000_000
sub for "cog" blink()
do
pintoggle(57)
pausems 200
loop
end sub
sub blinkstub()
blink()
end sub
dim mystack as byte(128)
var cogid = cpu(blinkstub(), @mystack(0))
print cogid
pausems(4000)
cpustop(cogid)
Incidentally, this is the example that you provided to demonstrate the need for the stub procedure.
Was this a temporary thing or a standard requirement?
@"Christof Eb." said:
Another riddle, perhaps related?
```
define TOS PR0
....
Why is this (int) before TOS needed?
Most hardware registers are considered to be unsigned integers. In order to treat them as signed you have to explicitly cast them. PR0 to PR7 aren't exactly hardware registers, but they're still treated as such.
I have for cogstop:
/*
PRIMI(cogstop) { // ( COGnr -- ) stop the cog -- does not work
_cogstop(TOS);
_drop();
}
*/
PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
__asm {
cogstop tos
} ;
_drop();
}
TOS and tos are different identifiers in C, so these codes will do different things.
@"Christof Eb." said:
Another riddle, perhaps related?
```
define TOS PR0
....
Why is this (int) before TOS needed?
Most hardware registers are considered to be unsigned integers. In order to treat them as signed you have to explicitly cast them. PR0 to PR7 aren't exactly hardware registers, but they're still treated as such.
Hm, it is most important for my Forth compiler, that PR0...PR7 are sitting in cog ram and I see each cell of this memory space as a "hardware register", as all of them can do maths like a traditional accumulator. This is the way I can share the same registers between assembler in a Spin2 file and C.
I have for cogstop:
/*
PRIMI(cogstop) { // ( COGnr -- ) stop the cog -- does not work
_cogstop(TOS);
_drop();
}
*/
PRIMI(cogstop) { // ( COGnr -- ) \ stop the cog
__asm {
cogstop tos
} ;
_drop();
}
TOS and tos are different identifiers in C, so these codes will do different things.
Oh, sorry, of course there is
....
// PR0–PR7 are in $1D8–$1DF
#define tos PR0
#define TOS PR0
....
So after preprocessing, the compiler should see the same thing.
Perhaps you could modify the text somehow to reflect that it is really
"extern register unsigned int"
Global Register variables
Global variables are normally placed in HUB memory, and local variables in COG memory (registers). The assembly backends permit variables to be declared as extern register, in which case they are placed in COG memory. Such variables cannot be initialized.
Comments
Could it be that the function
__builtin_frac
is not implemented although it is in the documentation (c.pdf)? I get an error "unknown identifier _builtin_frac used in function call" when trying to do something likeDo I need to #include something else additionally to "propeller2.h" to make it work?
__builtin_frac
was supposed to be a builtin keyword to C, but somehow it's missing from the C keywords table. I will fix that in the next release (it's fixed in github now). Thanks for catching this!In the meantime you can work around this by defining a function like:
which should usually expand to the same code as the builtin, at least on P2 (the builtin will also work in some other environments).
Hi,
is there something wrong with _cogstop() ? (version 7.4.1)
I had crashes with it, while
works.
Christof
_cogstop
is defined with the same inline assembly, so it should generate the exact same code. Do you have an example where it doesn't? (You can always look at the .p2asm file, or the listing file id-l
is given). Any details of the context or surrounding code?Just playing around the other day, blinking an LED in its own cog. Cogstop didn't behave as expected, the LED started blinking erratically. This was FlexBasic.
@Mickster @"Christof Eb." Do either of you have any examples of these problems? cpustop works in the examples I've tried, so it's not obviously broken. Whatever problem you're having is somehow context dependent, and I don't have enough information to debug it.
Another riddle, perhaps related?
Why is this (int) before TOS needed?
I have for cogstop:
@"Christof Eb." To answer "why does this work but that not" questions like that, grab the .p2asm file the compiler generates for both versions and run them through a diff tool.
Yes, I could dive into this question. At the moment I am busy doing other things. I do mostly not understand, how the compiler works or it's floating point library. It's a tool for me. So I would have to invest ???? time.
), this (int) should not be necessary.
My question was on another level. I asked (myself), why this (int) does change anything, as TOS alias PR0 already is a signed int32. In my opinion up to now (allways learning
Christof
Oh, naturally it started to work now
Incidentally, this is the example that you provided to demonstrate the need for the stub procedure.
Was this a temporary thing or a standard requirement?
Regards,
Craig
Most hardware registers are considered to be unsigned integers. In order to treat them as signed you have to explicitly cast them.
PR0
toPR7
aren't exactly hardware registers, but they're still treated as such.TOS
andtos
are different identifiers in C, so these codes will do different things.@Mickster The stub is no longer necessary on P2. It is still required on P1 (and will produce an error message in that case).
Sure enough...tested

Hm, it is most important for my Forth compiler, that PR0...PR7 are sitting in cog ram and I see each cell of this memory space as a "hardware register", as all of them can do maths like a traditional accumulator. This is the way I can share the same registers between assembler in a Spin2 file and C.
Oh, sorry, of course there is
So after preprocessing, the compiler should see the same thing.
I will try to provide full/real code later.
Perhaps you could modify the text somehow to reflect that it is really
"extern register unsigned int"
Global Register variables
Global variables are normally placed in HUB memory, and local variables in COG memory (registers). The assembly backends permit variables to be declared as extern register, in which case they are placed in COG memory. Such variables cannot be initialized.
extern register int *interpreter_pc;
int fetch() {
return *interpreter_pc++;
}
Variables that are explicitly defined as
extern register
will have whatever type they are declared as, e.g. inhas type
int *
(pointer to int).The builtin registers like
_OUTA
and_PR0
have typeunsigned int
. But they can be cast to any type you like.Ah, thank you for this explanation!