Shop OBEX P1 Docs P2 Docs Learn Events
Another Code Detonation in xBasic — Parallax Forums

Another Code Detonation in xBasic

JonnyMacJonnyMac Posts: 9,107
edited 2014-01-19 11:46 in Propeller 1
Many wonder why the Propeller didn't seem to take off with the same fervor of the BASIC Stamp -- I'm one of them. I wonder if it's not as simple as having the basics (pardon the word usage) that some many found so easy in PBASIC included in the Spin language. For example, the BASIC Stamp "Hello, World!" was:
Main:
  HIGH 0
  PAUSE 500
  LOW 0
  PAUSE 500
  GOTO Main


... or some variation, thereof. This was easy, and it stuck. Even "artists" could understand it.

I created methods in my base Spin template for pause, high, low, toggle, and input -- and now I'm doing the same for xBasic but attempting to use native instructions where I can to speed things up; we're already at a slight [speed] disadvantage by using a virtual machine.

As I cannot use "input" as a function name I call that function read_pin. That being the case I decided to make a complimentary function called write_pin. The PASM code compiles fine -- here's the conversion to a function.
def write_pin(pin, state)
  asm
    lref 0                // pin --> tos
    native 0xa0fc0801     // mov t4, #1
    native 0x2cbc0805     // shl t4, tos
    lref 1                // state --> tos
    native 0x61fc0a01     // and tos, #1 wc
    native 0x68b3e804     // if_c  or outa, t4
    native 0x648fe804     // if_nc andn outa, t4
    native 0x68bfec04     // or dira, t4
    returnx
  end asm
end def


The project using it will build fine, but then I get the following message in the debug terminal.
ILLEGAL OPCODE: STACK 00007BD8, STACK_TOP 00007FD8
PC       OP FP       SP       TOS      SP[0]    SP[1]    SP[2]    SP[3]
000001A6 27 00007FC4 00007FC0 00000199 00000000 000001F9 00007FD8 00000000

Comments

  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-01-18 13:29
    Well, of course, 30 seconds after submitting the above post I solved it -- with a bit of a guess (added drop before lref 1). Looking forward to more information on native coding like this in xBasic.
    def write_pin(pin, state)
      asm
        lref 0                // pin --> tos
        native 0xa0fc0801     // mov t4, #1
        native 0x2cbc0805     // shl t4, tos
        drop
        lref 1                // state --> tos
        native 0x61fc0a01     // and tos, #1 wc
        native 0x68b3e804     // if_c  or outa, t4
        native 0x648fe804     // if_nc andn outa, t4
        native 0x68bfec04     // or dira, t4
        returnx
      end asm
    end def
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 13:56
    I really *NEED* to do something about those hex constants that are required after the NATIVE keyword!

    Did you use pasm.exe to create those constants?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-01-18 15:02
    David Betz wrote: »
    I really *NEED* to do something about those hex constants that are required after the NATIVE keyword!

    Did you use pasm.exe to create those constants?

    Yes. Then I copied-and-pasted the hex values into my code. The process is a little tedious, but these bits of code are the exception, not the rule, so it's not a big problem.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 15:17
    JonnyMac wrote: »
    Yes. Then I copied-and-pasted the hex values into my code. The process is a little tedious, but these bits of code are the exception, not the rule, so it's not a big problem.
    It may not be a big problem but it should be pretty easy to fix. After all, I wrote both programs, the xbasic compiler and pasm.exe. :-)
  • jmgjmg Posts: 15,173
    edited 2014-01-18 15:19
    David Betz wrote: »
    I really *NEED* to do something about those hex constants that are required after the NATIVE keyword!

    Certainly support for in-line ASM would be nice, but an interim solution could be as you suggested to extend the NATIVE keyword to allow multiple lines, and remove most of the NATIVE overhead.

    I think that way the size and speed of HEX-asm would be very close to eventual in-line ASM ?
    David Betz wrote:
    It may not be a big problem but it should be pretty easy to fix. After all, I wrote both programs, the xbasic compiler and pasm.exe. :-)

    Sounds like it may be easier than I imagined :)
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 15:24
    jmg wrote: »
    Certainly support for in-line ASM would be nice, but an interim solution could be as you suggested to extend the NATIVE keyword to allow multiple lines, and remove most of the NATIVE overhead.

    I think that way the size and speed of HEX-asm would be very close to eventual in-line ASM ?
    By the way, I can't really do inline assembly for the same reason that Spin can't. xbasic code is compiled to bytecodes and it is a bytecode interpreter that runs it. There is no way to support inline assembly other than short snippets like the NATIVE instruction. The number of instructions could be increased but there isn't any way to allow arbitrary amounts of inline assembly. That will probably be possible in Spin2 though.
  • jmgjmg Posts: 15,173
    edited 2014-01-18 18:27
    David Betz wrote: »
    By the way, I can't really do inline assembly for the same reason that Spin can't. xbasic code is compiled to bytecodes and it is a bytecode interpreter that runs it. There is no way to support inline assembly other than short snippets like the NATIVE instruction. The number of instructions could be increased but there isn't any way to allow arbitrary amounts of inline assembly. That will probably be possible in Spin2 though.

    How large a piece of code are we talking about being the limit here ?
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 18:45
    jmg wrote: »
    How large a piece of code are we talking about being the limit here ?
    I figure 8-16 instructions. However, my first goal is to be able to do symbolic assembly of a single instruction so you don't have to use hex constants.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 18:55
    Is this an improvement?
    def write_pin(pin, state)
      asm
        lref 0  // pin --> tos
        native       mov  t4, #1
        native       shl  t4, tos
        lref 1  // state --> tos
        native       and  tos, #1 wc
        native if_c  or   outa, t4
        native if_nc andn outa, t4
        native       or   dira, t4
        returnx
      end asm
    end def
    
  • jmgjmg Posts: 15,173
    edited 2014-01-18 19:09
    David Betz wrote: »
    Is this an improvement?

    Do you really need to ask ? ;)
    I guess the hex syntax still works too ?
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 19:12
    jmg wrote: »
    Do you really need to ask ? ;)
    I guess the hex syntax still works too ?
    It's supposed to. I haven't checked this in yet because I haven't tested it very well. Maybe I can use it to figure out the other problem that JonnyMac reported about waitpeq.
  • jmgjmg Posts: 15,173
    edited 2014-01-18 19:19
    Does the asm..end asm support equates and conditional assembly ?
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-18 19:23
    jmg wrote: »
    Does the asm..end asm support equates and conditional assembly ?
    No. It's an extremely simple assembler only intended to write short sequences of instructions to implement low-level functions that are hard or impossible to implement in xbasic.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-19 06:26
    JonnyMac wrote: »
    Well, of course, 30 seconds after submitting the above post I solved it -- with a bit of a guess (added drop before lref 1). Looking forward to more information on native coding like this in xBasic.
    def write_pin(pin, state)
      asm
        lref 0                // pin --> tos
        native 0xa0fc0801     // mov t4, #1
        native 0x2cbc0805     // shl t4, tos
        drop
        lref 1                // state --> tos
        native 0x61fc0a01     // and tos, #1 wc
        native 0x68b3e804     // if_c  or outa, t4
        native 0x648fe804     // if_nc andn outa, t4
        native 0x68bfec04     // or dira, t4
        returnx
      end asm
    end def
    
    I know you've gotten far beyond this by now but this version of your code seems to work fine in my development version of xbasic. Notice that you can now use t1 without any problems. The t1-t4 registers are now for the exclusive use of NATIVE instructions. The VM opcode handlers use r1-r3 instead. Also, both the C and the Z flags are preserved between NATIVE instructions so you can count on them being as they were at the end of the previous NATIVE instruction.

    I'll check these changes in as soon as we resolve a minor loader issue.
    include "propeller.bas"
    
    def HIGH = 1
    def LOW = 0
    
    def LED = 0
    
    def write_pin(pin, state)
      asm
        lref 0  // pin --> tos
        native          mov     t1, #1
        native          shl     t1, tos
        drop
        lref 1  // state --> tos
        native          and     tos, #1 wc
        native    if_c  or      outa, t1
        native    if_nc andn    outa, t1
        native          or      dira, t1
        returnx
      end asm
    end def
    
    def pause(ms)
        waitcnt(cnt + ms * (clkfreq / 1000))
    end def
    
    main:
      write_pin(LED, HIGH)
      pause(500)
      write_pin(LED, LOW)
      pause(500)
      goto main
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-19 09:44
    David Betz wrote: »
    I know you've gotten far beyond this by now but this version of your code seems to work fine in my development version of xbasic. Notice that you can now use t1 without any problems. The t1-t4 registers are now for the exclusive use of NATIVE instructions. The VM opcode handlers use r1-r3 instead. Also, both the C and the Z flags are preserved between NATIVE instructions so you can count on them being as they were at the end of the previous NATIVE instruction.

    I'll check these changes in as soon as we resolve a minor loader issue.

    Steve fixed the "minor loader problem" so the PASM assembler and improvements to the NATIVE instruction are checked into Google Code. They should appear whenever Steve does another release of his IDE.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-01-19 10:07
    That is to say that now NATIVE allows the inclusion of PASM syntax -- without external assembling? And the preservation of C and Z flags is really useful.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-01-19 10:15
    JonnyMac wrote: »
    That is to say that now NATIVE allows the inclusion of PASM syntax -- without external assembling? And the preservation of C and Z flags is really useful.
    Yes, you can use PASM syntax after the NATIVE keyword. All I did was to merge my simple PASM assembler into xbasic to assemble one line at a time. And, as you say, C and Z are preserved between NATIVE instructions.
  • jazzedjazzed Posts: 11,803
    edited 2014-01-19 11:46
    David Betz wrote: »
    Yes, you can use PASM syntax after the NATIVE keyword. All I did was to merge my simple PASM assembler into xbasic to assemble one line at a time. And, as you say, C and Z are preserved between NATIVE instructions.
    Attached is an updated compiler. Unzip and copy xbcom-qt.exe to C:\Program Files (x86)\xBasic IDE\bin
Sign In or Register to comment.