STM8 assembly - some kind of arithmetic op to set carry if two values equal? - Page 1
Forum section: electronics / general

author: HwAoRrDk
author_rank: Super Contributor
timestamp: June 16, 2021, 08:22:18 pm
content: InSTM8 assembly language, is there some kind of arithmetic operation I can do that will have the effect of setting the carry flag if two values are equal, and clear the carry if they are not?I know there is theCP dst, srcinstruction, but that only sets carry ifsrcislargerthandst. I'm wondering if there is some kind of arithmetic trickery that can be done with possibly other instructions that modify carry, such asADD,SUB,DIV, etc.What I'm trying to do is generate a sequence of instructions, without branching, to set/clear several I/O port pins, but the state each is set to depends on whether an argument passed into the function matches its position. I thought theBCCMinstruction might be useful here, if I can only get the carry set appropriately...Code:LD A, (3, sp) ; load func arg to A reg; here, set carry = (A == 0)BCCM 0x5000, #3; here, set carry = (A == 1)BCCM 0x5005, #0; here, set carry = (A == 2)BCCM 0x5000, #6; here, set carry = (A == 3)BCCM 0x500F, #2; etc...

author: rhodges
author_rank: Frequent Contributor
timestamp: June 16, 2021, 09:42:12 pm
content: Something like this?Code:LD A, (3, sp) ; load func arg to A regsub a, #1 ; here, set carry = (A == 0)BCCM 0x5000, #3sub a, #1 ; here, set carry = (A == 1)BCCM 0x5005, #0sub a, #1 ; here, set carry = (A == 2)BCCM 0x5000, #6

author: HwAoRrDk
author_rank: Super Contributor
timestamp: June 16, 2021, 11:13:53 pm
content: Yes! That does the trick.If I'm understanding correctly, by decrementing the position argument itself at each step, the subtraction will have a negative result (i.e. underflow) and the carry bit set when needed. At the subsequent step, it will go back to no carry, as it's just decrementing from 255. I suppose this means I can't have more than 255 steps - as it would underflow twice - but I don't need to.I must be having a bit of brain drain today to not be able to think it would be that simple.Thanks very much.

author: ucanel
author_rank: Regular Contributor
timestamp: June 17, 2021, 12:10:29 am
content: Sorry for the interruption but after i saw this topic i think it would be efficent to do it with jump table and i do not know stm8 assembly so i searched for it for more than a hour but could not got it. So i wonder it nowMy question how is Program Counter manipulation done in Stm8 assembly?I was doing it for PIC mcus like this:Code:MOV 0x04,W ; load xxx to accumulator (W)ADDWF PCL,F ; PC = PC + Accumulator [add accumulator (W) to the Program counter and store it to the File ( Program Counter) ]

author: chickenHeadKnob
author_rank: Super Contributor
timestamp: June 17, 2021, 12:31:06 am
content: In general when I want to do some Boolean operation on an 8 bit micro and it is not directly supported in the instruction set and I want to avoid branching, I resort to 256 byte lookup tables. Input conditions form the index into the table. Might need 2 tables if'n you need to do something more complicated than set/clear.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: June 17, 2021, 12:34:07 am
content: Quote from: ucanel on June 17, 2021, 12:10:29 amI don't believe you can manipulate the program counter directly on STM8. You can only do so with jump, call, return, etc. instructions (e.g.JRA 0x20- adds 0x20 to PC).

author: HwAoRrDk
author_rank: Super Contributor
timestamp: June 17, 2021, 12:41:28 am
content: Quote from: chickenHeadKnob on June 17, 2021, 12:31:06 amI can't afford the memory for a lookup table.What I'm actually doing is writing some STM8 C code that will, at run-time, generate some functions in raw assembly and shove them in RAM, then they can be called when necessary. It's because I want to have code that uses atomic BSET/BRES (and BCCM now I have a solution for that) instructions to manipulate port I/O, but the trouble with those is that they only accept hard-coded register addresses (i.e. set at compile-time) and not, for example, indirect pointers in X/Y registers. That would normally preclude me from having code where I/O registers are configured dynamically, but this way gets around that.

author: ucanel
author_rank: Regular Contributor
timestamp: June 17, 2021, 12:52:36 am
content: ...QuoteI thought a way but that is not good there must be an elegant way.We have our function named PCMANIPULATORGet it's address,add whatever offset value desired,push this PCMANIPULATOR address + offset to the stackissue a RETURN instruction.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: June 17, 2021, 07:16:37 am
content: Quote from: HwAoRrDk on June 17, 2021, 12:41:28 amBut your generator code consumes flash anyway. You can just generate a singleBSET 0, #0 ; RETin RAM at startup and have a function (in flash) with a switch or LUT that will set correct addr, bit and SET/RES op on the fly and call the RAM snippet each time you were going to call your original RAM code. This way you’ll save even more RAM for no additional cost (the flash code size should be comparable to your generator’s).

author: westfw
author_rank: Super Contributor
timestamp: June 18, 2021, 02:53:00 am
content: Quote"Compare" is almost always implemented as a "subtract, but don't save the result", which will usually not affect a carry flag in the way that you want. Rhodge's solution or similar will work for the specific case you're looking at...