68040 takes the wrong If Ifsese branch

Any good 68k build programmers out there? I use the commercial Green Hills compiler for Motorola 68040, and I see very strange behavior in the code. Sometimes the code does an if / else comparison and accepts the wrong branch. For example:

float a = 1, b = 2; if (a < b) do c; else do d; 

The code will sometimes be d !? I found that when this error occurs, there is always one particular ISR that interrupts the comparison. I looked at the generated build for ISR and saw a few things that didn't make sense to me. At first it looks like floating point status registers, FPSR, FPCR and FPIAR, are not stored in the ISR. This explains why if / elses accept the wrong branch. The FPSR register is used to determine the result of the comparison, and if this register is overwritten in the ISR, then the branch may take the wrong path. The following is the input and output assembly generated by the compiler:

 isr_function: FSAVE -(%SP) LINK %A6,#-192 MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) ; isr code ... FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 UNLK %A6 FRESTORE (%SP)+ RTE 

I looked through the programmers reference manual and I can’t find anything that says FSAVE or FMOVEM saves FP status registers. In fact, I saw one comment that suggests that this is not the case: "FSAVE does not save the model registers of the programmer of the floating point module, it only saves the user invisible part of the machine." So I added some of my own assemblies to save registers at the beginning of the ISR and restore them at the end, and this greatly improved performance, but I still see some problems. The following are the additions that I made; backup variables are typed as unsigned long in the C code:

 isr_function: FSAVE -(%SP) LINK %A6,#-192 MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) FMOVE %FPIAR,fpiar_backup FMOVE %FPSR,fpsr_backup FMOVE %FPCR,fpcr_backup ; isr code ... FMOVE fpiar_backup,%FPIAR FMOVE fpsr_backup,%FPSR FMOVE fpcr_backup,%FPCR FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 UNLK %A6 FRESTORE (%SP)+ RTE 

It was hard for me to believe that the compiler had an error without preserving the registers. So I started looking at the FPx and Dx values ​​to make sure they are restored to the correct value, and it looks like they are not. However, I am not 100% sure that I am not changing the assembly code with my changes. Below is the code I added to save the registers; debug variables print as unsigned longs:

 isr_function: FMOVE %FP0,debug3 FMOVE %FP1,debug5 FMOVE %FP2,debug7 FMOVE %FP3,debug9 FMOVE %FP4,debug11 FMOVE %FP5,debug13 FMOVE %FP6,debug15 FMOVE %FP7,debug17 FMOVE %FPCR,debug19 FMOVE %FPIAR,debug23 FMOVE %FPSR,debug25 FSAVE -(%SP) LINK %A6,#-192 MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) ; isr code ... FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 UNLK %A6 FMOVE %FP0,debug4 FMOVE %FP1,debug6 FMOVE %FP2,debug8 FMOVE %FP3,debug10 FMOVE %FP4,debug12 FMOVE %FP5,debug14 FMOVE %FP6,debug16 FMOVE %FP7,debug18 FMOVE %FPCR,debug20 FMOVE %FPIAR,debug24 FMOVE %FPSR,debug26 FRESTORE (%SP)+ RTE 

In short, my questions are:

1) there is a problem with the generated assembly in that it does not save the FPSR, FPCR and FPIAR registers, but

2) Do I save register values ​​correctly when entering and exiting ISR?

It would be great if I had a different compiler for comparison. Unfortunately, I cannot connect the debugger to the code. I have a lot of experience in C / C ++ / C # / Java / Python / PHP / etc., But I'm far from a build specialist.

Any ideas appreciated!

+8
assembly compiler-construction isr 68000
source share
2 answers

I have not done 68K programming since 68020, but I will try to move on to the corresponding gray question and / or web resources :-)

Answering your specific questions:

Is there a problem with the generated assembly that it does not save the FPSR, FPCR, and FPIAR registers?

I would say yes, but only if there is something in the ISR that affects them. Although this seems unlikely (ISRs should be fast, so I would not expect them to be reset using floating point things), reasonableness seems to suggest that a normal operation only allows you to save everything no matter what the code can change it.

Having said that, I'm not sure how you compile ISR (or even your code at all). Perhaps a special flag is needed to force the compiler to generate more code to save other things.

Do I save register values ​​correctly when entering and exiting ISR?

Again, it depends. This looks good, but I would be a little worried about using specific memory locations, such as fpiar_backup or debug26 , if you are not sure if the ISR itself is not subject to another interrupt.

If interrupts are disabled during ISR processing, you are probably fine.

In addition, it depends on what the ISR serves. The docs seem to indicate that all ISRs serving floating point problems should always do fsave first.

It would be helpful if you reset the values ​​of these debugX locations debugX that you can see what values ​​differ between the input and output of the ISR. And make sure they are the right size. And be careful that you do not look at them in the middle of the ISR, where they will almost certainly be different.

+2
source share

For future reference, the problem is really related to the fact that the compiler does not save the value of the floating point status registers. I contacted Green Hills, and according to them, this is not a mistake, and that saving the value of registrars is the responsibility of the programmer. Which is strange for me, because the compiler saves all other internal registers, including the internal state of the FPU, why stop with state registers?

In short, saving the value of the FPSR and FPIAR that is included in the system and when exiting the ISR will fix the problem. The following should do the trick:

 void isr(void) { // variable declarations ... __asm(" FMOVE %FPIAR,-(%SP)"); __asm(" FMOVE %FPSR,-(%SP)"); // some code ... __asm(" FMOVE (%SP)+,%FPSR"); __asm(" FMOVE (%SP)+,%FPIAR"); } 
+2
source share

All Articles