flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

16364656769

Comments

  • @ersmith Looks better, can compile. But, this kind of initialization doesn't seem to work right:
    The filename comes out wrong...
    typedef struct logoim
    {
        char name[20];
      ft_uint16_t image_height;
      ft_uint8_t image_format:5; 
      ft_uint8_t filter:1;
      ft_uint16_t sizex;
      ft_uint16_t sizey;
      ft_uint16_t linestride:10;
      ft_uint32_t gram_address;
      
    }t_imageprp;
    //<filename><imageheight><format><filter><sizex><sizey><stride><gramaddress>//
    #ifndef DISPLAY_RESOLUTION_WVGA
    t_imageprp sym_prp[6] = {
                              {"S1.BIN",136,RGB565,BILINEAR, 512, 512,480,0 * 1024},      // handle 0
                  	          {"S2.BIN", 77,    L8,BILINEAR,2*77,2*77, 77,65*1024},      // handle 1
                              {"S3.BIN", 28,    L8, NEAREST,3*50,3*28, 50,77*1024},      // handle 2
                              {"S4.BIN", 50,    L8, NEAREST,  50,  50, 50,80*1024},
                              {"S5.BIN", 77,    L8,BILINEAR,2*77,2*77, 77,83*1024},
                              {"S6.BIN", 77,    L8, NEAREST,  84,  77, 84,95*1024}
    			},
              target_prp[4] = {
                                {"T1.BIN", 68,    L8,BILINEAR, 136,136,68,64*1024},      // handle 0
                      	    {"T2.BIN", 55,    L4,BILINEAR, 120, 55,60,70*1024},      // handle 1
                                {"T3.BIN", 60,    L4,BILINEAR, 240,180,60,78*1024},      // handle 2
                                {"T4.BIN", 150,   L8,BILINEAR, 480,300,240,82*1024},
                              },
    
  • There's a new release (4.4.0) of fastspin available from https://github.com/totalspectrum/spin2cpp/releases. There are many improvements to the C parser, thanks in large part to @Rayman's helpful bug reports (Ray, I think all the issues you reported above are addressed now). There are also some Spin2 improvements (in SEND and RECV) and a few bug fixes to the BASIC compiler.
  • @ersmith Thanks! I appreciate the hard work!

    But now, I'm getting a compile error on the above with "too many initializers..."

    Here's the code in question.
    See build.bat for the compile command line.
  • Some good news! Was just now able to get 9DOF MEMS code from the ST library to compile and run!

    There's a ton of chips supported there and I have a feeling they would all work: https://github.com/STMicroelectronics/STMems_Standard_C_drivers

    For the P2 part, I used @JonnyMac 's I2C driver from OBEX. It's really great to be able to use Spin files directly in FlexC!
  • @Rayman : I see the problem with EVE2. Fastspin isn't handling initializing bitfields (like "filter :1") properly, because multiple entries have to be compressed down to one actual word in memory. For now you can work around it by removing the ":N" notation from the structure declaration.
  • Ok, I'll try that. Interestingly, I just got this ST MEMS code working and it also uses bitfields of a byte and seems to work fine...
  • Good news! Was able to get Logos example working. But, in addition to the bitfields issue, there some issue with mixing types...

    Everything looked good, except the last element in the structure, the uint32. It was getting initialized to bizarre, sometimes negative values...
    But, making them all uint32 made it work...
    //typedef struct logoim
    //{
    //    char name[20];
    //  ft_uint16_t image_height;
    //  ft_uint8_t image_format; 
    //  ft_uint8_t filter;
    //  ft_uint16_t sizex;
    //  ft_uint16_t sizey;
    //  ft_uint16_t linestride;
    //  ft_uint32_t gram_address;
    //}t_imageprp;
    
    typedef struct logoim
    {
        char name[20];
        ft_uint32_t image_height;
        ft_uint32_t image_format;
        ft_uint32_t filter;
        ft_uint32_t sizex;
        ft_uint32_t sizey;
        ft_uint32_t linestride;
        ft_uint32_t gram_address;
    }t_imageprp;
    
  • @ersmith I'm having a mixed-language issue when using fixed-point math in FlexBASIC.

    This code works fine using IEEE 754 floating point:
    	dim f as single
    	dim i as long
    	
    	f = 1.234567890
    	i = 42
    
    	print "Float test"
    	
    	printf("Float = %f, Int = %d", f , i )
    
    But if I add the "--FIXED" option on the compiler command line, the value of "f" will be printed as "0.00000". Otherwise the fixed-point math works fine and is about 9x faster than floating point.

    Apologies for the really ugly language mash-up, but how do I use C's printf() to display a 16.16 fixed-point value?
  • JRoarkJRoark Posts: 564
    edited 2020-10-09 - 22:59:31
    @ersmith An old bug is back. Very minor, but I'll stick it out here in case you want to stomp it. :)

    A FOR/NEXT loop without anything inside the loop throws an "unexpected next" error. This code wont compile:
    dim a as long
    for a = 1 to 10
       'nothing here
    next a
    

    But this code works fine:
    dim a as long
    for a = 1 to 10
        ASM
          nop
        END ASM
    next a
    

    I would agree that a FOR/NEXT loop without anything inside it is a fairly useless creature (unless it was being used as a pidgin-style delay maybe?), but the syntax is valid.

    FWIW, all of the other "empty loop" fixes that you implemented previously still work fine. Only FOR/NEXT is wonky.

  • Is calling a C function with no argument legal if the declaration has one? I don't think so. The following code compiles without error and outputs "arg=1669342516" which I guess is a random value on the stack.
    uint32_t WaitFall (uint32_t tmax)
    {
      printf ("arg=%d ", tmax);
      return -1;
    }
    
    void main()
    {
      ...
      uint32_t x = WaitFall ();
    
    IMHO the compiler should say something like "no matching function found for call WaitFall(void)".
  • ManAtWorkManAtWork Posts: 801
    edited 2020-10-10 - 13:08:18
      uint32_t bit=2;
      uint32_t mask= 0x7fffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    outputs "bit=2 mask=1" which is correct. However...
      bit=2;
      mask= 0xffffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    outputs "bit=2 mask=ffffffff" instead of "mask=3". The shift operation is optimized away because the whole expression is constant. I think the compiler uses ROR or SAR instead of SHR.
  • Shifting negative numbers is undefined.
    but, if declared as uint instead of int, maybe it should have worked?
  • ManAtWork wrote: »
    Is calling a C function with no argument legal if the declaration has one? I don't think so. ...
    IMHO the compiler should say something like "no matching function found for call WaitFall(void)".

    It's a good question. I think maybe C sometimes won't check? C++ has to due to overloading, I imagine...

    If you use Visual Studio to edit the C code, it will both show you what arguments are needed when you are typing and flag as error with red squiggly underline if wrong.

    724 x 230 - 19K
    435 x 112 - 7K
  • I took a stab at compiling MicroMax Chess this morning...
    Got a couple versions to compile and run, but they don't work quite right... Seems the black pawns are messed up...
    This is probably asking too much from FlexC at this stage.
    I could probably figure out what is wrong by comparing with PC version, but that'd take a long time, I think...

    Anyway, just wanted to point out two things that I had to change to make some of these compile...
    First, they seem to declare the types of the parameters to a function like this, which FlexC doesn't like:
    D(k,q,l,e,E,z,n)        
    int k,q,l,e,E,z,n;      
    {
    
    This is a strange way to do it anyway, I think the author was just trying to save characters in the file for some reason...

    The other thing was a goto label with the same name "C" as a local variable. That seems like bad style to me anyway, but they claim this is ANSI C...

    Anyway, these two seem like they almost, but not quite work.
  • ManAtWork wrote: »
      uint32_t bit=2;
      uint32_t mask= 0x7fffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    outputs "bit=2 mask=1" which is correct. However...
      bit=2;
      mask= 0xffffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    outputs "bit=2 mask=ffffffff" instead of "mask=3". The shift operation is optimized away because the whole expression is constant. I think the compiler uses ROR or SAR instead of SHR.

    @ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1. Shifting a -1 to the right will always result in a -1, or 0xffffffff. On a machine with a 64-bit int 0xffffffff will be a positive number, and shifting it 30 bits to the right results in a value of 3.

    If you want to force the value 0xffffffff to be unsigned you can put a "u" at the end, such as 0xffffffff. Or you could cast it to unsigned using (uint32_t)0xffffffff.
  • I got an error in this code that had two semi-colons in a row...
    Is this a real error?
    int Xoutput=0;;
    
  • ManAtWork,
    C's >> operator is defined as SAR with signed operands and SHR for unsigned operands. As Dave Hein said, you need to cast your 32bit constant operand to be unsigned to get what you want, or make it a 64bit constant.

  • RaymanRayman Posts: 11,372
    edited 2020-10-10 - 22:24:20
    This chess code gives me a compile error like this:
    error : Internal error : unknown type 2 passed to TypeSize
    

    Also, the code uses the include sys/timeb.h to get the seconds and milliseconds of time and then form milliseconds.
    We don't have that, so I did a bad hack.
    Is there a good way to do that?
    c
    c
  • Rayman,
    Two semicolons like that should not be an error.
  • Dave Hein wrote: »
    @ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1.

    Ok, but if I assign this constant to a variable declared of type uint32_t I assume that it will be a positive number with all bits set. If I shift that variable right by 30 bits I assume that the result is 3, no matter of the original type of the constant before the assignment. I know that the compiler optimizes the assignment and even the variable away and directly passes the result to the print. But no optimization should ever change the semantics of a program.

    So
      uint32_t bit=2;
      uint32_t mask= 0xffffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    should output "bit=2 mask=3" unless I miss something. I'm curious what Eric says about this.
  • The value is not assigned until after the shift. In other words, the value is signed until it is assigned to the unsigned variable.
  • If you look at that expression, the compiler sees 0xffffffff as type int. The literal value 32 is also type int. So it reduces down to int >> int
  • RaymanRayman Posts: 11,372
    edited 2020-10-11 - 17:21:11
    I guess the best practice would be to put a "u" at the end when we intend for a constant to be bitfield type of thing like this:
    [code] uint32_t mask= 0xffffffffu >> (32-bit);
    

    I was just reading that u can be upper or lower case... Should there be an "L" at the end too?
  • RaymanRayman Posts: 11,372
    edited 2020-10-11 - 18:07:04
    Seems I need the asin() function to convert a quaternion to roll, yaw, pitch...
    Sadly, seems to be missing from math.h...

    Unless I can figure out a trick to use what is there to get it, might have to import from some other math library...
    I found "cephes". License appears to be liberal, but not 100% clear...

    Actually, Wikipedia appears to show you can get asin from atan.
    375 x 83 - 7K
  • Rayman wrote: »
    Everything looked good, except the last element in the structure, the uint32. It was getting initialized to bizarre, sometimes negative values...
    Do you have an example of this? The tests I did seem to work OK, so it may be an environmental dependency.
    Rayman wrote: »
    I got an error in this code that had two semi-colons in a row...
    Is this a real error?
    int Xoutput=0;;
    

    Yes, actually, that is illegal in ISO C (you can check with gcc -Wall -Wpedantic). It's surprising, but there you go. Most compilers do accept it, but fastspin is using a C parser I got from the web that is fairly strict.
  • ManAtWork wrote: »
    Is calling a C function with no argument legal if the declaration has one? I don't think so. The following code compiles without error and outputs "arg=1669342516" which I guess is a random value on the stack.
    uint32_t WaitFall (uint32_t tmax)
    {
      printf ("arg=%d ", tmax);
      return -1;
    }
    
    void main()
    {
      ...
      uint32_t x = WaitFall ();
    
    IMHO the compiler should say something like "no matching function found for call WaitFall(void)".

    It's a bit tricky, because while it could be a compile time error if there are declarations for everything, it actually is a construct that's used sometimes, where the function gets declared in one file and used "wrongly" in another file. I've added a warning for it to the next version of fastspin.
  • ManAtWork wrote: »
    Dave Hein wrote: »
    @ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1.

    Ok, but if I assign this constant to a variable declared of type uint32_t I assume that it will be a positive number with all bits set.
    The assignment to the variable happens *after* all the calculations are performed, so the type is "int" during the shift. That is, the expression is parsed as:
      uint32_t mask = (0xffffffff >> (32-bit));
    
    and not as
      (uint32_t mask = 0xffffffff) >> (32-bit);
    

    I need to look carefully at the standard to see if plain "0xffffffff" on its own has to be considered unsigned, but I strongly suspect it's a compiler dependent feature. For portable code you should either cast it to unsigned or put a "u" at the end to make sure it's explicitly unsigned.
      uint32_t bit=2;
      uint32_t mask= 0xffffffff >> (32-bit);
      printf ("bit=%d mask=%x\n", bit, mask);
    
    should output "bit=2 mask=3" unless I miss something. I'm curious what Eric says about this.

  • @ersmith Forsee any way to start more cogs running FlexC?

    Or, can there be only one?

    How about interrupt handling? Is that possible?
  • ManAtWorkManAtWork Posts: 801
    edited 2020-10-12 - 08:10:14
    ersmith wrote: »
    The assignment to the variable happens *after* all the calculations are performed, so the type is "int" during the shift. That is, the expression is parsed as:
      uint32_t mask = (0xffffffff >> (32-bit));
    
    and not as
      (uint32_t mask = 0xffffffff) >> (32-bit);
    

    Ok, that makes sense and I finally get it. That's what I hate about C. Those implicit typecasts are very dangerous. An expression that looks perfectly correct at first sight could actually contain bugs that are very hard to spot. And in most cases there is no way the compiler can warn about it because many "tricks" are commonly used and fully legal in C.

    Thanks Eric, not your fault...

    I think this is one or the (rare) cases where inline assembler is actually better/clearer than C code.
    __asm{
      sub bit,#1
      bmask mask,bit
    }
    

  • JRoark wrote: »
    @ersmith I'm having a mixed-language issue when using fixed-point math in FlexBASIC.
    I've updated C's printf to handle fixed point. I've also added "." to the BASIC PRINT USING statement, so you can format the numbers directly in BASIC if you want (e.g. print using "##.####"; x)

    I also fixed the empty FOR loop problem you saw (thanks).

    There's a beta version of fastspin/flexgui up on my Patreon page with these fixes.
Sign In or Register to comment.