Shop OBEX P1 Docs P2 Docs Learn Events
beginer : switch/case in asm — Parallax Forums

beginer : switch/case in asm

Hello,

I return to the asm after more than 20 years without. It's a bit rough. I have just asked for some help here because I have not found my answer in the forum or on Google. I try to make a mini interpreter of a small bytecode that I defined. Even if the question is probably classic, I wonder how to make the equivalent of a switch / case in asm specifically to interpret the byte of each bytecode, one after the other. Basically each byte corresponds to a bit of code asm to execute. There are surely x ways to do, but I obviously seek the fastest:
1 / I excluded the cmp and call / jmp to the chain, far too long
2 / I imagined running by dichotomy to accelerate, but it still seems too slow
3 / can it be possible to make a table with the addresses of the bits of code, and use the byte of the bytecode to treat as index of this table?
4 / I imagine that one could use the byte, multiply it by a value (related to the size of each block of instructions) and make the jump according to the result. On the other hand it imposes that all the blocks make the same size, quite to lose space ...

Well, I imagine there are more intelligent methods, but I can not find? And Google did not really help me on this one ...

THANK YOU

Ps: I'm French, so excuse my English ...

Comments

  • Are you aware of the jump table option?

    If your byte codes were all sequential, you could use a jump table as a sort of switch/case structure.
    clearCommand            wrlong  ZERO, par ' used to indicate command complete
    
                            
    smallLoop              rdlong  commandCog, par 
    
                            add     commandCog, #jumpTable
                           
                            jmp     commandCog ' this jump will branch the code to the appropiate section
    jumpTable               jmp     #smallLoop
                            
                            jmp     #shiftOne
                            jmp     #writeBuff_
                            jmp     #writeCommand
                            jmp     #addressedRead
                            jmp     #setDelay
                        
    
     ' Below are the commands the used to control the jump table.                   
     '#0, IDLE_SPI_0, OLED_WRITE_ONE_SPI_1, OLED_WRITE_BUFFER_SPI_2, WRITE_I2C_3, READ_I2C_4, CHANGE_DELAY_COMMAND_5
    

    The example above is from my current project but there are lots of other examples including examples from code in the Propeller Tool's library.

    If your byte codes aren't sequential, then I doubt this technique will be useful to you.

  • tonyp12tonyp12 Posts: 1,951
    edited 2017-04-02 17:58
    A jump table.

    But if you have up to 256 rejumps that would waste valuable 256 cog longs.
    Store a lookup table of 4 addresses in a one cog long. (can only jump to half of a cogs ram, unless you shift it up one bit and start all snippets with a nop in case it's in a odd address type thing)
    Decode the lower two bits of bytecode to mask out the address so it can be shifted and moved to a single location for jump address.
    self-modify a jmp #0-0 could also work but would need a instruction in between and maybe you could not come up with a useful one.

    And if you have 256 bytecode options how do you fit all those 256 code snippets in cog ram?
    So I guess you don't have that many bytecode headers?
  • Thank you both !
    I understood your proposals, I will think about them. It seems simple to me.

    For information, I have about 50 opcodes (including a dozen optional) I will see if it is possible as I go, I just start ...

    By cons I do not understand the "self-modify a jmp # 0-0 could also work"?
  • tonyp12tonyp12 Posts: 1,951
    edited 2017-04-02 20:34
    Could store three of 9bit address in a long and also gives you full access to all cogram and no need to mask out just the 8bit before movd
    If you for example:

    tst bytecode, #%11 wz wc
    ifnz shr snippet, #9 ' you have to lookup z c status as this is probably not correct
    ifc shr snippet, #9 ' shift it another 9bits
    movd lablej, snippet
    nop
    labelj jmp #0-0

    the jump can not be modified just before next instruction due to pipleline,
    sure you put a nop in between, but if you can find a instruction you need anyway I would do that.

    if you instead create a long to store address, a nop is not needed.
    mov snippetaddrs, snippet
    labelj jmp snippetaddrs



  • kwinnkwinn Posts: 8,697
    The simplest would be to make all your code to perform the commands start at an even address and make each byte code equal to one half of that address. That way you decode the command by placing it in a register, shifting it left one bit, and jumping to the resulting address.
  • jmgjmg Posts: 15,173
    henrib75 wrote: »
    For information, I have about 50 opcodes (including a dozen optional) I will see if it is possible as I go, I just start ...
    kwinn wrote: »
    The simplest would be to make all your code to perform the commands start at an even address and make each byte code equal to one half of that address. That way you decode the command by placing it in a register, shifting it left one bit, and jumping to the resulting address.

    Seems that would work well, with the 50 opcodes, you would end up with a sparse bytecode map, and could auto-generate the bytecodes from a source or listing file, so as to track any code changes/fixes.



  • kwinnkwinn Posts: 8,697
    If the byte codes need to be specific values ( for instance specific letters of the alphabet, A-Z & a-z). Subtracting dec 65 from the command would make it a value between 0 and 64 which could then be used to look up an address stored in cog as four eight bit values per long. This would require 16 longs. There are six characters between "Z" and "a" which could probably be ignored.
  • henrib75henrib75 Posts: 9
    edited 2017-04-03 13:18
    Thank you all! I have a lot of good ideas there.
    kwinn wrote: »
    The simplest would be to make all your code to perform the commands start at an even address and make each byte code equal to one half of that address. That way you decode the command by placing it in a register, shifting it left one bit, and jumping to the resulting address.
    Yes it's simple and smart! On the other hand it imposes lengths of asm codes for each opcodes ... and especially it seems to me complicated to modify if I want to optimize or to add opcodes (after writing programs) ? But this is probably the fastest solution ...

    I think now I have to write the asm code for each bytecode and depending on the result I can choose the right solution.

    I will give you news in the coming weeks ...
  • kwinnkwinn Posts: 8,697
    henrib75 wrote: »
    ......
    ...

    I think now I have to write the asm code for each bytecode and depending on the result I can choose the right solution.

    I will give you news in the coming weeks ...

    Probably the best way to approach it. Once you have the asm code for executing the commands you know how much memory is left and a clearer idea of what approach works best.
Sign In or Register to comment.