Shop OBEX P1 Docs P2 Docs Learn Events
Signed multiply in PASM - need one — Parallax Forums

Signed multiply in PASM - need one

Chris_DChris_D Posts: 305
edited 2014-11-24 13:32 in Propeller 1
Hi Follks

Somehow I painted myself into a corner with the PASM multiply example which is published in the new Prop manual.· I even asked for help on how to use it and was warned about it working with 16 bit values and postive numbers only.· Yet, I went ahead and used my selective reading skills to think it could work with signed numbers.

Now I am stuck and am hoping someone has a PASM multiply routine that can handle signed numbers.

I recall many months ago what I think was one posted by someone and I can't find it again.· I seem to recall the poster's avatar looking like an open cockpit pilot with bugs in his teeth - maybe goes by the name of Cessna pilot.· Even if you can't recall that one in particular, I am not that picky :-)· I just need one that can handle signed values.


Chris

Comments

  • Chris_DChris_D Posts: 305
    edited 2010-04-11 14:12
    Grr. I found that post and it appears it is for 8 bit.· So does anyone else have something that could solve my problem ?



    Chris
  • BeanBean Posts: 8,129
    edited 2010-04-11 14:25
    Here is the PropBasic multiply routine.
    This is a signed 32-bit by 32-bit with a 64-bit result.
                      mov           __temp1,mult1               '  mult3 = mult1 * mult2
                      mov           __temp2,mult2               
    
     
                      abs           __temp1,__temp1 WC          ' make values positive, __temp3 holds sign of result
                      muxc          __temp3,#1                  
                      abs           __temp2,__temp2 WC, WZ      
        IF_C          xor           __temp3,#1                  
    
                      mov           __temp4,#0                  ' Setup for 32 bits of multiply loop
                      mov           __temp5,#32                 
                      shr           __temp1,#1 WC               
    
     
    __L0001                                                     ' Main multiply loop
        IF_C          add           __temp4,__temp2 WC          
                      rcr           __temp4,#1 WC               
                      rcr           __temp1,#1 WC               
                      djnz          __temp5,#__L0001            
    
                      test          __temp3,#1 WZ               ' Check if result should be negative
        IF_NZ         neg           __temp4,__temp4             
        IF_NZ         neg           __temp1,__temp1 WZ          
        IF_NZ         sub           __temp4,#1                  
    
                      mov           mult3,__temp1               ' Store lower 32-bit of result, __temp4 = upper 32-bits of result
    
     
     
    

    __temp1 is the lower 32-bits of the result
    __temp4 is the upper 32-bits of the result

    Bean

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Use BASIC on the Propeller with the speed of assembly language.
    PropBASIC thread http://forums.parallax.com/showthread.php?p=867134

    March 2010 Nuts and Volts article·http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/prop/col/nvp5.pdf
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    There are two rules in life:
    · 1) Never divulge all information

    Post Edited (Bean) : 4/11/2010 2:38:40 PM GMT
  • Chris_DChris_D Posts: 305
    edited 2010-04-11 17:03
    Bean,

    Thank you VERY MUCH!· I will give that a go and see if I can get it working for me.

    Chris
  • parskoparsko Posts: 501
    edited 2014-11-22 05:42
    Hi Bean,

    Any chance of there being an equivalent divide routine?

    Thanks,

    Parsko
  • BeanBean Posts: 8,129
    edited 2014-11-22 10:00
    Here is what PropBasic generates
                      mov           __temp1,__param2             '  __param1 = __param2 / __param3
                      mov           __temp2,__param3            
                      mov           __temp4,#0                   ' Set result to zero
                      
                      ' Get sign of result in __temp5 while making values positive
                      abs           __temp1,__temp1 WC           ' __temp1 = abs(__temp1) carry is set if __temp1 was negative 
                      muxc          __temp5,#1                   ' If carry was set set __temp5 to 1 (1 means result is negative)
                      abs           __temp2,__temp2 WC, WZ       ' __temp2 = abs(__temp2) carry is set if __temp2 was negative, and zero flag is set if __temp2 is zero
        IF_Z          mov           __temp1,#0                   ' If divisor is zero return zero           
        IF_Z          jmp           #__L0001                    
        IF_C          xor           __temp5,#1                   ' If __temp2 was negative then invert result sign (neg / neg = pos)
               
                      ' Shift dividend until a 1 is in the MSB
                      mov           __temp3,#0                   ' __temp3 counts how many shifts
                      min           __temp2,#1                   ' Make sure __temp2 is not zero  
    __L0002                                                     
                      add           __temp3,#1                   
                      shl           __temp2,#1 WC               
        IF_NC         jmp           #__L0002                    
                      rcr           __temp2,#1                  
    
                      ' This is the main divide loop
    __L0003                                                     
                      cmpsub        __temp1,__temp2 WC          
                      rcl           __temp4,#1                  
                      shr           __temp2,#1                  
                      djnz          __temp3,#__L0003            
    
                      ' Handle result sign
                      test          __temp5,#1 WZ                ' Should result be negative ?
        IF_NZ         neg           __temp4,__temp4              ' If negative, negate result
        IF_NZ         neg           __temp1,__temp1              '  and also negate remainder too
    __L0001                                                     
                      mov           __param1,__temp4            
    

    The remainder is in __temp1 after the routine.

    You can strip a lot of code if your values are always positive.

    Bean
  • parskoparsko Posts: 501
    edited 2014-11-24 13:32
    Thanks bean!
Sign In or Register to comment.