Gotcha using SUBI to increment a 16-bit value

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My aim was to increment a word length value in R17:R16 by a constant amount like this:

        subi    R16,-0x40
        clr     a
        adc     R17,a

fails if, for example, R17:R16 holds 0x0140. I get 0x0280. How come R17 goes from 0x01 to 0x02? Turns out that the subi instruction sets the carry despite the minuend equalling the subtrahend and contrary to the Instruction Set manual (p153). What am I missing? Obviously easy to fix, but since there is no adi instruction, why not have subi work as expected?

Last Edited: Mon. Feb 12, 2018 - 09:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a macro that goes like this:

;Add immediate to register pair.
;
.MACRO 	ADDI_W 		;Arguments:  Register pair,   Data (ie zl,zh,1234)
	subi	@0, low (-@2)	;Add low byte ( x -(-y)) = x + y
	sbci	@1, high (-@2)	;Add high byte with carry
.ENDMACRO

 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jbug11 wrote:
What am I missing?

The app note on AVR arithmetic?

 

Why does your thread title say 32-bit, but your example is 16 bit?

 

If I were doing an ASM fragment I think I'd try to use an appropriate register pair and ADIW.

 

Why didn't they do it your way 30 years ago?  Dunno, but the action of SUBI has been well documented since then.

 

How do the compilers do it?

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I were doing an ASM fragment I think I'd try to use an appropriate register pair and ADIW.

surprise 

7. ADIW – Add Immediate to Word
7.1. Description
Adds an immediate value (0 - 63) to a register pair and places the result in the register pair.
 

...I would blame it on ol' age too....wink

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course your macro gives the right result, and so does adiw (for addendums <= 63) - I was just bemused by what I found.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

32 corrected to 16 in title

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jbug11 wrote:
Turns out that the subi instruction sets the carry despite the minuend equalling the subtrahend and contrary to the Instruction Set manual (p153).

Let's explore the premise for a bit.

 

Instruction set manual:

C:
Rd7• K7 +K7 •R7 +R7• Rd7
Set if the absolute value of K is larger than the absolute value of Rd; cleared otherwise.

 

So in your example

jbug11 wrote:
for example, R17:R16 holds 0x0140.
jbug11 wrote:
subi R16,-0x40

Rd is 0x40, and k is -0x40 or (+) 0xc0.  k is larger than Rd.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great. You are right. It was my reading of the wording 'absolute value'. In my (oversimplified) world |-5| = +5. I was forgetting the cleverness involved in two's complement arithmetic.