Hi I am using the MCF51JE2256 and when I try to use the DIVU/DIVS instructions it forces a reset...any ideas what I am doing wrong?
move.w #$03E8,D2 ;move in 1000 dec
divu.l D2,D0 ;divid by 1000
move.b D0,(adeci1,A5) ;store 1000 place
move.b D1,D0 ;get original byte
move.b #$64,D2 ;move in 100
divu.l D2,D0 ;divide it by 100
move.b D0,(adeci2,A5) ;save hundreds place
move.w D1,D0 ;get orginal byte
move.b #$0A,D2 ;move in 10 dec
divu.l D2,D0 ;divide by 10
move.b D0,(adeci3,A5) ;store tens place(s)
AFAIK JE256 has only MAC and no hardware divider. You need to use software routines for DIV and MOD.
Try reading hardware configuration info (contents of D0 register on reset, see Reset Exception chapter in JE reference manual). See if DIV bit is set or not.
> Try reading hardware configuration info (contents of D0 register on reset, see Reset Exception
> chapter in JE reference manual). See if DIV bit is set or not.
You shouldn't have to read a register to see if the CPU has a divide instruction. That should be obvious from the manual. That should be explicitly documented in the manual. But it isn't.
The Reference Manual states:
1.3 V1 ColdFire Core
The CPU implements ColdFire instruction set architecture revision C (ISA_C) with added
capabilities:
• Hardware MAC support for 16X16 32 and 32X32 32 bit multiply-accumulate operations
(32-bit accumulator)
• Upward compatibility with all other ColdFire cores (V2–V5)
7.1 Introduction
For detailed information on instructions, see the ISA_C definition in the
ColdFire Family Programmer’s Reference Manual.
That referenced manual states:
3.2 Instruction Set Summary
Table 3-14 shows the entire user instruction set in alphabetical order. Table 3-15 shows the entire
supervisor instruction set in alphabetical order. Recall the major ISA revisions are defined as:
• ISA_ A: Original ColdFire instruction set architecture.
• ISA_B: Improved data movement instructions, byte- and word-sized compares, and miscellaneous
enhancements are added.
• ISA_C: Instructions are added for improved bit manipulation.
• FPU: Floating-Point Unit instructions.
• MAC: Multiply-Accumulate instructions.
• EMAC: Revised ISA for enhanced Multiply-Accumulate unit.
• EMAC_B: Instructions are added for dual-accumulation operations.
DIV is listed as first appearing in ISA_A. The Cross Reference in Table 3-16 shows ISA_C supports DIVU, DIVS, REMS and REMU.
So from that the JE256 MUST support the DIV instructions.
Except ...
CFPRM Table 11-1. Exception Vector Assignments
Vector 5 [Note 2] Offset: 014 Assignment: Divide by zero
Note 2: If the divide unit is not present (5202, 5204, 5206), vector 5 is reserved.
So only the 5202, 5204 and 5206 don't have Divide Units according to the latest Programmer's Reference Manual (Rev 3, March 2005). This is also the version linked from the MCF51JE256 page on Freescale's web site.
Comparing that table with the one in the MCF51JE256 manual:
Table 7-6. Exception Vector Assignments
Vector 5-7 Offset: 0x014-0x01C Assignment: Reserved
No divide-by-zero trap. That implies it doesn't have the divide instruction.
> Try reading hardware configuration info (contents of D0 register on reset, see Reset Exception
> chapter in JE reference manual). See if DIV bit is set or not.
7.3.3.14 Reset Exception
Figure 7-12. D0 Hardware Configuration Info
The above figure doesn't give the default value for the DIV bit. It is blank.
Didn't Freescale know if the CPU was going to support the divide instruction when they wrote the manual?
That's a glaring conflict in the manual, and an important feature of the chip that looks to have been left out, without documenting that it has been left out.
Looking at other manuals...
The MCF51JM128 manual doesn't list a divide-by-zero exception, the Reset Exception documentation says the "DIV" bit isn't set (but it doesn't state if it has a MAC or not). Except this manual does state:
1.3 V1 ColdFire Core
This CPU implements ColdFire instruction set architecture revision C (ISA_C) with a reduced
programming model:
• No hardware support for MAC/EMAC and DIV instructions.
The MCF51AC256, CN128 and QE128 manuals say the same thing.
That text doesn't appear in the MCF51JE256 manual. That's the problem here. When the line in section 1.3 stating "Hardware MAC support..." got added, the "No hardware support .. DIV instruction" got deleted.
Tom
I think that DIV HW is optional and doesn't violate ISA_C requirements. CPU should handle divide and remainder instruction anyway, but since DIV HW is not present, CPU should jump to specific exception handler.
Of course you are right, it must be specified more clearly is DIV HW present in specific family, or not.
Indeed there are V1's with MAC
> I think that DIV HW is optional and doesn't violate ISA_C requirements.
Not as documented in the currently released (seven year old) version of the "ColdFire Family Programmer's Reference Manual Rev 3 03/2005".
According to it, the only "options" are Floating Point, MAC, EMAC and EMAC_B. It documents that DIV isn't available in MCF5202, MCF5204 and MCF5206, but ONLY in those models.
If some internal Freescale specification of "ISA_C" has changed to allow DIV to be optional, then a new version of the CFPRM should be released stating that.
The individual MCF51AC, CN, JM and QE manuals all state "ISA_C with a reduced programming model: ... No hardware support ... DIV instructions".
The documentation error is that sentence isn't present in the MCF51JE256 manual. I've put in a Service Report on this.
> but since DIV HW is not present, CPU should jump to specific exception handler.
Obviously not provided (or enabled) by whatever development environment "grt951" is using.
Does CodeWarrior provide these automatically if the right CPU and/or build options are selected?
Tom
V1CFWP.pdf "Version 1 ColdFire® White Paper", Rev 0 07/2006, on page 6 has these lines:
MCF51JFRM128.pdf confirms the above. On page 73 it is said that JF has both EMAC and DIV. D0 Hardware Configuration Information table on page 256 just confirms this.
So "ColdFire Family Programmer's Reference Manual Rev 3 03/2005" is really outdated
TomE wrote:The documentation error is that sentence isn't present in the MCF51JE256 manual. I've put in a Service Report on this.
I have received the following answer:
... In reply to your message regarding Service Request SR xxxx: Yes, you are right there is a document error on the reference manual of JE family. I already create an internal service request to the document department in order to fix this document. Please accept my apologies for the inconvenience. Have a good day.
Tom
I wrote, just over a YEAR ago:
> I have received the following answer:
>
>... In reply to your message regarding Service Request SR xxxx:
> Yes, you are right there is a document error on the reference
> manual of JE family. I already create an internal service request
> to the document department in order to fix this document. Please
> accept my apologies for the inconvenience. Have a good day.
That Service Request was closed 5 days after I reported it. Has the manual been updated? Has a Reference Manual Addendum been released? It would make a lot of sense if the "close" was delayed until something actually happened.
The Reference Manual "MCF51JE256RM.pdf" is still dated "12/1/2010" and there's no sign of a Reference Manual Addendum.
The only place these problems are documented is in this forum. Nothing else seems to work.
Tom
I was recently using the MCF51AC256 which hit me with the same unexpected problem, no division instruction.
The GNU C compiler supplies its own arithmetic and can handle that if you specify the
"-hwdiv" parameter for the call in your BAT file.
set GENFLAGS=-m5200 -mno-mac -mno-hwdiv -w -O0 -Wa,-a=C:\PROJ\GNUBOA~1\main.lst
here's an excerpt from the MCF51AC256 reference manual:
7.3.3.14 Reset Exception
Asserting the reset input signal (RESET) to the processor causes a reset exception. The reset exception has
the highest priority of any exception; it provides for system initialization and recovery from catastrophic
failure. Reset also aborts any processing in progress when the reset input is recognized. Processing cannot
be recovered.
The reset exception places the processor in the supervisor mode by setting the SR[S] bit and disables
tracing by clearing the SR[T] bit. This exception also clears the SR[M] bit and sets the processor’s SR[I]
bit to the highest level (level 7, 0b111). Next, the VBR is initialized to zero (0x0000_0000). The control
registers specifying the operation of any memories (e.g., cache and/or RAM modules) connected directly
to the processor are disabled.
NOTE
Other implementation-specific registers are also affected. Refer to each
module in this reference manual for details on these registers.
After the processor is granted the bus, it performs two longword read-bus cycles. The first longword at
address 0x(00)00_0000 is loaded into the supervisor stack pointer and the second longword at address
0x(00)00_0004 is loaded into the program counter. After the initial instruction is fetched from memory,
program execution begins at the address in the PC. If an access error or address error occurs before the first
instruction is executed, the processor enters the fault-on-fault state.
ColdFire processors load hardware configuration information into the D0 and D1 general-purpose
registers after system reset. The hardware configuration information is loaded immediately after the
reset-in signal is negated. This allows an emulator to read out the contents of these registers via the BDM
to determine the hardware configuration.
Information loaded into D0 defines the processor hardware configuration as shown in
Figure 7-12.
..and so forth, with a big diagram in Figure 7-12 showing each bit.
For assembly division on the V1 a macro is just about the worst thing I could immagine. I just whipped
up a quick shift and subtract subroutine. To be called by assembly calculations.
I've managed to scrounge up an old copy of that division routine written in PE-Micro assembly but it's an early one and I'm not sure if it has a bug with signed numbers or not.
(Man that excerpt didn't look that bad before I previewed it)
Mudwog
Thank you everyone for your help....
I had to use a macro to divide because as many of you pointed out there is no hardware divider in the JE256. I found the following routine which can divide pretty much anything.
;*** ColdFire 32/32->32 unsigned divide routine
;*** C = A/B, A is called the dividend, B the divisor and C the quotient.
;*** D0 = dividend
;*** D1 = divisor
;*** quotient returned in D0 also D0 = (D0/D1)
;*** (preserves all other registers)
uldiv lea.l (-16,a7),a7 ;adjust the stack pointer
movem.l D4-D7,(a7) ;save d4, d5, d6, d7 registers
move.l d0,d5 ;store a dividend copy in D5
move.l d1,d7 ;store a divisor copy in D7
move.l d7,d0 ;D0 = D7 = divisior
subq.l #$01,d0 ;D0 = D0 -1 = divisior - 1
and.l d7,d0 ;
bne.b L_ULDIV17
move.l d5,d0
lsr.l #$01,d7
beq.w L_ULDIV18
L_ULDIV5
lsr.l #$01,d0
lsr.l #$01,d7
bne.b L_ULDIV5
bra.w L_ULDIV18
L_ULDIV17
move.l d7,d4
or.l d5,d4
move.l #$0ff000000,d6
move.l d6,d0
and.l d4,d0
bne.b L_ULDIV6
asr.l #$08,d6
move.l d6,d0
and.l d4,d0
bne.b L_ULDIV6
asr.l #$08,d6
move.l d6,d0
and.l d4,d0
bne.b L_ULDIV6
asr.l #$08,d6
L_ULDIV6
moveq.l #$00,d4
move.l d6,d0
and.l d7,d0
bne.b L_ULDIV11
lsl.l #$08,d7
moveq.l #$08,d4
move.l d6,d0
and.l d7,d0
bne.b L_ULDIV11
lsl.l #$08,d7
moveq.l #$010,d4
move.l d6,d0
and.l d7,d0
bne.b L_ULDIV11
lsl.l #$08,d7
moveq.l #$018,d4
L_ULDIV11
tst.l d5
bpl.b L_ULDIV41
tst.l d7
ble.b L_ULDIV43
L_ULDIV44
addq.l #$01,d4
add.l d7,d7
bmi.b L_ULDIV43
addq.l #$01,d4
add.l d7,d7
bpl.b L_ULDIV44
L_ULDIV43
addq.l #$01,d4
bra.b L_ULDIV42
L_ULDIV41
cmp.l d5,d7
bhi.b L_ULDIV10
L_ULDIV39
add.l d7,d7
addq.l #$01,d4
cmp.l d5,d7
bhi.b L_ULDIV10
add.l d7,d7
addq.l #$01,d4
cmp.l d5,d7
bls.b L_ULDIV39
L_ULDIV10
lsr.l #$01,d7
L_ULDIV42
moveq.l #$00,d0
tst.l d4
beq.b L_ULDIV18
subq.l #$01,d4
ble.b L_ULDIV12
L_ULDIV13
cmp.l d7,d5
bcs.b L_ULDIV14
sub.l d7,d5
or.l #$01,d0
L_ULDIV14
lsr.l #$01,d7
add.l d0,d0
subq.l #$01,d4
ble.b L_ULDIV12
cmp.l d7,d5
bcs.b L_ULDIV14a
sub.l d7,d5
or.l #$01,d0
L_ULDIV14a
lsr.l #$01,d7
add.l d0,d0
subq.l #$01,d4
bgt.b L_ULDIV13
L_ULDIV12
cmp.l d7,d5
bcs.b L_ULDIV18
or.l #$01,d0
L_ULDIV18
tst.l d3
movem.l (a7),D4-D7 ;restore d4, d5, d6, d7 registers
lea.l (16,a7),a7
rts
I can't immediately see why you're getting a reset as it doesn't seem to be dividing by zero anywhere, but there are bugs on just about every line of your code.
For debugging the reset, add some exception service routines to all the exception vectors, and have them breakpoint or print or something. Are you sure "A5" is set up properly?
Can you single-step through the code and see which line it fails on?
As for the code:
Assume D0 contains xxxxxxxx and D2 contains yyyyyyyy move.w #$03E8,D2 ; move in 1000 decD2 now contains yyyy03e8 divu.l D2,D0 ;divid by 1000D0 contains xxxxxxxx/yyyy03e8, call this zzzzzzzz move.b D0,(adeci1,A5) ;store 1000 place move.b D1,D0 ;get original byteD0 now contains zzzzzzxx move.b #$64,D2 ;move in 100D2 now contains yyyy0364 divu.l D2,D0 ;divide it by 100D0 now contains zzzzzzxx/yyyy0364, call this mmmmmmmm move.b D0,(adeci2,A5) ;save hundreds place move.w D1,D0 ;get orginal byteD0 now contains mmmmzzzz move.b #$0A,D2 ;move in 10 decD2 now contains yyyy030a divu.l D2,D0 ;divide by 10D0 now contains mmmmzzzz/yyyy030a, call this nnnnnnnn move.b D0,(adeci3,A5) ;store tens place(s)
I'm not sure what the above routine is trying to do, but I'm sure you're not intending to divide by almost random numbers like you're doing.
"move.b #$64,D2 ;move in 100" moves 0x64 into the lower BYTE of D2, leaving the upper three bytes the same as they were before.
In your case, the divide instruction might have zeroed the upper bits as a side effect of the division and the data you're using, but relying on that is very risky. The "divide by 100" is guaranteed to be dividing by 868 (0x0364) even if you have zeroed D2 previously.
This is "just something you have to know". I've just read the "ColdFire Family Programmer's Reference Manual" pretty much from cover to cover, and after a trip back to an old 68000 Programming Manual I found section 1.19 in the ColdFire one:
1.9 Organization of Data in Registers This section describes data organization within the data, address, and control registers. 1.9.1 Organization of Integer Data Formats in Registers Each integer data register is 32 bits wide. Byte and word operands occupy the lower 8- and 16-bit portions of integer data registers, respectively. Longword operands occupy entire data registers. A data register that is either a source or destination operand only uses or changes the appropriate lower 8 or 16 bits (in byte orword operations, respectively). The remaining high-order portion does not change and is unused and unchanged.
If you missed reading that section you have to read between a lot of lines to find this out. The MOVE instruction
MOVE: Moves the data at the source to the destination locationand sets the condition codes according to the data. Thesize of the operation may be specified as byte, word, or longword.
That doesn't mention sign extending. Compare with these instructions:
MOVEA Word size source operands are sign extended to 32-bit quantities before the operation is done. MOVEQ The data in an 8-bit field within the operation word is sign-extended to a longword operand in the data register as it is transferred. MOV3Q The 3-bit immediate operand is sign extended to a longword operand and all 32 bits are transferred to the destination location. MVS Move with Sign ExtendSign-extend the source operand and move to the destination register. MVZ Move with Zero-Fill Zero-fill the source operand and move to the destination register .
MOV3Q, MVZ and MVZ all require ISA_B. I know the MCF51MM256 is ISA_C, so your one might be too. it is more portable to explicitly clear the registers before loading bytes or words into them, like this compiler-generated code does:
40104698: 4280 clrl %d 04010469a: 1001 moveb %d1,%d 04010469c: 2f00 movel %d0,%sp@- 4010469e: 4e90 jsr %a0@ ======================= 40104972: 4280 clrl %d0 40104974: 4878 000c pea c <OPER1> 40104978: 1439 4024 56bd moveb 402456bd <cmdQueueHead>,%d2 4010497e: 1002 moveb %d2,%d0 40104980: 2200 movel %d0,%d1 40104982: 5282 addql #1,%d2 40104984: e588 lsll #2,%d0 40104986: e989 lsll #4,%d1 40104988: 9280 subl %d0,%d1 4010498a: 0681 4024 5722 addil #1076123426,%d1 40104990: 2f01 movel %d1,%sp@- 40104992: 4879 4024 56be pea 402456be <testCmd.4546> 40104998: 4eb9 4015 04e0 jsr 401504e0 <memcpy> ;========================== if (testListPtr->numParams == testCmd.numParams) 401049dc: 4281 clrl %d1 401049de: 4280 clrl %d0 401049e0: 3228 0002 movew %a0@(2),%d1 401049e4: 3039 4024 56c0 movew 402456c0 <testCmd.4546+0x2>,%d0 401049ea: b081 cmpl %d1,%d0 401049ec: 660a bnes 401049f8 <HsvHwTest+0xb8>
This also shows why it is a very good idea to use a compiler to generate your code. It knows about this stuff.
If you're trying to convert binary to decimal, then you should check the REMS.L and REMU.L instructions. Just keep dividing the same number by 10 and print the REMAINDER until the dividend is zero
Tom