m68k fmovem

kevin diggs diggskevin38@gmail.com
Tue Mar 1 08:20:00 GMT 2011


Hi,

Adding some debug statements to tc-m68k.c reveals that (at least in
2.16.1) the statement:

fmovem.l %fpcr,%d0

tries the operand pattern "IiL8~s" first (from m68k-opc.c). This fails
to match because the '~' operand type does not include register
direct. Unfortunately, the 'L' operand type changes the mode
(opP->mode=REGLST) at line 1745.

The operand pattern "Iis8%s" is tried next. This would have matched
... except the 's' operand type wants the mode to be CONTROL. But this
got mucked up in the previous operand pattern check. If I comment out
the losing++; at line 1817 then:

unsigned int f(unsigned int *save)
{
unsigned int fpctrreg;

        asm volatile("fmovem.l %%fpcr,%0\n"
                :"=d"(fpctrreg)
        );

        asm volatile("fmoveml %%fpcr/%%fpsr,%0@\n"
                :
                :"a"(save)
        );

        return fpctrreg;
}

will assemble the first fmovem.l to 'f200 b000' which I think is
correct (and also matches what a similar fmove produces).

A quick check of the latest tc-m68k.c and m68k-opc.c (via cvsweb)
would seem to indicate that this should issue should still exist
(unless something has changed to alter the order that the operand
patterns are tried).

Any tips/pointers on how to fix this would be appreciated.

Can we just change the order of the first two fmoveml patterns in
m68k_op.c? Will that change the order that they are tried?

I am a little afraid of trashing some other instruction.

Thanks!

kevin

--- gas/config/tc-m68k-old_c    Tue Mar 22 07:31:48 2005
+++ gas/config/tc-m68k-new_c    Thu Dec 31 17:51:35 1903
@@ -1143,6 +1143,9 @@
       return;
     }

+  fprintf(stderr,__FILE__"`%s()-%d:  mnemonic=%s, opcode struct=%p, opcode="
+    "%lx\n",__func__,__LINE__,instring,opcode,opcode->m_opcode);
+
   /* Found a legitimate opcode, start matching operands.  */
   while (*p == ' ')
     ++p;
@@ -1213,10 +1216,16 @@
        ++losing;
       else
        {
+         fprintf(stderr,__FILE__"`%s()-%d:  operand match string \"%s\"\n",
+           __func__,__LINE__,opcode->m_operands);
+
          for (s = opcode->m_operands, opP = &the_ins.operands[0];
               *s && !losing;
               s += 2, opP++)
            {
+             fprintf(stderr,__FILE__"`%s()-%d:  matching operand %c%c\n",
+               __func__,__LINE__,*s,s[1]);
+
              /* Warning: this switch is huge! */
              /* I've tried to organize the cases into this order:
                 non-alpha first, then alpha by letter.  Lower-case
@@ -1797,11 +1806,16 @@
                  break;

                case 's':
+                 fprintf(stderr,__FILE__"`%s()-%d:  mode=%d, CONTROL=%d, "
+                   "reg=%d, FPI=%d/FPS=%d/FPC=%d\n",
+                   __func__,__LINE__,opP->mode,CONTROL,opP->reg,FPI,FPS,FPC);
+
                  if (opP->mode != CONTROL
                      || ! (opP->reg == FPI
                            || opP->reg == FPS
                            || opP->reg == FPC))
-                   losing++;
+//                 losing++;
+                   ;
                  break;

                case 'S':



More information about the Binutils mailing list