Jump to content

Photo

Is >= More Efficient Than > When Using batari Basic?


7 replies to this topic

#1 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 28,179 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Fri Dec 18, 2015 8:04 AM

I've been using SpiceWare's tip below while updating the Seaweed Assault code, but I just remembered what he posted at the bottom, that it might work differently with bB. I thought I should ask to make sure that nothing is different when using the tip with batari Basic. If it's also more efficient when using bB, I should mention it on the bB page.
 

Using >= in assembly should be more efficient than >.

 
A >= check only needs to worry about the state of C.
 

test:
  cmp #70
  bcc Skip ;C is set if Greater Than or Equal To 70
  ; >= 70 logic here
Skip:
 
While a > check needs to worry about C and Z.
 
test:
  cmp #69
  bcc Skip ; C is clear if Less Than 69
  beq Skip ; Z is set if Equal To 69
  ; > 69 logic here

Skip:
 
It's possible bB is written in a way that makes > more efficient than >=.

 



#2 GroovyBee OFFLINE  

GroovyBee

    Games Developer

  • 9,736 posts
  • Busy bee!
  • Location:North, England

Posted Fri Dec 18, 2015 8:30 AM

How about providing the output assembler listing of if statements with all 4 scenarios ">", "<",">=" and "<=" so we can check?



#3 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • Topic Starter
  • 28,179 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Fri Dec 18, 2015 8:46 AM

How about providing the output assembler listing of if statements with all 4 scenarios ">", "<",">=" and "<=" so we can check?


Good idea. Is this all you need or do you need the whole list file?
 

__Main_Loop


   a = a + 1

   if a = 10 then b = 42

   if a > 10 then b = 42

   if a >= 10 then b = 42

   if a < 10 then b = 42

   if a <= 10 then b = 42


   goto __Main_Loop

 

   1625  f45d				   .__Main_Loop
   1626  f45d							; __Main_Loop
   1627  f45d
   1628  f45d				   .
   1629  f45d							;
   1630  f45d
   1631  f45d				   .
   1632  f45d							;
   1633  f45d
   1634  f45d				   .L00 		;  a  =  a  +	1
   1635  f45d
   1636  f45d		       e6 d6		      INC	a
   1637  f45f				   .
   1638  f45f							;
   1639  f45f
   1640  f45f				   .L01 		;  if a  =  10 then b	=  42
   1641  f45f
   1642  f45f		       a5 d6		      LDA	a
   1643  f461		       c9 0a		      CMP	#10
   1644  f463		       d0 04		      BNE	.skipL01
   1645  f465				   .condpart0
   1646  f465		       a9 2a		      LDA	#42
   1647  f467		       85 d7		      STA	b
   1648  f469				   .skipL01
   1649  f469				   .
   1650  f469							;
   1651  f469
   1652  f469				   .L02 		;  if a  >  10 then b	=  42
   1653  f469
   1654  f469		       a9 0a		      LDA	#10
   1655  f46b		       c5 d6		      CMP	a
   1656  f46d		       b0 04		      BCS	.skipL02
   1657  f46f				   .condpart1
   1658  f46f		       a9 2a		      LDA	#42
   1659  f471		       85 d7		      STA	b
   1660  f473				   .skipL02
   1661  f473				   .
   1662  f473							;
   1663  f473
   1664  f473				   .L03 		;  if a  >=  10 then b  =  42
   1665  f473
   1666  f473		       a5 d6		      LDA	a
   1667  f475		       c9 0a		      CMP	#10
   1668  f477		       90 04		      BCC	.skipL03
   1669  f479				   .condpart2
   1670  f479		       a9 2a		      LDA	#42
   1671  f47b		       85 d7		      STA	b
   1672  f47d				   .skipL03
   1673  f47d				   .
   1674  f47d							;
   1675  f47d
   1676  f47d				   .L04 		;  if a  <  10 then b	=  42
   1677  f47d
   1678  f47d		       a5 d6		      LDA	a
   1679  f47f		       c9 0a		      CMP	#10
   1680  f481		       b0 04		      BCS	.skipL04
   1681  f483				   .condpart3
   1682  f483		       a9 2a		      LDA	#42
   1683  f485		       85 d7		      STA	b
   1684  f487				   .skipL04
   1685  f487				   .
   1686  f487							;
   1687  f487
   1688  f487				   .L05 		;  if a  <=  10 then b  =  42
   1689  f487
   1690  f487		       a9 0a		      LDA	#10
   1691  f489		       c5 d6		      CMP	a
   1692  f48b		       90 04		      BCC	.skipL05
   1693  f48d				   .condpart4
   1694  f48d		       a9 2a		      LDA	#42
   1695  f48f		       85 d7		      STA	b
   1696  f491				   .skipL05
   1697  f491				   .
   1698  f491							;
   1699  f491
   1700  f491				   .
   1701  f491							;
   1702  f491
   1703  f491				   .L06 		;  goto __Main_Loop
   1704  f491		       4c 5d f4 	      jmp	.__Main_Loop
   1705  f494					      if	ECHOFIRST
      2824 bytes of ROM space left

 

 

Here it is with a variable replacing the number:

 

__Main_Loop


   a = a + 1

   if a = c then b = 42

   if a > c then b = 42

   if a >= c then b = 42

   if a < c then b = 42

   if a <= c then b = 42


   goto __Main_Loop

 

   1625  f45d				   .__Main_Loop
   1626  f45d							; __Main_Loop
   1627  f45d
   1628  f45d				   .
   1629  f45d							;
   1630  f45d
   1631  f45d				   .
   1632  f45d							;
   1633  f45d
   1634  f45d				   .L00 		;  a  =  a  +	1
   1635  f45d
   1636  f45d		       e6 d6		      INC	a
   1637  f45f				   .
   1638  f45f							;
   1639  f45f
   1640  f45f				   .L01 		;  if a  =  c then b  =  42
   1641  f45f
   1642  f45f		       a5 d6		      LDA	a
   1643  f461		       c5 d8		      CMP	c
   1644  f463		       d0 04		      BNE	.skipL01
   1645  f465				   .condpart0
   1646  f465		       a9 2a		      LDA	#42
   1647  f467		       85 d7		      STA	b
   1648  f469				   .skipL01
   1649  f469				   .
   1650  f469							;
   1651  f469
   1652  f469				   .L02 		;  if a  >  c then b  =  42
   1653  f469
   1654  f469		       a5 d8		      LDA	c
   1655  f46b		       c5 d6		      CMP	a
   1656  f46d		       b0 04		      BCS	.skipL02
   1657  f46f				   .condpart1
   1658  f46f		       a9 2a		      LDA	#42
   1659  f471		       85 d7		      STA	b
   1660  f473				   .skipL02
   1661  f473				   .
   1662  f473							;
   1663  f473
   1664  f473				   .L03 		;  if a  >=  c then b	=  42
   1665  f473
   1666  f473		       a5 d6		      LDA	a
   1667  f475		       c5 d8		      CMP	c
   1668  f477		       90 04		      BCC	.skipL03
   1669  f479				   .condpart2
   1670  f479		       a9 2a		      LDA	#42
   1671  f47b		       85 d7		      STA	b
   1672  f47d				   .skipL03
   1673  f47d				   .
   1674  f47d							;
   1675  f47d
   1676  f47d				   .L04 		;  if a  <  c then b  =  42
   1677  f47d
   1678  f47d		       a5 d6		      LDA	a
   1679  f47f		       c5 d8		      CMP	c
   1680  f481		       b0 04		      BCS	.skipL04
   1681  f483				   .condpart3
   1682  f483		       a9 2a		      LDA	#42
   1683  f485		       85 d7		      STA	b
   1684  f487				   .skipL04
   1685  f487				   .
   1686  f487							;
   1687  f487
   1688  f487				   .L05 		;  if a  <=  c then b	=  42
   1689  f487
   1690  f487		       a5 d8		      LDA	c
   1691  f489		       c5 d6		      CMP	a
   1692  f48b		       90 04		      BCC	.skipL05
   1693  f48d				   .condpart4
   1694  f48d		       a9 2a		      LDA	#42
   1695  f48f		       85 d7		      STA	b
   1696  f491				   .skipL05
   1697  f491				   .
   1698  f491							;
   1699  f491
   1700  f491				   .
   1701  f491							;
   1702  f491
   1703  f491				   .L06 		;  goto __Main_Loop
   1704  f491		       4c 5d f4 	      jmp	.__Main_Loop


#4 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,746 posts

Posted Fri Dec 18, 2015 8:48 AM

RT, that is absolutely what is going on but it's the underlying 6502 design that is more efficient in one direction:

 

(Note: Your code otuput shows that ">=" is more efficient than ">", not the other way around).

 

bcc is "<" so in the first example we're running the target code only if the inverse is true (>=)

bcs is is the inverse of bcc but they are not equal (pardon the pun), we've basically got two instructions that say "<" and ">="

 

Now if we want logic for "<=" or ">" we have to add another branch instruction beq ("=") to build it so it's always better to go with ">=" instead of ">" and "<" instead of "<="  when you have the option.

 

Compiler optimizations usually take advantage of the architecture too; here is a For loop example is from Virtual World BASIC (bB may have similar optimizations):

 

The for loop that uses step has three extra instructions over the for loop that does not use step - I was able to add the optimization because step requires multiple instructions (must use the accumulator to add or subtract compared to inc) as well as bounds checking to keep the for loop from falling through which also isn't necessary without the step kepword: 

 

L_43 ;---assignments & functions: _43 for i= 91 to 13 step -2
 lda #91; -- Init For Loop
 sta i; -- Init For Loop
l0_For_Loop_STARTL_43

 

L_44 ;---assignments & functions: _44 for j = 7 to 12
 lda #7; -- Init For Loop
 sta j; -- Init For Loop
l1_For_Loop_STARTL_44

 

;.... looped code here

 

L_46 ;---assignments & functions: _46 next j,i

l1_For_Loop_END_checkL_44
 lda j
 cmp #12
 bcs l1_For_Loop_ENDL_44
 inc j
 jmp l1_For_Loop_STARTL_44
l1_For_Loop_ENDL_44; done with loop

l0_For_Loop_END_checkL_43
 lda i
 cmp #13
 beq l0_For_Loop_ENDL_43
 bcc l0_For_Loop_ENDL_43
 sec
 sbc #2
 bcc l0_For_Loop_ENDL_43; kick out if step value overflows
 sta i
 jmp l0_For_Loop_STARTL_43
l0_For_Loop_ENDL_43; done with loop

 

 

 

 



#5 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • Topic Starter
  • 28,179 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Fri Dec 18, 2015 10:48 AM

Thanks. I just added another version to my post that uses another variable instead of a number.



#6 GroovyBee OFFLINE  

GroovyBee

    Games Developer

  • 9,736 posts
  • Busy bee!
  • Location:North, England

Posted Fri Dec 18, 2015 2:59 PM

With bB there is always one comparison and one branch no matter if you use ">", ">=" or "<", "<=" so there are no size/speed optimisations to be had by choosing one over the other.



#7 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • Topic Starter
  • 28,179 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Fri Dec 18, 2015 3:53 PM

With bB there is always one comparison and one branch no matter if you use ">", ">=" or "<", "<=" so there are no size/speed optimisations to be had by choosing one over the other.

 

Thanks. I'll go put a version of what you said on the bB page right now before I forget in case anyone wonders about it in the future.

 

I'll also stop changing if-thens in the Seaweed Assault code. That will save me some time.

 

 

Here is the link:

 

randomterrain.com/atari-2600-memories-batari-basic-commands.html#note_simple_comparison



#8 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,746 posts

Posted Sat Dec 19, 2015 12:41 AM

With bB there is always one comparison and one branch no matter if you use ">", ">=" or "<", "<=" so there are no size/speed optimisations to be had by choosing one over the other.

That's pretty cool, I see from the code RT posted bB juxtaposes the operands to reduce the number of instructions used in Spice's example; here's the initial example code, and then again replaced with this optimization:  

 

test:

  lda c 
  cmp b
  bcc Skip ;  c is Less Than b (carry flag)
  beq Skip ; c is Equal To b (zero flag)
  ; c>b logic here

Skip:

 

becomes:

 

test:

  lda b 
  cmp c

  bcs Skip ; b >= c (otherwise c>b)
  ; c> b logic here

Skip:

 

vwB is using SpiceWare's double branch instructions from the first example:)






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users