瀏覽代碼

Fixes to local label stuff

ceriel 33 年之前
父節點
當前提交
c5c1b74381
共有 3 個文件被更改,包括 30 次插入8 次删除
  1. 2 1
      mach/m68020/ce/EM_table
  2. 27 7
      mach/m68020/ce/as.c
  3. 1 0
      mach/m68020/ce/as.h

+ 2 - 1
mach/m68020/ce/EM_table

@@ -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".
 

+ 27 - 7
mach/m68020/ce/as.c

@@ -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));
 	}

+ 1 - 0
mach/m68020/ce/as.h

@@ -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)