Fixes to local label stuff
authorceriel <none@none>
Mon, 28 Oct 1991 17:59:57 +0000 (17:59 +0000)
committerceriel <none@none>
Mon, 28 Oct 1991 17:59:57 +0000 (17:59 +0000)
mach/m68020/ce/EM_table
mach/m68020/ce/as.c
mach/m68020/ce/as.h

index af950b9..e5d8c74 100644 (file)
@@ -786,8 +786,9 @@ C_dup
        $1 == 8         ==>     "move.l (4, sp), -(sp)";
                                "move.l (4, sp), -(sp)".
        default         ==>     "move.l #$1/4, d0";
+                               "lea ($1, sp), a0";
                                "1:";
-                               "move.l ($1-4, sp), -(sp)";
+                               "move.l -(a0), -(sp)";
                                "sub.l #1, d0";
                                "bne 1b".
 
index 177c758..e9493b8 100644 (file)
@@ -113,8 +113,15 @@ register struct t_operand *op;
                                for ( ; *str == ' '; str++)
                                        ;
                                op->reg = reg_val( str);
-                               if ( *(str+2) == ')')           /*  (4, a0)  */
-                                       op->type = IS_IND_REG_DISPL;
+                               if ( *(str+2) == ')') {         /*  (4, a0)  */
+                                       int i = atoi(op->expr);
+                                       if ((*(op->expr) == '-' ||
+                                            isdigit(*(op->expr))) &&
+                                           i <= 32767 && i >= -32768) {
+                                               op->type = IS_IND_REG_DISPL;
+                                       }
+                                       else    op->type = IS_IND_REG_EDISPL;
+                               }
                                else {                   /*  (0, sp, d0.l*1)  */
                                        op->type = IS_3_OPS;
                                        for ( str++; *++str != ',';)
@@ -218,6 +225,8 @@ register struct t_operand *eaddr;
 
          case IS_IND_REG_DISPL : return( 0x28 | eaddr->reg);
 
+         case IS_IND_REG_EDISPL: return( 0x30 | eaddr->reg);
+
          case IS_GLOB_LBL      : return( 0x39);
 
          case IS_3_OPS         : if ( isdigit( *(eaddr->expr)) &&
@@ -231,7 +240,7 @@ register struct t_operand *eaddr;
          case IS_IMMEDIATE     : return( 0x3c);
 
          default               : fprintf( stderr,
-                                          "mode_reg(), verkeerde operand %d\n",
+                                          "mode_reg(), wrong operand %d\n",
                                           eaddr->type);
                                  abort();
                                  break;
@@ -266,6 +275,10 @@ register struct t_operand *eaddr;
          case IS_IND_REG_DISPL : @text2( %$( eaddr->expr));
                                  break;
 
+         case IS_IND_REG_EDISPL :@text2(0x0170);
+                                 @text4( %$( eaddr->expr));
+                                 break;
+
          case IS_GLOB_LBL      : @reloc4( %$(eaddr->lbl),
                                           %$(eaddr->expr),
                                           ABSOLUTE);
@@ -313,11 +326,18 @@ struct t_operand *eaddr;
 }
 
 
+/* The attempts to optimize the instruction size when it cannot be done
+   at code-expander generation time is actually quite dangerous, because
+   it may not happen between references to and definitions of (corresponding)
+   local labels. The reason for this is that these offsets are computed
+   at code-expander generation time. Unfortunately, no warning is given,
+   so this has to be checked by hand.
+*/
 code_instr( opcode, field1, field2, eaddr)
 int opcode, field1, field2;
 struct t_operand *eaddr;
 {
-       if (eaddr->type == IS_IND_REG_DISPL) {
+       if (eaddr->type == IS_IND_REG_EDISPL) {
                @__instr_code(%d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) |
                                ((field2 & 0x7) << 6)),
                              %d(eaddr->reg), %$(eaddr->expr));
@@ -333,8 +353,8 @@ code_move( size, src, dst)
 int size;
 struct t_operand *src, *dst;
 {
-       if (src->type == IS_IND_REG_DISPL) {
-               if (dst->type == IS_IND_REG_DISPL) {
+       if (src->type == IS_IND_REG_EDISPL) {
+               if (dst->type == IS_IND_REG_EDISPL) {
                        @__moveXX(%d( ((size & 0x3) << 12)),
                                 %d(dst->reg), %$(dst->expr),
                                 %d(src->reg), %$(src->expr));
@@ -344,7 +364,7 @@ struct t_operand *src, *dst;
                                 %d(src->reg), %$(src->expr));
                }
        }
-       else if (dst->type == IS_IND_REG_DISPL) {
+       else if (dst->type == IS_IND_REG_EDISPL) {
                @__move_X(%d( ((size & 0x3) << 12) | (mode_reg( src) & 0x3f)),
                         %d(dst->reg), %$(dst->expr));
        }
index 03c00d3..0a296e7 100644 (file)
@@ -21,6 +21,7 @@ struct t_operand {
 #define IS_LOC_LBL             12
 #define IS_IND_REG             13
 #define IS_IND_REG_DISPL       14
+#define IS_IND_REG_EDISPL      15
 
 #define QUICK( op)     (op->type == IS_QUICK)
 #define IMMEDIATE( op) (op->type == IS_IMMEDIATE)