avr.c (out_adj_frame_ptr): Make "frame pointer change too big for -mtiny-stack" a warning, if larger than 63.
* config/avr/avr.c (out_adj_frame_ptr): Make "frame pointer change too big for -mtiny-stack" a warning, if larger than 63. (out_set_stack_ptr): Change the logic so -mno-interrupts is always safe to use on possible future devices. (function_prologue): Write SPH before SPL, for consistency. If interrupt_func_p true, we know we have enabled interrupts. (avr_num_arg_regs): New function. Round up to even number of bytes if no -mpack-args or if calling a libgcc function. (function_arg, function_arg_advance): Use it. (output_movsisf, ashlsi3_out, ashrsi3_out, lshrsi3_out): Output "movw" if available. (out_tsthi, out_tstsi, ashlqi3_out, lshrqi3_out): Change uses of TEST_HARD_REG_CLASS macro to test_hard_reg_class function. (asm_output_section_name): Add blanks for consistent output. (encode_section_info): Set TREE_READONLY for progmem data to avoid gas warnings about changed section attributes. (avr_hard_regno_mode_ok): Force non-QImode data to start in even numbered registers on devices with "movw". * config/avr/avr.h (MASK_*): Define bits for target_flags. (TARGET_SWITCHES): Mark help strings for translation. Add new -mpack-args and -menhanced switches. (TARGET_OPTIONS): Mark help strings for translation. (progmem_section): Add section attributes. * config/avr/avr.md (*movhi, call_insn, call_value_insn): Output "movw" if available. (mulqi3, mulqihi3, umulqihi3, mulhi3, *tablejump_enh): New patterns. * config/avr/libgcc.S (_mulqi3, _divqi3): Update to the new call convention (arguments aligned on even registers). (_cleanup, _exit): Make weak symbols libc can override. From-SVN: r34847
This commit is contained in:
parent
2e63772162
commit
c4984bad36
@ -1,3 +1,36 @@
|
||||
2000-07-01 Marek Michalkiewicz <marekm@linux.org.pl>
|
||||
|
||||
* config/avr/avr.c (out_adj_frame_ptr): Make "frame pointer
|
||||
change too big for -mtiny-stack" a warning, if larger than 63.
|
||||
(out_set_stack_ptr): Change the logic so -mno-interrupts is
|
||||
always safe to use on possible future devices.
|
||||
(function_prologue): Write SPH before SPL, for consistency.
|
||||
If interrupt_func_p true, we know we have enabled interrupts.
|
||||
(avr_num_arg_regs): New function. Round up to even number of
|
||||
bytes if no -mpack-args or if calling a libgcc function.
|
||||
(function_arg, function_arg_advance): Use it.
|
||||
(output_movsisf, ashlsi3_out, ashrsi3_out, lshrsi3_out):
|
||||
Output "movw" if available.
|
||||
(out_tsthi, out_tstsi, ashlqi3_out, lshrqi3_out): Change uses
|
||||
of TEST_HARD_REG_CLASS macro to test_hard_reg_class function.
|
||||
(asm_output_section_name): Add blanks for consistent output.
|
||||
(encode_section_info): Set TREE_READONLY for progmem data to
|
||||
avoid gas warnings about changed section attributes.
|
||||
(avr_hard_regno_mode_ok): Force non-QImode data to start in
|
||||
even numbered registers on devices with "movw".
|
||||
* config/avr/avr.h (MASK_*): Define bits for target_flags.
|
||||
(TARGET_SWITCHES): Mark help strings for translation.
|
||||
Add new -mpack-args and -menhanced switches.
|
||||
(TARGET_OPTIONS): Mark help strings for translation.
|
||||
(progmem_section): Add section attributes.
|
||||
* config/avr/avr.md (*movhi, call_insn, call_value_insn):
|
||||
Output "movw" if available.
|
||||
(mulqi3, mulqihi3, umulqihi3, mulhi3, *tablejump_enh):
|
||||
New patterns.
|
||||
* config/avr/libgcc.S (_mulqi3, _divqi3): Update to the new
|
||||
call convention (arguments aligned on even registers).
|
||||
(_cleanup, _exit): Make weak symbols libc can override.
|
||||
|
||||
2000-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* fp-bit.h: New file.
|
||||
|
@ -49,6 +49,7 @@ static int signal_function_p PARAMS ((tree));
|
||||
static int sequent_regs_live PARAMS ((void));
|
||||
static char * ptrreg_to_str PARAMS ((int));
|
||||
static char * cond_string PARAMS ((enum rtx_code));
|
||||
static int avr_num_arg_regs PARAMS ((enum machine_mode, tree));
|
||||
static int out_adj_frame_ptr PARAMS ((FILE *, int));
|
||||
static int out_set_stack_ptr PARAMS ((FILE *, int, int));
|
||||
|
||||
@ -347,30 +348,23 @@ out_adj_frame_ptr (file, adj)
|
||||
|
||||
if (adj)
|
||||
{
|
||||
/* For -mtiny-stack, the high byte (r29) does not change -
|
||||
prefer "subi" (1 cycle) over "sbiw" (2 cycles). */
|
||||
|
||||
if (adj < -63 || adj > 63 || TARGET_TINY_STACK)
|
||||
if (TARGET_TINY_STACK)
|
||||
{
|
||||
fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB), adj);
|
||||
if (adj < -63 || adj > 63)
|
||||
warning ("large frame pointer change (%d) with -mtiny-stack", adj);
|
||||
|
||||
/* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
|
||||
over "sbiw" (2 cycles, same size). */
|
||||
|
||||
fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
|
||||
size++;
|
||||
|
||||
if (TARGET_TINY_STACK)
|
||||
{
|
||||
/* In addition to any local data, each level of function calls
|
||||
needs at least 4 more bytes of stack space for the saved
|
||||
frame pointer and return address. So, (255 - 16) leaves
|
||||
room for 4 levels of function calls. */
|
||||
|
||||
if (adj < -(255 - 16) || adj > (255 - 16))
|
||||
fatal ("Frame pointer change (%d) too big for -mtiny-stack",
|
||||
adj);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, (AS2 (sbci, r29, hi8(%d)) CR_TAB), adj);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
else if (adj < -63 || adj > 63)
|
||||
{
|
||||
fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
|
||||
AS2 (sbci, r29, hi8(%d)) CR_TAB),
|
||||
adj, adj);
|
||||
size += 2;
|
||||
}
|
||||
else if (adj < 0)
|
||||
{
|
||||
@ -398,17 +392,18 @@ out_set_stack_ptr (file, before, after)
|
||||
int before;
|
||||
int after;
|
||||
{
|
||||
int do_sph, do_cli, do_save, size;
|
||||
int do_sph, do_cli, do_save, do_sei, lock_sph, size;
|
||||
|
||||
if (TARGET_NO_INTERRUPTS)
|
||||
{
|
||||
before = 0;
|
||||
after = 0;
|
||||
}
|
||||
/* The logic here is so that -mno-interrupts actually means
|
||||
"it is safe to write SPH in one instruction, then SPL in the
|
||||
next instruction, without disabling interrupts first".
|
||||
The after != -1 case (interrupt/signal) is not affected. */
|
||||
|
||||
do_sph = !TARGET_TINY_STACK;
|
||||
do_cli = (before != 0 && (after == 0 || do_sph));
|
||||
do_save = (before == -1 && after == -1 && do_cli);
|
||||
lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
|
||||
do_cli = (before != 0 && (after == 0 || lock_sph));
|
||||
do_save = (do_cli && before == -1 && after == -1);
|
||||
do_sei = ((do_cli || before != 1) && after == 1);
|
||||
size = 1;
|
||||
|
||||
if (do_save)
|
||||
@ -424,8 +419,8 @@ out_set_stack_ptr (file, before, after)
|
||||
}
|
||||
|
||||
/* Do SPH first - maybe this will disable interrupts for one instruction
|
||||
someday, much like x86 does when changing SS (a suggestion has been
|
||||
sent to avr@atmel.com for consideration in future devices). */
|
||||
someday (a suggestion has been sent to avr@atmel.com for consideration
|
||||
in future devices - that would make -mno-interrupts always safe). */
|
||||
if (do_sph)
|
||||
{
|
||||
fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
|
||||
@ -440,7 +435,7 @@ out_set_stack_ptr (file, before, after)
|
||||
fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
|
||||
size++;
|
||||
}
|
||||
else if (after == 1 && (before != 1 || do_cli))
|
||||
else if (do_sei)
|
||||
{
|
||||
fprintf (file, "sei" CR_TAB);
|
||||
size++;
|
||||
@ -503,8 +498,8 @@ function_prologue (FILE *file, int size)
|
||||
fprintf (file, ("\t"
|
||||
AS2 (ldi, r28, lo8(%s - %d)) CR_TAB
|
||||
AS2 (ldi, r29, hi8(%s - %d)) CR_TAB
|
||||
AS2 (out,__SP_L__,r28) CR_TAB
|
||||
AS2 (out,__SP_H__,r29) "\n"),
|
||||
AS2 (out, __SP_H__, r29) CR_TAB
|
||||
AS2 (out, __SP_L__, r28) "\n"),
|
||||
initial_stack, size, initial_stack, size);
|
||||
|
||||
prologue_size += 4;
|
||||
@ -569,7 +564,7 @@ function_prologue (FILE *file, int size)
|
||||
|
||||
if (interrupt_func_p)
|
||||
{
|
||||
prologue_size += out_set_stack_ptr (file, -1, 1);
|
||||
prologue_size += out_set_stack_ptr (file, 1, 1);
|
||||
}
|
||||
else if (signal_func_p)
|
||||
{
|
||||
@ -1288,6 +1283,33 @@ init_cumulative_args (cum, fntype, libname, indirect)
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the number of registers to allocate for a function argument. */
|
||||
|
||||
static int
|
||||
avr_num_arg_regs (mode, type)
|
||||
enum machine_mode mode;
|
||||
tree type;
|
||||
{
|
||||
int size;
|
||||
|
||||
if (mode == BLKmode)
|
||||
size = int_size_in_bytes (type);
|
||||
else
|
||||
size = GET_MODE_SIZE (mode);
|
||||
|
||||
/* Align all function arguments to start in even-numbered registers,
|
||||
for "movw" on the enhanced core (to keep call conventions the same
|
||||
on all devices, do it even if "movw" is not available). Odd-sized
|
||||
arguments leave holes above them - registers still available for
|
||||
other uses. Use -mpack-args for compatibility with old asm code
|
||||
(the new convention will still be used for libgcc calls). */
|
||||
|
||||
if (!(type && TARGET_PACK_ARGS))
|
||||
size += size & 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Controls whether a function argument is passed
|
||||
in a register, and which register. */
|
||||
|
||||
@ -1298,12 +1320,11 @@ function_arg (cum, mode, type, named)
|
||||
tree type;
|
||||
int named ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
|
||||
int bytes = avr_num_arg_regs (mode, type);
|
||||
|
||||
if (cum->nregs && bytes <= cum->nregs)
|
||||
return gen_rtx (REG, mode, cum->regno - bytes);
|
||||
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
@ -1317,9 +1338,8 @@ function_arg_advance (cum, mode, type, named)
|
||||
tree type; /* type of the argument or 0 if lib support */
|
||||
int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
|
||||
{
|
||||
int bytes;
|
||||
int bytes = avr_num_arg_regs (mode, type);
|
||||
|
||||
bytes = (mode == BLKmode ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
|
||||
cum->nregs -= bytes;
|
||||
cum->regno -= bytes;
|
||||
|
||||
@ -1328,8 +1348,6 @@ function_arg_advance (cum, mode, type, named)
|
||||
cum->nregs = 0;
|
||||
cum->regno = FIRST_CUM_REG;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -1788,16 +1806,33 @@ output_movsisf(insn, operands, which_alternative)
|
||||
{
|
||||
case 0: /* mov r,r */
|
||||
if (true_regnum (operands[0]) > true_regnum (operands[1]))
|
||||
return (AS2 (mov,%D0,%D1) CR_TAB
|
||||
AS2 (mov,%C0,%C1) CR_TAB
|
||||
AS2 (mov,%B0,%B1) CR_TAB
|
||||
AS2 (mov,%A0,%A1));
|
||||
{
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS2 (movw,%C0,%C1) CR_TAB
|
||||
AS2 (movw,%A0,%A1)); /* FIXME: length = 4 -> 2 */
|
||||
else
|
||||
return (AS2 (mov,%D0,%D1) CR_TAB
|
||||
AS2 (mov,%C0,%C1) CR_TAB
|
||||
AS2 (mov,%B0,%B1) CR_TAB
|
||||
AS2 (mov,%A0,%A1));
|
||||
}
|
||||
else
|
||||
return (AS2 (mov,%A0,%A1) CR_TAB
|
||||
AS2 (mov,%B0,%B1) CR_TAB
|
||||
AS2 (mov,%C0,%C1) CR_TAB
|
||||
AS2 (mov,%D0,%D1));
|
||||
{
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS2 (movw,%A0,%A1) CR_TAB
|
||||
AS2 (movw,%C0,%C1)); /* FIXME: length = 4 -> 2 */
|
||||
else
|
||||
return (AS2 (mov,%A0,%A1) CR_TAB
|
||||
AS2 (mov,%B0,%B1) CR_TAB
|
||||
AS2 (mov,%C0,%C1) CR_TAB
|
||||
AS2 (mov,%D0,%D1));
|
||||
}
|
||||
case 1: /* mov r,L */
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS1 (clr,%A0) CR_TAB
|
||||
AS1 (clr,%B0) CR_TAB
|
||||
AS2 (movw,%C0,%A0)); /* FIXME: length = 4 -> 3 */
|
||||
|
||||
return (AS1 (clr,%A0) CR_TAB
|
||||
AS1 (clr,%B0) CR_TAB
|
||||
AS1 (clr,%C0) CR_TAB
|
||||
@ -2052,7 +2087,7 @@ out_tsthi (insn,l)
|
||||
if (l) *l = 1;
|
||||
return AS1 (tst,%B0);
|
||||
}
|
||||
if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
|
||||
if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
|
||||
{
|
||||
if (l) *l = 1;
|
||||
return AS2 (sbiw,%0,0);
|
||||
@ -2080,7 +2115,7 @@ out_tstsi (insn,l)
|
||||
if (l) *l = 1;
|
||||
return AS1 (tst,%D0);
|
||||
}
|
||||
if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
|
||||
if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
|
||||
{
|
||||
if (l) *l = 3;
|
||||
return (AS2 (sbiw,%A0,0) CR_TAB
|
||||
@ -2142,7 +2177,7 @@ out_shift_with_cnt (template,insn,operands,len)
|
||||
*len = mov_len + 1;
|
||||
}
|
||||
}
|
||||
else if (register_operand (operands[2],QImode))
|
||||
else if (register_operand (operands[2], QImode))
|
||||
{
|
||||
if (reg_unused_after (insn, operands[2]))
|
||||
op[3] = op[2];
|
||||
@ -2211,7 +2246,7 @@ ashlqi3_out (insn,operands,len)
|
||||
AS1 (lsl,%0));
|
||||
|
||||
case 4:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len = 2;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2224,7 +2259,7 @@ ashlqi3_out (insn,operands,len)
|
||||
AS1 (lsl,%0));
|
||||
|
||||
case 5:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len = 3;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2239,7 +2274,7 @@ ashlqi3_out (insn,operands,len)
|
||||
AS1 (lsl,%0));
|
||||
|
||||
case 6:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len = 4;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2376,6 +2411,13 @@ ashlsi3_out (insn,operands,len)
|
||||
int reg0 = true_regnum (operands[0]);
|
||||
int reg1 = true_regnum (operands[1]);
|
||||
*len = 4;
|
||||
if (TARGET_ENHANCED && (reg0 + 2 != reg1))
|
||||
{
|
||||
*len = 3;
|
||||
return (AS2 (movw,%C0,%A1) CR_TAB
|
||||
AS1 (clr,%B0) CR_TAB
|
||||
AS1 (clr,%A0));
|
||||
}
|
||||
if (reg0 + 1 >= reg1)
|
||||
return (AS2 (mov,%D0,%B1) CR_TAB
|
||||
AS2 (mov,%C0,%A1) CR_TAB
|
||||
@ -2610,6 +2652,15 @@ ashrsi3_out (insn,operands,len)
|
||||
int reg0 = true_regnum (operands[0]);
|
||||
int reg1 = true_regnum (operands[1]);
|
||||
*len=6;
|
||||
if (TARGET_ENHANCED && (reg0 != reg1 + 2))
|
||||
{
|
||||
*len = 5;
|
||||
return (AS2 (movw,%A0,%C1) CR_TAB
|
||||
AS1 (clr,%D0) CR_TAB
|
||||
AS2 (sbrc,%B0,7) CR_TAB
|
||||
AS1 (com,%D0) CR_TAB
|
||||
AS2 (mov,%C0,%D0));
|
||||
}
|
||||
if (reg0 <= reg1 + 1)
|
||||
return (AS2 (mov,%A0,%C1) CR_TAB
|
||||
AS2 (mov,%B0,%D1) CR_TAB
|
||||
@ -2693,7 +2744,7 @@ lshrqi3_out (insn,operands,len)
|
||||
AS1 (lsr,%0));
|
||||
|
||||
case 4:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len=2;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2706,7 +2757,7 @@ lshrqi3_out (insn,operands,len)
|
||||
AS1 (lsr,%0));
|
||||
|
||||
case 5:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len = 3;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2721,7 +2772,7 @@ lshrqi3_out (insn,operands,len)
|
||||
AS1 (lsr,%0));
|
||||
|
||||
case 6:
|
||||
if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
|
||||
if (test_hard_reg_class (LD_REGS, operands[0]))
|
||||
{
|
||||
*len = 4;
|
||||
return (AS1 (swap,%0) CR_TAB
|
||||
@ -2860,6 +2911,13 @@ lshrsi3_out (insn,operands,len)
|
||||
int reg0 = true_regnum (operands[0]);
|
||||
int reg1 = true_regnum (operands[1]);
|
||||
*len = 4;
|
||||
if (TARGET_ENHANCED && (reg0 != reg1 + 2))
|
||||
{
|
||||
*len = 3;
|
||||
return (AS2 (movw,%A0,%C1) CR_TAB
|
||||
AS1 (clr,%C0) CR_TAB
|
||||
AS1 (clr,%D0));
|
||||
}
|
||||
if (reg0 <= reg1 + 1)
|
||||
return (AS2 (mov,%A0,%C1) CR_TAB
|
||||
AS2 (mov,%B0,%D1) CR_TAB
|
||||
@ -3275,7 +3333,7 @@ asm_output_section_name(file, decl, name, reloc)
|
||||
const char *name;
|
||||
int reloc ATTRIBUTE_UNUSED;
|
||||
{
|
||||
fprintf (file, ".section\t%s,\"%s\",@progbits\n", name, \
|
||||
fprintf (file, ".section %s, \"%s\", @progbits\n", name,
|
||||
decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" :
|
||||
decl && TREE_READONLY (decl) ? "a" : "aw");
|
||||
}
|
||||
@ -3407,9 +3465,9 @@ valid_machine_type_attribute(type, attributes, identifier, args)
|
||||
Valid attributes:
|
||||
progmem - put data to program memory;
|
||||
signal - make a function to be hardware interrupt. After function
|
||||
epilogue interrupts are disabled;
|
||||
prologue interrupts are disabled;
|
||||
interrupt - make a function to be hardware interrupt. After function
|
||||
epilogue interrupts are enabled;
|
||||
prologue interrupts are enabled;
|
||||
naked - don't generate function prologue/epilogue and `ret' command. */
|
||||
|
||||
int
|
||||
@ -3440,7 +3498,7 @@ valid_machine_decl_attribute (decl, attributes, attr, args)
|
||||
|
||||
|
||||
/* Look for attribute `progmem' in DECL
|
||||
founded - 1 otherwise 0 */
|
||||
if found return 1, otherwise 0. */
|
||||
|
||||
int
|
||||
avr_progmem_p (decl)
|
||||
@ -3481,6 +3539,7 @@ encode_section_info (decl)
|
||||
{
|
||||
char * dsec = ".progmem.data";
|
||||
DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
|
||||
TREE_READONLY (decl) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3864,7 +3923,7 @@ avr_function_value (type,func)
|
||||
return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
|
||||
}
|
||||
|
||||
/* Returns non-zero if number MASK have only one setted bit */
|
||||
/* Returns non-zero if the number MASK has only one bit set. */
|
||||
|
||||
int
|
||||
mask_one_bit_p (mask)
|
||||
@ -3892,7 +3951,7 @@ mask_one_bit_p (mask)
|
||||
in class CLASS. */
|
||||
|
||||
enum reg_class
|
||||
preferred_reload_class(x,class)
|
||||
preferred_reload_class (x, class)
|
||||
rtx x;
|
||||
enum reg_class class;
|
||||
{
|
||||
@ -3908,7 +3967,7 @@ preferred_reload_class(x,class)
|
||||
}
|
||||
|
||||
int
|
||||
test_hard_reg_class(class, x)
|
||||
test_hard_reg_class (class, x)
|
||||
enum reg_class class;
|
||||
rtx x;
|
||||
{
|
||||
@ -3946,9 +4005,9 @@ jump_over_one_insn_p (insn, dest)
|
||||
}
|
||||
|
||||
/* Returns 1 if a value of mode MODE can be stored starting with hard
|
||||
register number REGNO. On the enhanced core, it should be a win to
|
||||
align modes larger than QI on even register numbers (even if < 24).
|
||||
so that the "movw" instruction can be used on them. */
|
||||
register number REGNO. On the enhanced core, anything larger than
|
||||
1 byte must start in even numbered register for "movw" to work
|
||||
(this way we don't have to check for odd registers everywhere). */
|
||||
|
||||
int
|
||||
avr_hard_regno_mode_ok (regno, mode)
|
||||
@ -3957,7 +4016,7 @@ avr_hard_regno_mode_ok (regno, mode)
|
||||
{
|
||||
if (mode == QImode)
|
||||
return 1;
|
||||
if (regno < 24 /* && !TARGET_ENHANCED */ )
|
||||
if (regno < 24 && !TARGET_ENHANCED)
|
||||
return 1;
|
||||
return !(regno & 1);
|
||||
}
|
||||
|
@ -249,6 +249,9 @@
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0: /* mov r,r */
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS2 (movw,%0,%1)); /* FIXME: length = 2 -> 1 */
|
||||
|
||||
if (true_regnum (operands[0]) > true_regnum (operands[1]))
|
||||
return (AS2 (mov,%B0,%B1) CR_TAB
|
||||
AS2 (mov,%A0,%A1));
|
||||
@ -653,6 +656,57 @@
|
||||
[(set_attr "length" "4,4")
|
||||
(set_attr "cc" "set_czn,set_czn")])
|
||||
|
||||
;******************************************************************************
|
||||
; mul
|
||||
|
||||
(define_insn "mulqi3"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(mult:QI (match_operand:QI 1 "register_operand" "r")
|
||||
(match_operand:QI 2 "register_operand" "r")))]
|
||||
"TARGET_ENHANCED"
|
||||
"mul %1,%2
|
||||
mov %0,r0
|
||||
clr r1"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "mulqihi3"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
|
||||
(sign_extend:HI (match_operand:QI 2 "register_operand" "d"))))]
|
||||
"TARGET_ENHANCED"
|
||||
"muls %1,%2
|
||||
movw %0,r0
|
||||
clr r1"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "umulqihi3"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r")
|
||||
(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
|
||||
(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
|
||||
"TARGET_ENHANCED"
|
||||
"mul %1,%2
|
||||
movw %0,r0
|
||||
clr r1"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "mulhi3"
|
||||
[(set (match_operand:HI 0 "register_operand" "=&r")
|
||||
(mult:HI (match_operand:HI 1 "register_operand" "r")
|
||||
(match_operand:HI 2 "register_operand" "r")))]
|
||||
"TARGET_ENHANCED"
|
||||
"mul %A1,%A2
|
||||
movw %0,r0
|
||||
mul %A1,%B2
|
||||
add %B0,r0
|
||||
mul %B1,%A2
|
||||
add %B0,r0
|
||||
clr r1"
|
||||
[(set_attr "length" "7")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
; and
|
||||
|
||||
@ -1604,9 +1658,15 @@
|
||||
if (which_alternative==0)
|
||||
return \"icall\";
|
||||
else if (which_alternative==1)
|
||||
return (AS2 (mov, r30,%A0) CR_TAB
|
||||
AS2 (mov, r31,%B0) CR_TAB
|
||||
\"icall\");
|
||||
{
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS2 (movw, r30, %0) CR_TAB
|
||||
\"icall\");
|
||||
else
|
||||
return (AS2 (mov, r30, %A0) CR_TAB
|
||||
AS2 (mov, r31, %B0) CR_TAB
|
||||
\"icall\");
|
||||
}
|
||||
else if (!AVR_MEGA)
|
||||
return AS1(rcall,%c0);
|
||||
return AS1(call,%c0);
|
||||
@ -1634,9 +1694,15 @@
|
||||
if (which_alternative==0)
|
||||
return \"icall\";
|
||||
else if (which_alternative==1)
|
||||
return (AS2 (mov, r30,%A1) CR_TAB
|
||||
AS2 (mov, r31,%B1) CR_TAB
|
||||
\"icall\");
|
||||
{
|
||||
if (TARGET_ENHANCED)
|
||||
return (AS2 (movw, r30, %1) CR_TAB
|
||||
\"icall\");
|
||||
else
|
||||
return (AS2 (mov, r30, %A1) CR_TAB
|
||||
AS2 (mov, r31, %B1) CR_TAB
|
||||
\"icall\");
|
||||
}
|
||||
else if (!AVR_MEGA)
|
||||
return AS1(rcall,%c1);
|
||||
return AS1(call,%c1);
|
||||
@ -1676,6 +1742,21 @@
|
||||
"optimize"
|
||||
"")
|
||||
|
||||
(define_insn "*tablejump_enh"
|
||||
[(set (pc) (mem:HI
|
||||
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
(label_ref (match_operand 2 "" "")))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
"TARGET_ENHANCED"
|
||||
"subi r30,lo8(-(%2))
|
||||
sbci r31,hi8(-(%2))
|
||||
lpm __tmp_reg__,Z+
|
||||
lpm r31,Z
|
||||
mov r30,__tmp_reg__
|
||||
ijmp"
|
||||
[(set_attr "length" "6")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "*tablejump"
|
||||
[(set (pc) (mem:HI
|
||||
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
@ -1686,10 +1767,10 @@
|
||||
sbci r31,hi8(-(%2))
|
||||
lpm
|
||||
push r0
|
||||
adiw r30,1
|
||||
adiw r30,1
|
||||
lpm
|
||||
push r0
|
||||
ret"
|
||||
ret"
|
||||
[(set_attr "length" "8")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */
|
||||
*******************************************************/
|
||||
#if defined (Lmulqi3)
|
||||
|
||||
#define r_arg2 r25 /* multiplicand */
|
||||
#define r_arg2 r22 /* multiplicand */
|
||||
#define r_arg1 r24 /* multiplier */
|
||||
#define r_res __tmp_reg__ /* result */
|
||||
|
||||
@ -201,8 +201,8 @@ __mulsi3_exit:
|
||||
Division 8 / 8 => (result + remainder)
|
||||
*******************************************************/
|
||||
#define r_rem r26 /* remainder */
|
||||
#define r_arg1 r25 /* dividend */
|
||||
#define r_arg2 r24 /* divisor */
|
||||
#define r_arg1 r24 /* dividend */
|
||||
#define r_arg2 r22 /* divisor */
|
||||
#define r_cnt r27 /* loop count */
|
||||
|
||||
#if defined (Lumodqi3)
|
||||
@ -272,8 +272,7 @@ __divqi3_1:
|
||||
sbrc __tmp_reg__,7
|
||||
neg r_arg1 ; correct result sign
|
||||
__divqi3_exit:
|
||||
mov r24,r_arg1 ; put result to return register
|
||||
ret
|
||||
ret ; result already in r24 (r_arg1)
|
||||
.endfunc
|
||||
#endif /* defined (Ldivqi3) */
|
||||
|
||||
@ -434,8 +433,6 @@ _umodsi3_ret:
|
||||
mov r24,r_remHL
|
||||
mov r23,r_remH
|
||||
mov r22,r_remL
|
||||
.global _cleanup
|
||||
_cleanup:
|
||||
ret
|
||||
.endfunc
|
||||
#endif /* defined (Lumodsi3) */
|
||||
@ -630,9 +627,12 @@ __epilogue_restores__:
|
||||
#endif /* defined (Lepilogue) */
|
||||
|
||||
#ifdef L__exit
|
||||
.global _exit
|
||||
.weak _exit
|
||||
.func _exit
|
||||
_exit:
|
||||
rjmp _exit
|
||||
.weak _cleanup
|
||||
_cleanup:
|
||||
ret
|
||||
.endfunc
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user