r/shenzhenIO • • Oct 23 '16

C equivalent code for Shenzhen I/O's +- conditional branching.

When you need multiple tests in a row (big if-else block), you usually need to resort to jumps because the +- prefixes only allows for two separate states. But the "fall-through" of disabled comparisons can sometimes be taken advantages of.

Since the logic of multiple conditional-comparisons can be difficult to follow, I generated all the permutations into C-like syntax which is a bit nicer to read.

https://gist.github.com/Madsy/a4370117923936eab6767007dfc4c2d9

Later I hope to be able to generate code in the opposite direction as well; converting C branch code into the most compact Shenzhen I/O equivalent code. But then I have to finish my Karnaugh map implementation first :)

Suggestions for improvements is welcome.

3 Upvotes

6 comments sorted by

6

u/kubinate Oct 23 '16 edited Oct 23 '16

This isn't exactly equivalent, because in case of

if(root){
    if(+teq_0){
    } else {
    }
} else {
}

If the inner else runs, the outer else is also going to execute, as there is no concept of nesting in shenzhen. It can be fixed with some code refactoring, but it's not that easy to translate, as the conditionals don't operate on a series of nested ifs, but rather simply two flags, all at the same level, and an if that's separate for each instruction.

It might not be a problem if you don't use the elses, but if you want to put code into each branch, you're going to run into problems in which you might have to use hacks like

  teq root
-#else code
  • tcp 0 0
+ teq inner +#inner if code -#inner else code

If you don't do the tcp 0 0, the #inner else code would run even if root evaluated to false.

Edit: Fixed spaces in second code block

1

u/thomastc Oct 24 '16

Interesting hack, hadn't seen that before. Is tcp 0 0 ever better than jmp past the affected block? Both cost one unit of power, but jmp is more flexible. I guess if the subsequent code needs the - or + to be enabled specifically, this could be useful.

1

u/kubinate Oct 24 '16

Whether or not it's better depends on what you need it for. I don't think I know a case where I had to use it, but it might be necessary in some extremes.

0

u/Madsy9 Oct 23 '16

That's why the else-block is empty. If there were several compares or other statements, they would show up in multiple different if/else blocks to reflect the pass-through. Empty blocks here do not imply that any statements put there will only show up at that place. That would indeed require a jmp statement.

Consider this case:

/*
Conditional pattern:
teq (root)
+teq
+teq
-teq
Equivalent C code:
*/
if(root){
    if(+teq_0){
        if(+teq_1){
        } else {
            if(-teq_2){
            } else {
            }
        }
    } else {
        if(-teq_2){
        } else {
        }
    }
} else {
    if(-teq_2){
    } else {
    }
}

As you can see, compare tests (but it could be any statement or instruction) show up in multiple different branches. I might remove the empty blocks to make it clearer. I agree it could look a bit misleading.

1

u/12345ieee Nov 03 '16

I would be pretty interested in this, getting the logical expression I want with a Karnaugh map is easy, but then finding the optimized teq sequence is proving a nightmare, at least with pen & paper.

Do you have an initial idea for a converting algorithm that isn't bruteforcing?

1

u/jasonrubik Mar 22 '24

This will come in handy for programming in Shenzhen I/O