CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Hardware division

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

Hardware division
PostPosted: Fri Oct 20, 2017 8:23 am     Reply with quote

Good day,

How would I code the following in assembly?

Code:
      TempMsg = TempMsg/10000; //Gives 1 decimal after point thus 122 will be 12.2A

Where TempMsg is a int32 variable.

Using CCS 5.074
dsPIC33EP128GM604 which have a hardware division instruction, can't seem to find a function in CCS which will do what the _mul() do.

Regards[/quote]
Ttelmah



Joined: 11 Mar 2010
Posts: 19559

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 8:35 am     Reply with quote

You can't.
A float number has no concept of decimal places. In fact it won't even guarantee to hold any number accurately. 33000.1 for example will actually be stored internally as 33000.102 since this is the closest representation possible.

Just store integer 'tenths'. So /1000, so you have 122. Then the %LW output will print this as if it has one decimal.

122 will print as 12.2 etc..
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 8:49 am     Reply with quote

Hi Ttelmah,

Everything is already in integer. I just need to scale by 10000.
So something like 123456 will become 12. this i send through to someone else who will display as 1.2 for instance.

I don't want float and have never used it before.
I want to use the div.sd instruction, but my assembler are not that good, can understand when I read the listing but that is as far as it go. Last time I used assembler with MPLAB was in 1999.

Regards
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 9:35 am     Reply with quote

Try using the ldiv() function and look at the assembly it generates. I might be misunderstanding what you are looking for though.
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 10:06 am     Reply with quote

I'll try again.

I want something similar to the _mul() function
Code:
....................       TempMsg = _mul(iref,Offset);
  MOV     101C,W4
  MOV     103A,W3
  MUL.US  W4,W3,W0
  MOV     W0,1140
  MOV     W1,1142


Code:
      TempMsg = TempMsg/10000;
  MOV     101C,W4
  MOV     103A,W3
  MOV     103A,W3  ???
  MOV     103A,W3  ???
  REPEAT #18  ?????
  DIV.SD  ??,??,??,W4,W3,W0
  MOV     W0,1140
  MOV     W1,1142

Edit: Had a look on the web and found that there will probably be a repeat.
Regards
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 10:52 am     Reply with quote

did you try the ldiv() function?

I don't know off the top of my head if it implements the same or not. It might be different.

The repeat instruction is required for hardware division to work.

EDIT: Here is the relevant blurb from the datasheet:
Quote:

The 16-bit ALU has been enhanced with integer divide
assist hardware that supports an iterative non-restoring
divide algorithm. It operates in conjunction with the
REPEAT instruction looping mechanism and a selection
of iterative divide instructions to support 32-bit (or
16-bit), divided by 16-bit, integer signed and unsigned
division. All divide operations require 19 cycles to
complete, but are interruptible at any cycle boundary.
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 1:27 pm     Reply with quote

Sorry I should have included the asm in previous reply.
Code:
....................     TempMsg = TempMsg/10000; //Gives 1 decimal after point thus 122 will be 12.2A
014FE:  BCLR.B  43.0
01500:  MOV     1140,W0
01502:  MOV     1142,W1
01504:  MOV     #2710,W2
01506:  MOV     #0,W3
                                     01508:  CALL    13A2
0150C:  MOV     W0,1140
0150E:  MOV     W1,1142
....................     TempMsg = ldiv(TempMsg,10000);
01510:  PUSH    1140
01512:  POP     116A
01514:  PUSH    1142
01516:  POP     116C
01518:  MOV     #2710,W4
0151A:  MOV     W4,116E
0151C:  CLR     1170
0151E:  CALL    14AE
01522:  MOV     W0,1140
01524:  MOV     W1,1142

and then the call to 14AE. You will see it end up calling 13A2 which are the same function for the standard divide.
Code:
....................    val.quot = numer / denom;
*
014AE:  BCLR.B  43.0
014B0:  MOV     116A,W0
014B2:  MOV     116C,W1
014B4:  MOV     116E,W2
014B6:  MOV     1170,W3
                                   014B8:  CALL    13A2
014BC:  MOV     W0,1172
014BE:  MOV     W1,1174
....................    val.rem = numer - (denom * val.quot);
014C0:  MOV     116E,W0
014C2:  MOV     1170,W1
014C4:  MOV     1172,W2
014C6:  MOV     1174,W3
014C8:  CALL    146C
014CC:  MOV     116A,W4
014CE:  SUB     W4,W0,W0
014D0:  MOV     W0,1176
014D2:  MOV     116C,W4
014D4:  SUBB    W4,W1,W0
014D6:  MOV     W0,1178
....................    return (val);
014D8:  MOV     1172,W0
014DA:  MOV     1174,W1
014DC:  MOV     1176,W2
014DE:  MOV     1178,W3
014E0:  RETURN 
Ttelmah



Joined: 11 Mar 2010
Posts: 19559

View user's profile Send private message

PostPosted: Fri Oct 20, 2017 2:08 pm     Reply with quote

A standard integer division does what he is describing.
The point about ldiv, is it gives you access to the remainder, which he is not talking about.

Key is that there is no equivalent to mul. A numeric multiplication can overflow. The point about mul is you start with two smaller numbers (8 bit say), and keep the overflow to give you a 16bit result. On a division, you need to be using the larger maths type to actually perform the division. You can simply just take the smaller result when finished.

Declare a structure containing two int16's 'MSW & LSW'. Then declare a union between this and the int32. Simply perform a standard division by 10000, and then access the LSW as the result. No casting needed, and you are now using the smaller type.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group