Commit 2c11c712 by Tom Wood

(best_from_align): Add a target processor dimension for -m88000, -m88110, and -m88100.

(best_from_align): Add a target processor dimension for
	-m88000, -m88110, and -m88100.
	(expand_block_move): Choose method and limits based on -m88xxx option.
	(block_move_no_loop): Extend to allow DImode.
(output_call): Use different syntax for GAS.

From-SVN: r2355
parent eb829545
...@@ -21,6 +21,7 @@ along with GNU CC; see the file COPYING. If not, write to ...@@ -21,6 +21,7 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
...@@ -46,7 +47,7 @@ extern char *ctime (); ...@@ -46,7 +47,7 @@ extern char *ctime ();
extern int flag_traditional; extern int flag_traditional;
extern FILE *asm_out_file; extern FILE *asm_out_file;
static char out_sccs_id[] = "@(#)m88k.c 2.2.12.1 09/12/92 07:06:48"; static char out_sccs_id[] = "@(#)m88k.c 2.2.13.1 10/07/92 06:31:13";
static char tm_sccs_id [] = TM_SCCS_ID; static char tm_sccs_id [] = TM_SCCS_ID;
char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
...@@ -369,22 +370,57 @@ legitimize_address (pic, orig, reg) ...@@ -369,22 +370,57 @@ legitimize_address (pic, orig, reg)
#define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */ #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
#define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
#define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */ #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
#define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
#define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
#define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11, #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
__movstrSI46x46 .. __movstrSI46x10, __movstrSI46x46 .. __movstrSI46x10,
__movstrSI45x45 .. __movstrSI45x9 */ __movstrSI45x45 .. __movstrSI45x9 */
#define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
__movstrDI46x46 .. __movstrDI46x22,
/* Break even points where memcpy will do just as well. */ __movstrDI45x45 .. __movstrDI45x21,
#define MOVSTR_QI_LIMIT 13 __movstrDI44x44 .. __movstrDI44x20,
#define MOVSTR_HI_LIMIT 38 __movstrDI43x43 .. __movstrDI43x19,
#define MOVSTR_SI_LIMIT MOVSTR_SI __movstrDI42x42 .. __movstrDI42x18,
__movstrDI41x41 .. __movstrDI41x17 */
static enum machine_mode mode_from_bytes[] =
{VOIDmode, QImode, HImode, VOIDmode, SImode}; /* Limits for using the non-looping movstr functions. For the m88100
static int max_from_bytes[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI}; processor, we assume the source and destination are word aligned.
static int all_from_bytes[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI}; The QImode and HImode limits are the break even points where memcpy
static int best_from_bytes[] = does just as well and beyond which memcpy does better. For the
{0, MOVSTR_QI_LIMIT, MOVSTR_HI_LIMIT, 0, MOVSTR_SI_LIMIT}; m88110, we tend to assume double word alignment, but also analyze
the word aligned cases. The analysis is complicated because memcpy
may use the cache control instructions for better performance. */
#define MOVSTR_QI_LIMIT_88100 13
#define MOVSTR_HI_LIMIT_88100 38
#define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
#define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
#define MOVSTR_QI_LIMIT_88000 16
#define MOVSTR_HI_LIMIT_88000 38
#define MOVSTR_SI_LIMIT_88000 72
#define MOVSTR_DI_LIMIT_88000 72
#define MOVSTR_QI_LIMIT_88110 16
#define MOVSTR_HI_LIMIT_88110 38
#define MOVSTR_SI_LIMIT_88110 72
#define MOVSTR_DI_LIMIT_88110 72
static enum machine_mode mode_from_align[] =
{VOIDmode, QImode, HImode, VOIDmode, SImode,
VOIDmode, VOIDmode, VOIDmode, DImode};
static int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
0, 0, 0, MOVSTR_DI};
static int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI,
0, 0, 0, MOVSTR_ODD_DI};
static int best_from_align[3][9] =
{0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
0, 0, 0, MOVSTR_DI_LIMIT_88100,
0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
0, 0, 0, MOVSTR_DI_LIMIT_88110,
0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
0, 0, 0, MOVSTR_DI_LIMIT_88000};
static void block_move_loop (); static void block_move_loop ();
static void block_move_no_loop (); static void block_move_no_loop ();
...@@ -406,12 +442,17 @@ expand_block_move (dest_mem, src_mem, operands) ...@@ -406,12 +442,17 @@ expand_block_move (dest_mem, src_mem, operands)
int align = INTVAL (operands[3]); int align = INTVAL (operands[3]);
int constp = (GET_CODE (operands[2]) == CONST_INT); int constp = (GET_CODE (operands[2]) == CONST_INT);
int bytes = (constp ? INTVAL (operands[2]) : 0); int bytes = (constp ? INTVAL (operands[2]) : 0);
int target = (int) m88k_cpu;
assert (CPU_M88100 == 0);
assert (CPU_M88110 == 1);
assert (CPU_M88000 == 2);
if (constp && bytes <= 0) if (constp && bytes <= 0)
return; return;
/* Determine machine mode to do move with. */ /* Determine machine mode to do move with. */
if (align > 4) if (align > 4 && !TARGET_88110)
align = 4; align = 4;
else if (align <= 0 || align == 3) else if (align <= 0 || align == 3)
abort (); /* block move invalid alignment. */ abort (); /* block move invalid alignment. */
...@@ -420,11 +461,11 @@ expand_block_move (dest_mem, src_mem, operands) ...@@ -420,11 +461,11 @@ expand_block_move (dest_mem, src_mem, operands)
block_move_sequence (operands[0], dest_mem, operands[1], src_mem, block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
bytes, align, 0); bytes, align, 0);
else if (constp && bytes <= best_from_bytes[align]) else if (constp && bytes <= best_from_align[target][align])
block_move_no_loop (operands[0], dest_mem, operands[1], src_mem, block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
bytes, align); bytes, align);
else if (constp && align == 4) else if (constp && align == 4 && TARGET_88100)
block_move_loop (operands[0], dest_mem, operands[1], src_mem, block_move_loop (operands[0], dest_mem, operands[1], src_mem,
bytes, align); bytes, align);
...@@ -488,7 +529,7 @@ block_move_loop (dest, dest_mem, src, src_mem, size, align) ...@@ -488,7 +529,7 @@ block_move_loop (dest, dest_mem, src, src_mem, size, align)
remainder = size - count * MOVSTR_LOOP - units * align; remainder = size - count * MOVSTR_LOOP - units * align;
mode = mode_from_bytes[align]; mode = mode_from_align[align];
sprintf (entry, "__movstr%s%dn%d", sprintf (entry, "__movstr%s%dn%d",
GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
entry_name = get_identifier (entry); entry_name = get_identifier (entry);
...@@ -527,24 +568,24 @@ block_move_no_loop (dest, dest_mem, src, src_mem, size, align) ...@@ -527,24 +568,24 @@ block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
int size; int size;
int align; int align;
{ {
enum machine_mode mode = mode_from_bytes[align]; enum machine_mode mode = mode_from_align[align];
int units = size / align; int units = size / align;
int remainder = size - units * align; int remainder = size - units * align;
int most; int most;
int evenp; int value_reg;
rtx offset_rtx; rtx offset_rtx;
rtx value_rtx; rtx value_rtx;
char entry[30]; char entry[30];
tree entry_name; tree entry_name;
if (remainder && size <= all_from_bytes[align]) if (remainder && size <= all_from_align[align])
{ {
most = all_from_bytes[align] - (align - remainder); most = all_from_align[align] - (align - remainder);
remainder = 0; remainder = 0;
} }
else else
{ {
most = max_from_bytes[align]; most = max_from_align[align];
} }
sprintf (entry, "__movstr%s%dx%d", sprintf (entry, "__movstr%s%dx%d",
...@@ -561,12 +602,13 @@ block_move_no_loop (dest, dest_mem, src, src_mem, size, align) ...@@ -561,12 +602,13 @@ block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem); MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
evenp = ((most - (size - remainder)) / align) & 1; value_reg = ((((most - (size - remainder)) / align) & 1) == 0
? (align == 8 ? 6 : 5) : 4);
emit_insn (gen_call_block_move emit_insn (gen_call_block_move
(gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
dest, src, offset_rtx, value_rtx, dest, src, offset_rtx, value_rtx,
gen_rtx (REG, GET_MODE (value_rtx), (evenp ? 4 : 5)))); gen_rtx (REG, GET_MODE (value_rtx), value_reg)));
if (remainder) if (remainder)
block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem, block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
...@@ -601,7 +643,7 @@ block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset) ...@@ -601,7 +643,7 @@ block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
/* Establish parameters for the first load and for the second load if /* Establish parameters for the first load and for the second load if
it is known to be the same mode as the first. */ it is known to be the same mode as the first. */
amount[0] = amount[1] = align; amount[0] = amount[1] = align;
mode[0] = mode_from_bytes[align]; mode[0] = mode_from_align[align];
temp[0] = gen_reg_rtx (mode[0]); temp[0] = gen_reg_rtx (mode[0]);
if (size >= 2 * align) if (size >= 2 * align)
{ {
...@@ -620,8 +662,8 @@ block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset) ...@@ -620,8 +662,8 @@ block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
/* Change modes as the sequence tails off. */ /* Change modes as the sequence tails off. */
if (size < amount[next]) if (size < amount[next])
{ {
amount[next] = (size >= 2 ? 2 : 1); amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
mode[next] = mode_from_bytes[amount[next]]; mode[next] = mode_from_align[amount[next]];
temp[next] = gen_reg_rtx (mode[next]); temp[next] = gen_reg_rtx (mode[next]);
} }
size -= amount[next]; size -= amount[next];
...@@ -794,6 +836,12 @@ output_call (operands, addr) ...@@ -794,6 +836,12 @@ output_call (operands, addr)
: (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")), : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
operands); operands);
#ifdef USE_GAS
last = (delta < 0
? "subu %#r1,%#r1,.-%l0+4"
: "addu %#r1,%#r1,%l0-.-4");
operands[0] = dest;
#else
operands[0] = gen_label_rtx (); operands[0] = gen_label_rtx ();
operands[1] = gen_label_rtx (); operands[1] = gen_label_rtx ();
if (delta < 0) if (delta < 0)
...@@ -813,6 +861,7 @@ output_call (operands, addr) ...@@ -813,6 +861,7 @@ output_call (operands, addr)
sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name); sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name);
sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high); sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high);
sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low); sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low);
#endif /* Don't USE_GAS */
return last; return last;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment