DIVU/DIVS Forcing a Reset

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

DIVU/DIVS Forcing a Reset

2,814 Views
grt951
Contributor II

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)

Labels (1)
0 Kudos
12 Replies

1,561 Views
kef
Specialist I

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.

0 Kudos

1,561 Views
TomE
Specialist II

> 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

 

 

 

 

 

0 Kudos

1,561 Views
kef
Specialist I
  • 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.

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.

 

 

  • 1.3 V1 ColdFire Core
  • This CPU implements ColdFire instruction set architecture revision C (ISA_C) with a reduced
  •  programming model: No ardware support for MAC/EMAC and DIV instructions.

Indeed there are V1's with MAC

0 Kudos

1,561 Views
TomE
Specialist II

> 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

 

0 Kudos

1,561 Views
kef
Specialist I
  • > 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.

 

V1CFWP.pdf  "Version 1 ColdFire® White Paper", Rev 0 07/2006, on page 6 has these lines:

 

  • Additionally, the V1 core includes design parameters to easily include/exclude various “execute engines”
  • associated with specific instructions. These optional execute engines include an integer divider (DIV),
  •  {E}MAC multiply-accumulate engines, and a cryptographic acceleration unit (CAU).

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

0 Kudos

1,561 Views
TomE
Specialist II

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

 

0 Kudos

1,561 Views
TomE
Specialist II

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

0 Kudos

1,561 Views
Mudwog
Contributor I

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

 

0 Kudos

1,561 Views
kef
Specialist I

It is not that bad with availability of FF1 instruction, which allows to determine required iterations count (FF1(numerator)-FF1(denominator)) or quickly skip past leading zeros.

0 Kudos

1,561 Views
Mudwog
Contributor I

COOL!

I was not aware of the FF1 instruction before.   This will come in handy the next time I work on a V1.

 

Thanks,

Mudwog

0 Kudos

1,561 Views
grt951
Contributor II

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

0 Kudos

1,561 Views
TomE
Specialist II

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&gt
;========================== 
                               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

0 Kudos