OpenCores
no use no use 1/2 Next Last
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 9, 2004
Not available!
Hi,

This little patch does some house cleaning plus that it splits the sfCC+bX
sequences into sfCC/bX (there is need need for then to be located next to
each other.)

I would be greatfull if someone could take a quick look at it, and then
commit it. (To let ATS build Linux with it and try it out in the simulator.)

Special interest is the changed to or32.md -- I suppose.

If something goes horrible wrong, it can always be reverted.


Index: or32-protos.h
===================================================================
RCS file: /home/oc/cvs/or1k/gcc-3.2.3/gcc/config/or32/or32-protos.h,v
retrieving revision 1.1.1.1
diff -u -p -u -r1.1.1.1 or32-protos.h
--- or32-protos.h 14 Feb 2004 17:48:11 -0000 1.1.1.1
+++ or32-protos.h 9 Mar 2004 19:58:48 -0000
@@ -22,11 +22,9 @@ Boston, MA 02111-1307, USA. */
#ifdef TREE_CODE
#endif /* TREE_CODE */

-extern void print_operand PARAMS ((FILE *, rtx, char));
+extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, register rtx));
-extern void gen_cond_branch PARAMS ((rtx [], enum rtx_code));
-
-extern rtx or1k_cmp_op0, or1k_cmp_op1;
+extern const char *or1k_output_move_double PARAMS ((rtx *operands));

#endif /* RTX_CODE */

Index: or32.c
===================================================================
RCS file: /home/oc/cvs/or1k/gcc-3.2.3/gcc/config/or32/or32.c,v
retrieving revision 1.1.1.1
diff -u -p -u -r1.1.1.1 or32.c
--- or32.c 14 Feb 2004 17:48:12 -0000 1.1.1.1
+++ or32.c 9 Mar 2004 19:58:48 -0000
@@ -38,16 +38,11 @@ Boston, MA 02111-1307, USA. */
of l.jr instruction in epilogue. */
#define NOP_DELAY_SLOT_FILL 0

-/* for holding comparison operands. */
-rtx or1k_cmp_op0, or1k_cmp_op1;
-enum machine_mode or1k_cmp_mode = SImode;
-
/* used in function prologue/epilogue generation */
extern int leaf_function;

/* Local function prototypes */
static char *get_function_name PARAMS ((void));
-static int log_of_two PARAMS ((int));
static void or32_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void or32_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));

@@ -59,7 +54,6 @@ static void or32_output_function_epilogu
/* Initialize the GCC target structure. */
struct gcc_target targetm = TARGET_INITIALIZER;

-
int
print_operand_punct_valid_p (code)
int code;
@@ -87,7 +81,8 @@ print_operand_address (file, addr)
case MEM:
if (GET_CODE (XEXP (addr, 0)) == REG)
fprintf (file, "%s", reg_names[REGNO (addr)]);
- else abort();
+ else
+ abort();
break;

case REG:
@@ -119,408 +114,382 @@ print_operand_address (file, addr)
}

static char *
-get_function_name ()
+get_function_name (void)
{
- char *kind = (char *)"function";
- if (current_function_decl != 0
- && TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
- kind = (char *)"method";
-
if (current_function_decl == NULL)
- {
- return (char *)"top level";
- }
- else
- {
- return (char *)(*decl_printable_name) (current_function_decl, &kind);
- }
+ return (char *)"top level";
+
+ return (char *)(*decl_printable_name) (current_function_decl, 2);
}

-/*
- * operands[0] will be the branch target.
- * test will be the comparison type.
- * or1k_cmp_mode is SImode
- * or1k_cmp_op0 and or1k_cmp_op1 are the things to be
- * compared.
- *
- * This routine has to generate a compare and a branch rtx.
- *
- */
-void
-gen_cond_branch(operands, test)
- rtx operands[];
- enum rtx_code test;
+int
+sym_ref_mem_operand(op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
- rtx tmp;
-
- switch(or1k_cmp_mode)
+ if (GET_CODE(op) == MEM)
{
- case SImode:
- /* generate a sfXX instruction. */
-
- /* check if operand 1 is an integer that is too big;
- move it into a register if it is. */
-
-#if 1 /* Set to 0 if sfXXi are not available (also cmpsi should compare only registers (no imms)) */
- if(GET_CODE(or1k_cmp_op1) == CONST_INT)
- {
-#if 0
- int c = INTVAL(or1k_cmp_op1);
- if (!(CONST_OK_FOR_LETTER_P(c, 'I')))
- debug_rtx(or1k_cmp_op1);
-#endif
- or1k_cmp_op1 = force_reg (SImode, or1k_cmp_op1);
- }
-#endif
- else if(GET_CODE(or1k_cmp_op1) == SYMBOL_REF)
- {
- or1k_cmp_op1 = force_reg(SImode, or1k_cmp_op1);
- }
-
- /* emit the set instruction. */
- tmp = gen_rtx(SET, VOIDmode, cc0_rtx,
- gen_rtx(test, SImode,
- or1k_cmp_op0, or1k_cmp_op1));
- emit_insn(tmp);
-
- /* emit the branch instruction. */
- tmp = gen_rtx(SET, VOIDmode,
- pc_rtx,
- gen_rtx(IF_THEN_ELSE, VOIDmode,
- gen_rtx(NE, VOIDmode, const0_rtx,
- cc0_rtx),
- gen_rtx_LABEL_REF (VOIDmode,operands[0]),
- pc_rtx));
- emit_jump_insn(tmp);
- break;
- default:
- break;
+ rtx t1 = XEXP(op, 0);
+ if (GET_CODE(t1) == SYMBOL_REF)
+ return 1;
}
+ return 0;
}

-int
-sym_ref_mem_operand(op, mode)
- register rtx op;
- enum machine_mode mode;
+/* Calulcate and return stack size for current function. */
+static int
+calculate_stack_size (int vars, int *lr_save_area,
+ int *fp_save_area, int *gpr_save_area,
+ int *save_area)
{
- if(GET_CODE(op) == MEM) {
- rtx t1 = XEXP(op, 0);
- if (GET_CODE(t1) == SYMBOL_REF)
- return 1;
- }
+ int regno;

- return 0;
-}
+ *gpr_save_area = 0;
+ for (regno = 0; regno + {
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ *gpr_save_area += 4;
+ }

-/* Set up the stack and frame pointer (if desired) for the function. */
+ *lr_save_area = (!current_function_is_leaf
+ || regs_ever_live[LINK_REGNUM]) ? 4 : 0;
+ *fp_save_area = frame_pointer_needed ? 4 : 0;
+
+ *save_area = (OR1K_ALIGN (current_function_outgoing_args_size, 4)
+ + *lr_save_area + *fp_save_area);
+
+ return
+ (OR1K_ALIGN (current_function_outgoing_args_size,4)
+ + *lr_save_area + *fp_save_area + *gpr_save_area
+ + OR1K_ALIGN (vars, 4));
+}

+/* Set up the stack and frame pointer (if desired) for the
+ function. */
static void
-or32_output_function_prologue(file, vars)
- FILE *file;
- int vars;
+or32_output_function_prologue (file, vars)
+ FILE *file;
+ int vars;
{
- register int save_area;
- register int gpr_save_area = 0;
- register int lr_save_area;
- register int fp_save_area;
- register int stack_size;
- register int regno = 0;
+ int save_area;
+ int gpr_save_area;
+ int lr_save_area;
+ int fp_save_area;
+ int stack_size;
+ int regno;

- fprintf(file, "\n\t# ");
+ stack_size = calculate_stack_size
+ (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);

- for (regno = 0; regno - fprintf(file,"%i", regs_ever_live[regno]);
+ fprintf (file, "\n\t# gpr_save_area %d vars %d current_function_outgoing_args_size %d\n",
+ gpr_save_area, vars, current_function_outgoing_args_size);

- if (regs_ever_live[regno] && !call_used_regs[regno]) {
- gpr_save_area += 4;
- }
- }
+ if(stack_size >= 0x8000)
+ {
+ fprintf (file, "\tl.movhi \tr%d,hi(%d)\n", GP_ARG_RETURN,
+ stack_size);
+ fprintf (file, "\tl.ori \tr%d,r%d,lo(%d)\n", GP_ARG_RETURN,
+ GP_ARG_RETURN, stack_size);
+ fprintf (file, "\tl.sub \tr%d,r%d,r%d\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, GP_ARG_RETURN);
+ }
+ else if(stack_size > 0)
+ {
+ fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, - stack_size);
+ }

- lr_save_area = !current_function_is_leaf || regs_ever_live[LINK_REGNUM] ? 4 : 0;
- fp_save_area = frame_pointer_needed ? 4 : 0;
+ if (fp_save_area)
+ {
+ fprintf (file, "\tl.sw \t%d(r%d),r%d\n",
+ OR1K_ALIGN (current_function_outgoing_args_size, 4)
+ + lr_save_area,
+ STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM);
+ if(stack_size >= 0x8000)
+ fprintf (file, "\tl.add \tr%d,r%d,r%d\n", FRAME_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, GP_ARG_RETURN);
+ else
+ fprintf (file, "\tl.addi \tr%d,r%d,%d\n", FRAME_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, stack_size);
+ }

- stack_size = OR1K_ALIGN(current_function_outgoing_args_size,4) + lr_save_area + fp_save_area + gpr_save_area + OR1K_ALIGN(vars,4);
+ if (lr_save_area)
+ {
+ fprintf (file, "\tl.sw \t%d(r%d),r%d\n",
+ OR1K_ALIGN (current_function_outgoing_args_size, 4),
+ STACK_POINTER_REGNUM, LINK_REGNUM);
+ }

- fprintf(file, "\n\t# gpr_save_area %d vars %d current_function_outgoing_args_size %d\n", gpr_save_area, vars, current_function_outgoing_args_size);
+ save_area = (OR1K_ALIGN (current_function_outgoing_args_size, 4)
+ + lr_save_area + fp_save_area);

- if(stack_size >= 0x8000) {
- fprintf (file, "\tl.movhi \tr%d,hi(%d)\n", GP_ARG_RETURN, stack_size);
- fprintf (file, "\tl.ori \tr%d,r%d,lo(%d)\n", GP_ARG_RETURN, GP_ARG_RETURN, stack_size);
- fprintf (file, "\tl.sub \tr%d,r%d,r%d\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, GP_ARG_RETURN);
- }
- else if(stack_size > 0)
- fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, -stack_size);
-
- if (fp_save_area) {
- fprintf (file, "\tl.sw \t%d(r%d),r%d\n", OR1K_ALIGN(current_function_outgoing_args_size,4) + lr_save_area, STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM);
- if(stack_size >= 0x8000)
- fprintf (file, "\tl.add \tr%d,r%d,r%d\n", FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM, GP_ARG_RETURN);
- else
- fprintf (file, "\tl.addi \tr%d,r%d,%d\n", FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM, stack_size);
+ for (regno = 0; regno + {
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ fprintf (file, "\tl.sw \t%d(r%d),r%d\n", save_area,
+ STACK_POINTER_REGNUM, regno);
+ save_area += 4;
}
-
- if (lr_save_area)
- fprintf (file, "\tl.sw \t%d(r%d),r%d\n", OR1K_ALIGN(current_function_outgoing_args_size,4), STACK_POINTER_REGNUM, LINK_REGNUM);
-
- save_area = OR1K_ALIGN(current_function_outgoing_args_size,4) + lr_save_area + fp_save_area;
- for (regno = 0; regno - if (regs_ever_live[regno] && !call_used_regs[regno]) {
- fprintf (file, "\tl.sw \t%d(r%d),r%d\n", save_area, STACK_POINTER_REGNUM, regno);
- save_area += 4;
- }
+ }
}

/* Do any necessary cleanup after a function to restore stack, frame,
and regs. */
-
static void
-or32_output_function_epilogue(file, vars)
- FILE *file;
- int vars;
+or32_output_function_epilogue (file, vars)
+ FILE *file;
+ int vars;
{
- register int save_area;
- register int gpr_save_area = 0;
- register int lr_save_area;
- register int fp_save_area;
- register int stack_size;
- register int regno = 0;
-
- for (regno = 0; regno - if (regs_ever_live[regno] && !call_used_regs[regno]) {
- gpr_save_area += 4;
- }
-
- lr_save_area = !current_function_is_leaf || regs_ever_live[LINK_REGNUM] ? 4 : 0;
- fp_save_area = frame_pointer_needed ? 4 : 0;
-
- stack_size = OR1K_ALIGN(current_function_outgoing_args_size, 4) + lr_save_area + fp_save_area + gpr_save_area + OR1K_ALIGN(vars, 4);
-
- if (lr_save_area)
- fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", LINK_REGNUM, OR1K_ALIGN(current_function_outgoing_args_size, 4), STACK_POINTER_REGNUM);
-
- if (fp_save_area)
- fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", FRAME_POINTER_REGNUM, OR1K_ALIGN(current_function_outgoing_args_size,4) + lr_save_area, STACK_POINTER_REGNUM);
-
- save_area = OR1K_ALIGN(current_function_outgoing_args_size,4) + lr_save_area + fp_save_area;
- for (regno = 0; regno - if (regs_ever_live[regno] && !call_used_regs[regno]) {
- fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", regno, save_area, STACK_POINTER_REGNUM);
- save_area += 4;
- }
-
- if(stack_size >= 0x8000) {
- fprintf (file, "\tl.movhi \tr3,hi(%d)\n", stack_size);
- fprintf (file, "\tl.ori \tr3,r3,lo(%d)\n", stack_size);
+ int save_area;
+ int gpr_save_area;
+ int lr_save_area;
+ int fp_save_area;
+ int stack_size;
+ int regno;
+
+ stack_size = calculate_stack_size
+ (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);
+
+ if (lr_save_area)
+ {
+ fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", LINK_REGNUM,
+ OR1K_ALIGN (current_function_outgoing_args_size, 4),
+ STACK_POINTER_REGNUM);
+ }
+ if (fp_save_area)
+ {
+ fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", FRAME_POINTER_REGNUM,
+ OR1K_ALIGN (current_function_outgoing_args_size, 4)
+ + lr_save_area, STACK_POINTER_REGNUM);
+ }
+ save_area = (OR1K_ALIGN (current_function_outgoing_args_size, 4)
+ + lr_save_area + fp_save_area);
+
+ for (regno = 0; regno + {
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ fprintf (file, "\tl.lwz \tr%d,%d(r%d)\n", regno, save_area,
+ STACK_POINTER_REGNUM);
+ save_area += 4;
+ }
+ }
+
+ if(stack_size >= 0x8000)
+ {
+ fprintf (file, "\tl.movhi \tr3,hi(%d)\n", stack_size);
+ fprintf (file, "\tl.ori \tr3,r3,lo(%d)\n", stack_size);
#if NOP_DELAY_SLOT_FILL
- fprintf (file, "\tl.add \tr%d,r%d,r3\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM);
- fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
- fprintf (file, "\tl.nop\n");
+ fprintf (file, "\tl.add \tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM);
+ fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
+ fprintf (file, "\tl.nop\n");
#else
- fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
- fprintf (file, "\tl.add \tr%d,r%d,r3\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM);
+ fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
+ fprintf (file, "\tl.add \tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM);
#endif
- }
- else if (stack_size > 0) {
+ }
+ else if (stack_size > 0)
+ {
#if NOP_DELAY_SLOT_FILL
- fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, stack_size);
- fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
- fprintf (file, "\tl.nop\n");
+ fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, stack_size);
+ fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
+ fprintf (file, "\tl.nop\n");
#else
- fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
- fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, stack_size);
+ fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
+ fprintf (file, "\tl.addi \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM, stack_size);
#endif
- }
- else {
- fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
- fprintf (file, "\tl.nop\n");
- }
-
- fprintf (file, ".endproc _%s\n", get_function_name());
-}
-
-static int log_of_two(int x)
-{
- int y;
-
- x >>= 1;
- for(y=0; x; x>>=1, y++);
+ }
+ else
+ {
+ fprintf (file, "\tl.jr \tr%d\n", LINK_REGNUM);
+ fprintf (file, "\tl.nop\n");
+ }

- return y;
+ fprintf (file, ".endproc _%s\n", get_function_name ());
}

void
print_operand (file, x, code)
FILE *file;
rtx x;
- char code;
+ int code;
{
if (code == 'r' && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
else if (code == '(')
- if (dbr_sequence_length())
- fprintf (file, "\t# delay slot filled");
- else
- fprintf (file, "\n\tl.nop\t\t\t# nop delay slot");
+ {
+ if (dbr_sequence_length())
+ fprintf (file, "\t# delay slot filled");
+ else
+ fprintf (file, "\n\tl.nop\t\t\t# nop delay slot");
+ }
else if (code == 'C')
- switch(GET_CODE(x))
- {
- case EQ: fputs("eq", file); break;
- case NE: fputs("ne", file); break;
- case GT: fputs("gts", file); break;
- case GE: fputs("ges", file); break;
- case LT: fputs("lts", file); break;
- case LE: fputs("les", file); break;
- case GTU: fputs("gtu", file); break;
- case GEU: fputs("geu", file); break;
- case LTU: fputs("ltu", file); break;
- case LEU: fputs("leu", file); break;
- default:
- abort ();
- }
- else if (code == 'H') {
- if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
- else
- abort();
- }
+ {
+ switch(GET_CODE(x))
+ {
+ case EQ: fputs("eq", file); break;
+ case NE: fputs("ne", file); break;
+ case GT: fputs("gts", file); break;
+ case GE: fputs("ges", file); break;
+ case LT: fputs("lts", file); break;
+ case LE: fputs("les", file); break;
+ case GTU: fputs("gtu", file); break;
+ case GEU: fputs("geu", file); break;
+ case LTU: fputs("ltu", file); break;
+ case LEU: fputs("leu", file); break;
+ default:
+ abort ();
+ }
+ }
+ else if (code == 'H')
+ {
+ if (GET_CODE (x) == REG)
+ fprintf (file, "%s", reg_names[REGNO (x) + 1]);
+ else
+ abort();
+ }
else if (GET_CODE (x) == REG)
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
+ output_address (XEXP (x, 0));
else
- {
- /*debug_rtx(x);*/
- output_addr_const (file, x);
- }
+ output_addr_const (file, x);
}

/*---------------------------------------------------------------------------*/
/* Generate assembler code for a movdi/movdf */

-char *
-or1k_output_move_double(operands)
- rtx *operands;
+const char *
+or1k_output_move_double (operands)
+ rtx *operands;
{
- rtx xoperands[3];
- switch (GET_CODE (operands[0])) {
- case REG:
- if (GET_CODE (operands[1]) == REG)
- {
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- {
- output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
- output_asm_insn ("\tl.or \t%0, %1, r0", operands);
- return "";
- }
- else
- {
- output_asm_insn ("\tl.or \t%0, %1, r0", operands);
- output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
- return "";
- }
- }
- else if (GET_CODE (operands[1]) == MEM)
- {
- xoperands[1] = XEXP (operands[1], 0);
- if (GET_CODE (xoperands[1]) == REG)
- {
- xoperands[0] = operands[0];
- if (REGNO (xoperands[0]) == REGNO (xoperands[1]))
- {
- output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
- output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
- return "";
- }
- else
- {
- output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
- output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
- return "";
- }
- }
- else if (GET_CODE (xoperands[1]) == PLUS)
- {
- if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 1)) == REG)
- {
- xoperands[0] = operands[0];
- xoperands[1] = XEXP (xoperands[1], 0);
- if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
- {
- output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
- output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
- return "";
- }
- else
- {
- output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
- output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
- return "";
- }
- }
- else if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 0)) == REG)
- {
- xoperands[0] = operands[0];
- xoperands[1] = XEXP (xoperands[1], 1);
- if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
- {
- output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
- output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
- return "";
- }
- else
- {
- output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
- output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
- return "";
- }
- }
- else abort ();
- }
- else abort ();
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- if (INTVAL (operands[1]) - output_asm_insn ("\tl.addi \t%0, r0, -1", operands);
- else
- output_asm_insn ("\tl.or \t%0, r0, r0", operands);
- output_asm_insn ("\tl.movhi \t%H0, hi(%1)", operands);
- output_asm_insn ("\tl.ori \t%H0, %H0, lo(%1)", operands);
- return "";
- }
- else abort ();
- case MEM:
- xoperands[0] = XEXP (operands[0], 0);
- if (GET_CODE (xoperands[0]) == REG)
- {
- xoperands[1] = operands[1];
- output_asm_insn ("\tl.sw \t0(%0), %1", xoperands);
- output_asm_insn ("\tl.sw \t4(%0), %H1", xoperands);
- return "";
- }
- else if (GET_CODE (xoperands[0]) == PLUS)
- {
- if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 1)) == REG)
- {
- xoperands[0] = XEXP (xoperands[0], 0);
- xoperands[2] = operands[1];
- output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
- output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
- return "";
- }
- else if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 0)) == REG)
- {
- xoperands[0] = XEXP (xoperands[0], 1);
- xoperands[2] = operands[1];
- output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
- output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
- return "";
- }
- else abort ();
- }
- else abort ();
- default:
- abort ();
+ rtx xoperands[3];
+
+ switch (GET_CODE (operands[0]))
+ {
+ case REG:
+ if (GET_CODE (operands[1]) == REG)
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ {
+ output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
+ output_asm_insn ("\tl.or \t%0, %1, r0", operands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.or \t%0, %1, r0", operands);
+ output_asm_insn ("\tl.or \t%H0, %H1, r0", operands);
+ return "";
+ }
}
+ else if (GET_CODE (operands[1]) == MEM)
+ {
+ xoperands[1] = XEXP (operands[1], 0);
+ if (GET_CODE (xoperands[1]) == REG)
+ {
+ xoperands[0] = operands[0];
+ if (REGNO (xoperands[0]) == REGNO (xoperands[1]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
+ output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands);
+ return "";
+ }
+ }
+ else if (GET_CODE (xoperands[1]) == PLUS)
+ {
+ if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 1)) == REG)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (xoperands[1], 0);
+ if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
+ return "";
+ }
+ }
+ else if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 0)) == REG)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (xoperands[1], 1);
+ if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
+ {
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands);
+ output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", xoperands);
+ return "";
+ }
+ }
+ else abort ();
+ }
+ else abort ();
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) + output_asm_insn ("\tl.addi \t%0, r0, -1", operands);
+ else
+ output_asm_insn ("\tl.or \t%0, r0, r0", operands);
+ output_asm_insn ("\tl.movhi \t%H0, hi(%1)", operands);
+ output_asm_insn ("\tl.ori \t%H0, %H0, lo(%1)", operands);
+ return "";
+ }
+ else abort ();
+ case MEM:
+ xoperands[0] = XEXP (operands[0], 0);
+ if (GET_CODE (xoperands[0]) == REG)
+ {
+ xoperands[1] = operands[1];
+ output_asm_insn ("\tl.sw \t0(%0), %1", xoperands);
+ output_asm_insn ("\tl.sw \t4(%0), %H1", xoperands);
+ return "";
+ }
+ else if (GET_CODE (xoperands[0]) == PLUS)
+ {
+ if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 1)) == REG)
+ {
+ xoperands[0] = XEXP (xoperands[0], 0);
+ xoperands[2] = operands[1];
+ output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
+ output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
+ return "";
+ }
+ else if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 0)) == REG)
+ {
+ xoperands[0] = XEXP (xoperands[0], 1);
+ xoperands[2] = operands[1];
+ output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands);
+ output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands);
+ return "";
+ }
+ else abort ();
+ }
+ else abort ();
+ default:
+ abort ();
+ }
}

Index: or32.h
===================================================================
RCS file: /home/oc/cvs/or1k/gcc-3.2.3/gcc/config/or32/or32.h,v
retrieving revision 1.1.1.1
diff -u -p -u -r1.1.1.1 or32.h
--- or32.h 14 Feb 2004 17:48:12 -0000 1.1.1.1
+++ or32.h 9 Mar 2004 19:58:49 -0000
@@ -209,7 +209,7 @@ extern int target_flags;
from 0 to just below FIRST_PSEUDO_REGISTER.
All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers. */
-#define FIRST_PSEUDO_REGISTER 32
+#define FIRST_PSEUDO_REGISTER 33
#define LAST_INT_REG (FIRST_PSEUDO_REGISTER - 1)

/* 1 for registers that have pervasive standard uses
@@ -217,7 +217,7 @@ extern int target_flags;
On the or1k, these are r1 as stack pointer and
r2 as frame/arg pointer. */
#define FIXED_REGISTERS {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
registers that can be used without being saved.
@@ -225,7 +225,7 @@ extern int target_flags;
and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like. */
#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1 \
- , 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
+ , 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}

#define CALL_USED_REGISTERS_NUM 11

Index: or32.md
===================================================================
RCS file: /home/oc/cvs/or1k/gcc-3.2.3/gcc/config/or32/or32.md,v
retrieving revision 1.1.1.1
diff -u -p -u -r1.1.1.1 or32.md
--- or32.md 14 Feb 2004 17:48:12 -0000 1.1.1.1
+++ or32.md 9 Mar 2004 19:58:50 -0000
@@ -29,7 +29,7 @@

(define_delay (eq_attr "type" "branch,jump")
[(and (eq_attr "type" "!branch,jump")
- (eq_attr "length" "1")) (nil) (nil)])
+ (eq_attr "length" "1")) (nil) (nil)])

;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
;; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
@@ -120,34 +120,84 @@
[(set_attr "type" "fp")
(set_attr "length" "1")])

+
;;
-;; Compares
-;;
+;; Conditional Branches
+;;

-;; XXX check second match_operand as:
-;; (match_operand:SI 1 "nonmemory_operand" "rI")
-(define_expand "cmpsi"
- [(set (cc0)
- (compare:CC (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r")))]
+(define_expand "cbranchsi4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "
+ {
+ int compare_code = GET_CODE (operands[0]);
+
+ if (GET_MODE (operands[0]) != SImode)
+ abort ();
+
+ /* Emit an insn that should be matched by the ``sfccsi2'' pattern
+ defined below. Use register 32 instead of cc0 since cc0 setter
+ and user have to be adjacent. */
+ emit_insn (gen_rtx (SET, VOIDmode,
+ gen_rtx_REG (CCmode, 32),
+ gen_rtx (compare_code, CCmode,
+ operands[1],
+ operands[2])));
+
+ /* Emit conditional branch which checks the calculated value
+ of (reg 32) and branches to operands[3] depending on the
+ value. */
+ emit_jump_insn
+ (gen_rtx (SET, VOIDmode, pc_rtx,
+ gen_rtx (IF_THEN_ELSE, VOIDmode,
+ gen_rtx (NE, CCmode,
+ const0_rtx,
+ gen_rtx_REG (CCmode, 32)),
+ gen_rtx_LABEL_REF (VOIDmode, operands[3]),
+ pc_rtx)));
+ DONE;
+ }"
+)
+
+(define_insn "sfccsi2"
+ [(set (reg:CC 32)
+ (match_operator:CC 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "general_operand" "r,I")]))]
+ ""
+ "@
+ l.sf%C0 \\t%1, %2
+ l.sf%C0i \\t%1, %2"
+ [(set_attr "type" "logic,logic")
+ (set_attr "length" "1,1")]
+)
+
+(define_insn "bf"
+ [(set (pc)
+ (if_then_else (ne:CC (const_int 0) (reg:CC 32))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "
-{
- or1k_cmp_op0 = operands[0];
- or1k_cmp_op1 = operands[1];
- DONE;
-}")
+ "l.bf \\t%0%("
+ [(set_attr "type" "branch")
+ (set_attr "length" "1")]
+)

-(define_expand "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "register_operand" "r"))]
+(define_insn "bnf"
+ [(set (pc)
+ (if_then_else (eq:CC (const_int 0) (reg:CC 32))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "
-{
- or1k_cmp_op0 = operands[0];
- or1k_cmp_op1 = const0_rtx;
- DONE;
-}")
+ "l.bnf \\t%0%("
+ [(set_attr "type" "branch")
+ (set_attr "length" "1")]
+)

;;
;; Moves
@@ -659,96 +709,28 @@
(set_attr "length" "1")])

;;
-;; Conditional Branches
-;;
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, EQ); DONE; }")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, NE); DONE; }")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, LT); DONE; }")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, GT); DONE; }")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, LE); DONE; }")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, GE); DONE; }")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, LTU); DONE; }")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, GTU); DONE; }")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, LEU); DONE; }")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- "" "{ gen_cond_branch(operands, GEU); DONE; }")
-
-;;
;; Output insns for conditional branches; RTL for these is
;; generated in gen_cond_branch().
;;

-(define_insn "branch_output"
- [(set (pc) (if_then_else (eq (const_int 0)
- (cc0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- ""
- "l.bnf \\t%0%("
- [(set_attr "type" "branch")
- (set_attr "length" "1")])
+; (define_insn "branch_output"
+; [(set (pc) (if_then_else (eq (const_int 0)
+; (cc0))
+; (label_ref (match_operand 0 "" "")) (pc)))]
+; ""
+; "l.bnf \\t%0%("
+; [(set_attr "type" "branch")
+; (set_attr "length" "1")])
+
+; (define_insn "branch_output_rev"
+; [(set (pc) (if_then_else (ne (const_int 0)
+; (cc0))
+; (label_ref (match_operand 0 "" "")) (pc)))]
+; ""
+; "l.bf \\t%0%("
+; [(set_attr "type" "branch")
+; (set_attr "length" "1")])

-(define_insn "branch_output_rev"
- [(set (pc) (if_then_else (ne (const_int 0)
- (cc0))
- (label_ref (match_operand 0 "" "")) (pc)))]
- ""
- "l.bf \\t%0%("
- [(set_attr "type" "branch")
- (set_attr "length" "1")])
-
-;;
-;; Output insns for set intructions; RTL for these is
-;; generated in gen_cond_branch().
-;;
-
-(define_insn "set_output1"
- [(set (cc0)
- (match_operator:SI 0 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "register_operand" "r")]))]
- ""
- "l.sf%C0 \\t%1,%2"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])

;;(define_insn "set_output2"
;; [(set (cc0)
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 9, 2004
Not available!
Johan Rydberg jrydberg@night.trouble.net> writes:
-extern void print_operand PARAMS ((FILE *, rtx, char));
+extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, register rtx));
-extern void gen_cond_branch PARAMS ((rtx [], enum rtx_code));


PARAMS isn't needed anymore since gcc now requires a iso C compiler to
bootstrap.

-void
-gen_cond_branch(operands, test)
- rtx operands[];
- enum rtx_code test;


Ditto.

[PATCH] GCC: split sfCC+bX
by Unknown on Mar 9, 2004
Not available!
James Morrison ja2morri@csclub.uwaterloo.ca> wrote: : > -extern void print_operand PARAMS ((FILE *, rtx, char)); : > +extern void print_operand PARAMS ((FILE *, rtx, int)); : > extern void print_operand_address PARAMS ((FILE *, register rtx)); : > -extern void gen_cond_branch PARAMS ((rtx [], enum rtx_code)); : : PARAMS isn't needed anymore since gcc now requires a iso C compiler to : bootstrap. True. But as you see, I only removed gen_cond_branch and changed print_operand. I didn't do any house cleaning in that file. : > -void : > -gen_cond_branch(operands, test) : > - rtx operands[]; : > - enum rtx_code test; : : Ditto. That function is removed. -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Ladytron - The Reason Why
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 11, 2004
Not available!
* Johan Rydberg (jrydberg@night.trouble.net) wrote:
Hi,

This little patch does some house cleaning plus that it splits the sfCC+bX
sequences into sfCC/bX (there is need need for then to be located next to
each other.)

I would be greatfull if someone could take a quick look at it, and then
commit it. (To let ATS build Linux with it and try it out in the simulator.)
i tried it and i get gcc segfault while compiling linux. details attached. regards, p. -------------- next part -------------- gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -I/center/opencores/toolchains/oce-2.55/p_root/lin ux-2.4/arch/or32 -o scripts/split-include scripts/split-include.c scripts/split-include include/linux/autoconf.h include/config or32-uclinux-gcc -D__KERNEL__ -I/center/opencores/toolchains/oce-2.55/p_root/linux-2.4/include -Wall -Wst rict-prototypes -Werror-implicit-function-declaration -fno-strict-aliasing -O -nostdlib -fomit-frame-poin ter -I/center/opencores/toolchains/oce-2.55/p_root/linux-2.4/arch/or32 -fsigned-char -msoft-float -pipe - ffixed-r2 -Wno-uninitialized -g -DKBUILD_BASENAME=main -c -o init/main.o init/main.c /center/opencores/toolchains/oce-2.55/p_root/linux-2.4/include/asm/system.h: In function __xchg': /center/opencores/toolchains/oce-2.55/p_root/linux-2.4/include/asm/system.h:82: internal error: Segmentat ion fault Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. make: *** [init/main.o] Error 1 -------------- next part -------------- /* * Based on: * include/asm-ppc/system.h * Copyright (C) 1999 Cort Dougan cort@cs.nmt.edu> */ #ifndef __OR32_SYSTEM_H #define __OR32_SYSTEM_H #include #include #include /* Memory bariers */ #define mb() __asm__ __volatile__ ("" : : : "memory") #define rmb() __asm__ __volatile__ ("" : : : "memory") #define wmb() __asm__ __volatile__ ("" : : : "memory") #define set_mb(var, value) do { var = value; mb(); } while (0) #define set_wmb(var, value) do { var = value; wmb(); } while (0) #define smp_mb() __asm__ __volatile__("": : :"memory") #define smp_rmb() __asm__ __volatile__("": : :"memory") #define smp_wmb() __asm__ __volatile__("": : :"memory") #define nop() __asm__ __volatile__ ("l.nop"::) #ifdef __KERNEL__ struct task_struct; struct thread_struct; extern unsigned int rtas_data; struct pt_regs; int printk(const char *, ...); extern void show_regs(struct pt_regs * regs); extern void __save_flags(unsigned long *flags); extern void __restore_flags(unsigned long flags); extern void __save_and_cli(unsigned long *flags); extern void __sti(void); extern void __cli(void); extern void __mtspr(unsigned long add, unsigned long val); extern unsigned long __mfspr(unsigned long add); #define cli() __cli() #define sti() __sti() #define save_flags(flags) __save_flags(&(flags)) #define restore_flags(flags) __restore_flags(flags) #define save_and_cli(flags) __save_and_cli(&(flags)) #define mfspr(x) __mfspr(x) #define mtspr(x,y) __mtspr(x,y) #define local_irq_disable() __cli() #define local_irq_enable() __sti() #define local_irq_save(flags) __save_and_cli(&(flags)) #define local_irq_restore(flags) __restore_flags(flags) #define prepare_to_switch() do { } while(0) #define switch_to(prev,next,last) _switch_to((prev),(next),&(last)) extern void _switch_to(struct task_struct *, struct task_struct *, struct task_struct **); struct thread_struct; extern struct task_struct *_switch(struct thread_struct *prev, struct thread_struct *next); struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) ((volatile struct __xchg_dummy *)(x)) #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) static inline unsigned long __xchg(unsigned long x, void * ptr, int size) { unsigned long tmp, flags; save_and_cli(flags); switch (size) { case 1: __asm__ __volatile__ ("l.lbz %0,%2\n\t" "l.sb %2,%1" : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); break; case 2: __asm__ __volatile__ ("l.lhz %0,%2\n\t" "l.sh %2,%1" : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); break; case 4: __asm__ __volatile__ ("l.lwz %0,%2\n\t" "l.sw %2,%1" : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory"); break; } restore_flags(flags); return tmp; } extern inline void * xchg_ptr(void * m, void * val) { return (void *) __xchg((unsigned long)m, val, sizeof(unsigned long)); } /* * debugging aid */ extern void __print(const char *fmt, ...); #endif /* __KERNEL__ */ #endif /* __OR32_SYSTEM_H */
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 11, 2004
Not available!
Matjaz Breskvar phoenix@opencores.org> wrote: : > I would be greatfull if someone could take a quick look at it, and then : > commit it. (To let ATS build Linux with it and try it out in the simulator.) : : i tried it and i get gcc segfault while compiling linux. details attached. Thanks. This was caused by a small miss by me. I have introduces a new faked condition code register, and had forgotten to put it in REGISTER_NAMES. This patch should do it (the files compile for me at least, with the same flags.) Thanks for sending the pre-processed file, that made things a lot easier. Hopefully this patch will apply to your already patched tree. Best regards, Johan. Index: or32.h =================================================================== RCS file: /home/oc/cvs/or1k/gcc-3.2.3/gcc/config/or32/or32.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 or32.h --- or32.h 14 Feb 2004 17:48:12 -0000 1.1.1.1 +++ or32.h 11 Mar 2004 00:13:08 -0000 @@ -889,7 +889,7 @@ fprintf (FILE, ".file\t"); \ #define REGISTER_NAMES \ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" \ -, "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"} +, "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", "fake-cc0"} /* Define this to be the delimiter between SDB sub-sections. The default
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 12, 2004
Not available!
* Johan Rydberg (jrydberg@night.trouble.net) wrote:
Matjaz Breskvar phoenix@opencores.org> wrote: : > I would be greatfull if someone could take a quick look at it, and then : > commit it. (To let ATS build Linux with it and try it out in the simulator.) : : i tried it and i get gcc segfault while compiling linux. details attached. Thanks. This was caused by a small miss by me. I have introduces a new faked condition code register, and had forgotten to put it in REGISTER_NAMES. This patch should do it (the files compile for me at least, with the same flags.)


this patch fixes it; linux builds and runs...

regards,
p.

[PATCH] GCC: split sfCC+bX
by Unknown on Mar 12, 2004
Not available!
Matjaz Breskvar phoenix@opencores.org> wrote: : > This patch should do it (the files compile for me at least, with the same : > flags.) : : this patch fixes it; linux builds and runs... Great. I'm a bit supprised that it works, since I've found a serious bug. At least in my CVS HEAD branch (I'm not sure about 3.2.3, haven't tested it.) GCC barfs on the following code: if (foo > 0x7fff) ... "foo" is signed, so it must use signed compare and 0x8000 does overflow the 16-bits for the "sfCCsi" insns. GCC should then simply reload it into a register, but it doesn't for some reason. I've fixed the bug in my CVS HEAD branch. Do you think I should spend time backporting it to 3.2.3? Regarding the CVS HEAD branch. I've got it working pretty good in 32 bit mode. I haven't run a simple piece of code it generates yet, though. For the compile.exp testcases: The eight failures is because I have no string.h in my include path as of yet. === gcc Summary === # of expected passes 3550 # of unexpected failures 8 # of unsupported tests 30 64 bit mode is absurdly broken. It generates code, but badly. Mainly because I havn't added any new insn to the machine descriptor file. Anyone have an idea on how 64-bit constants (for example addresses) should be put in a register, in the most effective way? I guess we could use a GOT, but that will be dead slow for configurations without a cache. The best I've come up with so far is this, which requires us to introduce two new relocation types: l.movi r3, hi48(foo) l.ori r3, hi32(foo) l.slli r3, r3, 16 l.ori r3, hi(foo) l.slli r3, r3, 16 l.ori r3, lo(foo) Six insns in total for loading a full 64-bit constant. PPC needs 5 insn if it doesnt use a GOT. -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Granada - The Tortoise
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 14, 2004
Not available!
: > I would be greatfull if someone could take a quick look at it, and then
: > commit it. (To let ATS build Linux with it and try it out in the simulator.)


i've compiled linux kernel with and without this patch. binary compiled
with patched gcc is ~5% smaller then without it.

1736704 (linux kernel, with sfCCxx patch)
1818624 (linux kernel, without sfCCxx patch)

i intend to do some performance comparisson in the comming days and i'll
report back then...

best regards,
p.

PS. Johan, if you don't have any additional changes i think we can
commit this.

[PATCH] GCC: split sfCC+bX
by Unknown on Mar 15, 2004
Not available!
Matjaz Breskvar phoenix@opencores.org> wrote: : i've compiled linux kernel with and without this patch. binary compiled : with patched gcc is ~5% smaller then without it. : : 1736704 (linux kernel, with sfCCxx patch) : 1818624 (linux kernel, without sfCCxx patch) I didn't know it would effect the code size that much. I didn't think it would effect it at all, actually. But this is a good thing. It seems to work as before? I.e, the patch didn't introduce any regressions? : PS. Johan, if you don't have any additional changes i think we can : commit this. Since I see you as maintainer for 3.2.3 I would prefer that you commit it, provided that you don't find any problems with it. It would make things a bit easier for me, since my development trees is in a bit of a mess :) -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Incubus - Nice To Know You
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
It seems to work as before? I.e, the patch didn't introduce any regressions?


no i didn't notice any regression, great work.

and about the codesize. the biggest (all?) reduction is because of l.sfCCi
usage. if compare is to 16 bit value, there is no need to load that into
register and then compare. to illustrate the point

gcc without patch:

grep "l.sfeqi" vmlinux.DS | wc -l
50

gcc with patch:

grep "l.sfeqi" vmlinux.DS | wc -l
18311

: PS. Johan, if you don't have any additional changes i think we can
: commit this.

Since I see you as maintainer for 3.2.3 I would prefer that you commit it,
provided that you don't find any problems with it. It would make things
a bit easier for me, since my development trees is in a bit of a mess :)


ok, no problem, i'll also try ecos (just in case) and then commit it
to the cvs in a day or so.

best regards,
p.

[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
Matjaz Breskvar phoenix@opencores.org> wrote: : and about the codesize. the biggest (all?) reduction is because of l.sfCCi : usage. if compare is to 16 bit value, there is no need to load that into : register and then compare. Also the l.sfCC insns can be scheduled into a delay slot. I'll see if I can backport a change to the 3.2.3 version that would probably decrease the code size a bit. Currently loads is done in the following way; l.movhi r3,hi(sym) l.ori r3,r3,lo(sym) l.lwz r3,0(r3) I've splitted up the l.movhi/l.ori insn (it is considered one insn by GCC) into two separate, making two things possible: 1) they can be scheduleded independent of each other. for example, the l.ori insn can be put in a delay slot. 2) with a small fix to binutils (libbfd) you can generate the following code for a load: l.movhi r3,hi(sym) l.lwz r3,lo(sym)(r3) same can be done for stores. the reason for the fix in bfd is that "l.ori" does not sign extend it's immediate, which lwz/addi/sw does. if the displacement is negative the high bits of l.movhi must be adjusted. otherwise an invalid address will get calculated. Do you think this would effect code size at all? It only eliminates one insn. -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Grovskopa - B1 - Strap-on Suncica (Version
[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
I could see this being useful in code which does a lot of peripheral accesses, where ptrs are usually declared volatile. I've certainly noticed the inefficiency of e.g.: l.movhi r3,0x9100 l.ori r3,r3,0x0 l.lwz r3,0(r3) Robert Cragie, Design Engineer _______________________________________________________________ Jennic Ltd, Furnival Street, Sheffield, S1 4QT, UK http://www.jennic.com Tel: +44 (0) 114 281 2655 _______________________________________________________________
-----Original Message----- From: openrisc-bounces@opencores.org [mailto:openrisc-bounces@opencores.org]On Behalf Of Johan Rydberg Sent: 16 March 2004 14:12 To: Matjaz Breskvar Cc: openrisc@opencores.org Subject: Re: [openrisc] [PATCH] GCC: split sfCC+bX Matjaz Breskvar phoenix@opencores.org> wrote: : and about the codesize. the biggest (all?) reduction is because of l.sfCCi : usage. if compare is to 16 bit value, there is no need to load that into : register and then compare. Also the l.sfCC insns can be scheduled into a delay slot. I'll see if I can backport a change to the 3.2.3 version that would probably decrease the code size a bit. Currently loads is done in the following way; l.movhi r3,hi(sym) l.ori r3,r3,lo(sym) l.lwz r3,0(r3) I've splitted up the l.movhi/l.ori insn (it is considered one insn by GCC) into two separate, making two things possible: 1) they can be scheduleded independent of each other. for example, the l.ori insn can be put in a delay slot. 2) with a small fix to binutils (libbfd) you can generate the following code for a load: l.movhi r3,hi(sym) l.lwz r3,lo(sym)(r3) same can be done for stores. the reason for the fix in bfd is that "l.ori" does not sign extend it's immediate, which lwz/addi/sw does. if the displacement is negative the high bits of l.movhi must be adjusted. otherwise an invalid address will get calculated. Do you think this would effect code size at all? It only eliminates one insn. -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Grovskopa - B1 - Strap-on Suncica (Version _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc



[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
* Johan Rydberg (jrydberg@night.trouble.net) wrote:
Matjaz Breskvar phoenix@opencores.org> wrote: : and about the codesize. the biggest (all?) reduction is because of l.sfCCi : usage. if compare is to 16 bit value, there is no need to load that into : register and then compare. Also the l.sfCC insns can be scheduled into a delay slot. I'll see if I can backport a change to the 3.2.3 version that would probably decrease the code size a bit.


that would be great. i think that code size is very important to
many doing work with openrisc...

Currently loads is done in the following way;

l.movhi r3,hi(sym)
l.ori r3,r3,lo(sym)
l.lwz r3,0(r3)

I've splitted up the l.movhi/l.ori insn (it is considered one insn by GCC)
into two separate, making two things possible:

1) they can be scheduleded independent of each other. for example,
the l.ori insn can be put in a delay slot.

2) with a small fix to binutils (libbfd) you can generate the following
code for a load:

l.movhi r3,hi(sym)
l.lwz r3,lo(sym)(r3)

same can be done for stores. the reason for the fix in bfd is that
"l.ori" does not sign extend it's immediate, which lwz/addi/sw does.
if the displacement is negative the high bits of l.movhi must be
adjusted. otherwise an invalid address will get calculated.

Do you think this would effect code size at all? It only eliminates one
insn.


i think it would. it's a little bit more difficult to do an
aproximation but i see a lot of l.movhi -> l.ori
-> l.lwz/l.sw patterns...

i'm really interested in this patch...

best regards,
p.

[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
Johan Rydberg wrote:

2) with a small fix to binutils (libbfd) you can generate the following
code for a load:

l.movhi r3,hi(sym)
l.lwz r3,lo(sym)(r3)

same can be done for stores. the reason for the fix in bfd is that
"l.ori" does not sign extend it's immediate, which lwz/addi/sw does.
if the displacement is negative the high bits of l.movhi must be
adjusted. otherwise an invalid address will get calculated.


The linker already propagates carry bits from a 'lo(sym)' field to the
nearest preceding 'hi(sym)' field. (This is necessary because the
values of symbols change each time an object file is relocated and the
or32 linker uses REL-style relocation, in which the relocation offsets
are embedded in the instructions rather than in a separate section.)

In fact, it may be problematic if the compiler schedules an instruction
so that the hi(sym) reference no longer precedes the lo(sym) reference.
I haven't thought about it much, but that might require switching to
RELA-style relocations, in which the relocation offsets are stored as
part of the relocation record rather than embedded in the instructions.

-Scott




[PATCH] GCC: split sfCC+bX
by Unknown on Mar 16, 2004
Not available!
Scott Furman sfurman@rosum.com> wrote: : The linker already propagates carry bits from a 'lo(sym)' field to the : nearest preceding 'hi(sym)' field. (This is necessary because the : values of symbols change each time an object file is relocated and the : or32 linker uses REL-style relocation, in which the relocation offsets : are embedded in the instructions rather than in a separate section.) I did a small test. By putting the data segment at 0xfff00 forcing negative values into the low order bits. All relocations is done on the object "bar", located at 0xfff00. objdump output: 01000074 : 1000074: 18 60 00 0f l.movhi r3,0xf 1000078: 84 63 ff 00 l.lwz r3,0xffffff00(r3) Low order bits sign extended, no carry from lower bits to upper. EA result: 0xf0000 + -256 = 0xeff00. Invalid address! 100007c: 18 60 00 0f l.movhi r3,0xf 1000080: a8 63 ff 00 l.ori r3,r3,0xff00 Low order bits zero extended, no carry needed. EA result: 0xf0000 + 0xff00 = 0xfff00. Correct address! 1000084: 18 60 00 0f l.movhi r3,0xf 1000088: 9c 63 ff 00 l.addi r3,r3,0xffffff00 Low order bits sign extended, no carry from lower bits. EA result: 0xf0000 + -256 = 0xeff00. Invalid address! : In fact, it may be problematic if the compiler schedules an instruction : so that the hi(sym) reference no longer precedes the lo(sym) reference. : I haven't thought about it much, but that might require switching to : RELA-style relocations, in which the relocation offsets are stored as : part of the relocation record rather than embedded in the instructions. The simplest solution, I guess is to use RELA, do carrying for all relocations, thus making l.movhi/l.ori pairs invalid in favour of l.movhi/l.addi . This is what PowerPC does, IIRC. -- Johan Rydberg, Free Software Developer, Sweden http://rtmk.sf.net | http://www.nongnu.org/guss/ Playing Incubus - Nice To Know You
no use no use 1/2 Next Last
© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.