From 2c11c7126f11f1b2aba6d0b1e4e9561fb82479ed Mon Sep 17 00:00:00 2001 From: Tom Wood Date: Wed, 7 Oct 1992 20:19:22 +0000 Subject: [PATCH] (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 --- gcc/config/m88k/m88k.c | 105 ++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c index 04c671fb7f1..46814ef32c5 100644 --- a/gcc/config/m88k/m88k.c +++ b/gcc/config/m88k/m88k.c @@ -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. */ #include +#include #include #include #include @@ -46,7 +47,7 @@ extern char *ctime (); extern int flag_traditional; 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; char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ @@ -369,22 +370,57 @@ legitimize_address (pic, orig, reg) #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */ #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ #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, __movstrSI46x46 .. __movstrSI46x10, __movstrSI45x45 .. __movstrSI45x9 */ -#define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ - -/* Break even points where memcpy will do just as well. */ -#define MOVSTR_QI_LIMIT 13 -#define MOVSTR_HI_LIMIT 38 -#define MOVSTR_SI_LIMIT MOVSTR_SI - -static enum machine_mode mode_from_bytes[] = - {VOIDmode, QImode, HImode, VOIDmode, SImode}; -static int max_from_bytes[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI}; -static int all_from_bytes[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI}; -static int best_from_bytes[] = - {0, MOVSTR_QI_LIMIT, MOVSTR_HI_LIMIT, 0, MOVSTR_SI_LIMIT}; +#define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23, + __movstrDI46x46 .. __movstrDI46x22, + __movstrDI45x45 .. __movstrDI45x21, + __movstrDI44x44 .. __movstrDI44x20, + __movstrDI43x43 .. __movstrDI43x19, + __movstrDI42x42 .. __movstrDI42x18, + __movstrDI41x41 .. __movstrDI41x17 */ + +/* Limits for using the non-looping movstr functions. For the m88100 + processor, we assume the source and destination are word aligned. + The QImode and HImode limits are the break even points where memcpy + does just as well and beyond which memcpy does better. For the + 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_no_loop (); @@ -406,12 +442,17 @@ expand_block_move (dest_mem, src_mem, operands) int align = INTVAL (operands[3]); int constp = (GET_CODE (operands[2]) == CONST_INT); 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) return; /* Determine machine mode to do move with. */ - if (align > 4) + if (align > 4 && !TARGET_88110) align = 4; else if (align <= 0 || align == 3) abort (); /* block move invalid alignment. */ @@ -420,11 +461,11 @@ expand_block_move (dest_mem, src_mem, operands) block_move_sequence (operands[0], dest_mem, operands[1], src_mem, 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, 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, bytes, align); @@ -488,7 +529,7 @@ block_move_loop (dest, dest_mem, src, src_mem, size, align) remainder = size - count * MOVSTR_LOOP - units * align; - mode = mode_from_bytes[align]; + mode = mode_from_align[align]; sprintf (entry, "__movstr%s%dn%d", GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); entry_name = get_identifier (entry); @@ -527,24 +568,24 @@ block_move_no_loop (dest, dest_mem, src, src_mem, size, align) int size; int align; { - enum machine_mode mode = mode_from_bytes[align]; + enum machine_mode mode = mode_from_align[align]; int units = size / align; int remainder = size - units * align; int most; - int evenp; + int value_reg; rtx offset_rtx; rtx value_rtx; char entry[30]; 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; } else { - most = max_from_bytes[align]; + most = max_from_align[align]; } sprintf (entry, "__movstr%s%dx%d", @@ -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_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 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), 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) 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) /* Establish parameters for the first load and for the second load if it is known to be the same mode as the first. */ amount[0] = amount[1] = align; - mode[0] = mode_from_bytes[align]; + mode[0] = mode_from_align[align]; temp[0] = gen_reg_rtx (mode[0]); if (size >= 2 * align) { @@ -620,8 +662,8 @@ block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset) /* Change modes as the sequence tails off. */ if (size < amount[next]) { - amount[next] = (size >= 2 ? 2 : 1); - mode[next] = mode_from_bytes[amount[next]]; + amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1)); + mode[next] = mode_from_align[amount[next]]; temp[next] = gen_reg_rtx (mode[next]); } size -= amount[next]; @@ -794,6 +836,12 @@ output_call (operands, addr) : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")), 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[1] = gen_label_rtx (); if (delta < 0) @@ -813,6 +861,7 @@ output_call (operands, addr) sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name); sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high); sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low); +#endif /* Don't USE_GAS */ return last; } -- 2.30.2