From dd99f952d5c67568dd4fb29e2859d73967987b94 Mon Sep 17 00:00:00 2001 From: ceriel Date: Mon, 28 Oct 1991 17:59:57 +0000 Subject: [PATCH] Fixes to local label stuff --- mach/m68020/ce/EM_table | 3 ++- mach/m68020/ce/as.c | 34 +++++++++++++++++++++++++++------- mach/m68020/ce/as.h | 1 + 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/mach/m68020/ce/EM_table b/mach/m68020/ce/EM_table index af950b9f6..e5d8c74e8 100644 --- a/mach/m68020/ce/EM_table +++ b/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". diff --git a/mach/m68020/ce/as.c b/mach/m68020/ce/as.c index 177c75840..e9493b800 100644 --- a/mach/m68020/ce/as.c +++ b/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)); } diff --git a/mach/m68020/ce/as.h b/mach/m68020/ce/as.h index 03c00d36f..0a296e7bf 100644 --- a/mach/m68020/ce/as.h +++ b/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)