Unsupported instruction Exception on AC256 with DIVS

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Unsupported instruction Exception on AC256 with DIVS

3,021 Views
Kopone
Contributor IV
Hello,

working on a project, I encountered the following using Codewarrior 6.1 that came with the new AC development board (target CPU is the Coldfire 51AC256 that came with the board):

I got some C source, which devides a global variable by a #define'd constant:


Code:
int test_function(void){#define SCALER 20static int position=0;// dial_turns is a global variable which is written by an interrupt service routineposition+=dial_turns/SCALER;dial_turns=0;return position;}


The compiled code will never get below the division line.
The assembly reads:

Code:
41A8  MVS.W   0x0080051E,D1   ; This fetches the global dial_turns variable41AA  MOVEQ   #20, D0   ; Loads the constant41B0  DIVS.W  D0, D1 ; Execute division  

 Using the debugger, I can step up to the DIVS.W mnemonic.
The registers will read D0=0x14 (yes, that's 20) and D1=0 at this point.
Executing the next assembly step will take me here:

Code:
/*** ===================================================================**     Method      :  Cpu_Cpu_Interrupt (bean MCF51AC256A_80)****     Description :**         This ISR services an unused interrupt/exception vector.**         This method is internal. It is used by Processor Expert only.** ===================================================================*/ISR(Cpu_Interrupt){}

 The assembly reads just RTE which will take me back to the faulty DIVS command, so the MCU is trapped in an infinite loop.

The question is, what is happening here. At first I thought about a division by zero, but I am dividing by a constant which is always loaded as #20. The divident is zero, yes, but that should just result in 0x00 in D1. So not to confuse, DIVS shall divide D1/D0 here and store in D1. That's 0x00/0x14.

I then took a look at the exception stack, which reads the following:

40 F4 20 00 00 00 41 A8

According to the prog.ref manual, the exception stack frame is the same for all kinds of traps, the latter LONG is the return pointer. The leading long though is made up of the exception cause and the vector number that has been accessed, which to me means this result:

40                 f4                 20               00

0100 0000   1111 0100   0010 0000   0000 0000

Format: 0100
FS[3-2]: 00
VEC: 00111101
FS[1-0]: 00

A fault status of 00 means
"0000 Not an access or address error nor an interrupted debug service routine"

Vector 00111101=decimal 61 means:
61 0F4 Fault Unsupported instruction

As far as I can see though, the prog manual does not state any exception from the DIVS command for the AC MCUs.

I might have overlooked just a tiny little thing which would have made a long story pretty short. If so, by all means, PLEASE point me to it.

If not, I have no idea what to do to prevent the compiler from generating commands the MCU is not capable of.

Any hints HIGHLY appreciated.

Regards,
 Sven




Message Edited by Kopone on 2008-11-24 12:04 AM
Labels (1)
0 Kudos
Reply
5 Replies

1,186 Views
CompilerGuru
NXP Employee
NXP Employee
I would suggest to file a service request and also to check if this has been fixed in the current 6.2 release.

Daniel
0 Kudos
Reply

1,186 Views
Kopone
Contributor IV
Provided I did not overlook something essential - which is why I posted this - a support ticket was definitely a good idea.

I can not check if it works with current 6.2 because the compiler crashes when compiling my project and I already filed a request on that (and got the confirmation that it's reproducable). Ah, I could at least try a tiny little test project that just does the division.

Edit: 6.2 does it right, it always calls _ldiv_. So I guess there aint much point in requesting a ticket since 6.1 undergoes no further development, or does it?
Either way I had to wait for a 6.1 that works ok with 16 bit integers or wait for a 6.2 that won't crash on compiling. Darn thing, now what...

Regards,
 Sven



Message Edited by Kopone on 2008-11-24 04:30 PM
0 Kudos
Reply

1,186 Views
ForthOK
Contributor I
Just ran into this same problem.  You did not post a follow-up, but I found this in the RM:

1.3 V1 ColdFire Core

The MCF51AC256 series devices contain a version of the V1 ColdFire core that is optimized for area and low power. This CPU implements ColdFire instruction set architecture revision C (ISA_C) plus adds support for real-time program trace capability:

• No hardware support for MAC/EMAC and DIV instructions

0 Kudos
Reply

1,186 Views
Kopone
Contributor IV
Ok, so that is where the information is written. My bad, I clearly overlooked this one (darn thing, I really searched all the docs, but I searched for DIVS and DIVU, not just DIV...).
I got feedback from support meanwhile, but they just pointed me to the CPRM and said the ISA_C instruction set was used on the AC core (there is however no hint in the CPRM about a CF V1 core with a missing hardware divider, and DIVS is of course part of the ISA_C set), so there wasn't any point in posting a followup. I still have a strong feeling that this document needs updating, since it is the #1 place to look for any particular assembly instruction issue. However support told me there are no plans to do any updating.

Well, seems it just happens from time to time that the vital information you're looking for is hiding too well - or you (in this case me) didn't chose your search phrase carefull enough :smileywink:

Anyway, the issue stays the same and it is now clear that the missing divider is intentional but the CW version that ships with the demo board ain't aware of that. The simple solution still is to use CW 6.2 (and the particular problem I encountered with the compiler crash can easily be worked around with a different optimization setting - thanks to Freescale support for pointing this out).

Regards,
 Sven
0 Kudos
Reply

1,186 Views
Kopone
Contributor IV
Hm, seems my own reply got just lost while editing. Great. Here I go again.

Ok, so what I found in the CFPRM is the following:

---quote---
NOTE
The DIVS/DIVU and RES/REMU instructions are not implemented on the
earliest V2-based devices MCR5202, MCF5204 and MCF5206.
---quote---

I also tracked down the above problem to be entirely dependant on the compiler setting "4-Byte Integers".
I UNchecked this for my project, since it's a port from an 8 Bit CPU and it's heavily relying on INTs being 16 bit since it's accessing data in an Eeprom which exists in 16 bit portions.

A simple test project revealed that CW will generate a DIVS instruction for any division when i UNcheck "4-Byte Integers".
Then checking it again will produce code that instead of doing a DIVS will call a subroutine "__ldiv__" for any division (be it char, int or long).

Any DIVS will clearly lead to an illeagal opcode exception, I however can not find a hint in the manual (Document Number: CFPRM Rev. 3 03/2005) that this is intentional. So it's either the MCU, the compiler, or me overlooking something blatant that leads to all the confusion.

Could someone please shed some light on this issue since right now I really don't see how to proceed with porting the project without having 16 bit integers?

Edit:

3/2005 seems pretty outdated for a document to cover the lates Flexis core, but it is exactly the document which the ColdFire V1 page links to (see link "ColdFire Programmer's Reference Manual" on top right of this page:
http://www.freescale.com/webapp/sps/site/overview.jsp?code=DR68KV1CF&fsrch=1

A closer look now revealed that this document doesn't even have an idea of the existance of a V1 core, hence no comment about DIVS being present or not. According to the D0 register content on startup though, there is clearly no hardware divider present, hence this all comes down to a compiler bug. I just wonder if other than the AC Flexis cores got a divider, cause otherwise this should have stood out long ago already?

Regards,
 Sven


Message Edited by Kopone on 2008-11-24 11:59 AM
0 Kudos
Reply