mirror of git://gcc.gnu.org/git/gcc.git
re PR target/50931 ([avr] Support a 24-bit scalar integer mode)
gcc/ PR target/50931 * config/avr/avr-modes.def: New file defining PSImode. * config/avr/avr-c.c (__INT24_MAX__, __INT24_MIN__, __UINT24_MAX__): New built-in defines. * config/avr/avr.md (adjust_len): Add tstpsi, mov24, reload_in24, ashlpsi, ashrpsi, lshrpsi. (QISO, QIDI, HISI, HIDI, MPUSH, rotx, rotsmode): Add PSI. (MOVMODE): New mode iterator. (movpsi): New expander. (movqi, movhi, movsi, movsf, movpsi): Write as one using MOVMODE. (*reload_inpsi, *movpsi): New insns. (*reload_inpsi): New RTL peephole. (addpsi3, *addpsi3_zero_extend.qi, *addpsi3_zero_extend.hi, *addpsi3_sign_extend.hi): New insns. (subpsi3, *subpsi3_zero_extend.qi, *subpsi3_zero_extend.hi, *subpsi3_sign_extend.hi): New insns. (divmodpsi4, udivmodpsi4): New define insn-and-split. (*divmodpsi4_call, *udivmodpsi4_call): New insns. (andpsi3, iorpsi3, xorpsi3): New insns. (*rotlpsi2.1, *rotlpsi2.23): New insns. (*rotw<mode>): Insn condition only allow even-sized modes. (*rotb<mode>): Insn condition allows odd-sized modes. (ashlpsi3, ashrpsi3, lshrpsi3, *addpsi3.lt0): New insns. (negpsi2, one_cmplpsi2): New insns. (extendqipsi2, extendhipsi2, extendpsisi2): New insns. (zero_extendqipsi2, zero_extendhipsi2, zero_extendpsisi2): New insn-and-splits. (*cmppsi, *negated_tstpsi, *reversed_tstpsi): New insns. (cbranchpsi4): New expander. * config/avr/constraints.md (Ca3, Co3, Cx3): New constraints. * config/avr/avr-protos.h (avr_out_tstpsi, avr_out_movpsi, avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3, avr_out_reload_inpsi): New prototypes. * config/avr/avr.c (TARGET_SCALAR_MODE_SUPPORTED_P): Define to... (avr_scalar_mode_supported_p): ...this new static function. (avr_asm_len): Always return "". (avr_out_load_psi, avr_out_store_psi): New static functions. (avr_out_movpsi, avr_out_reload_inpsi): New functions. (avr_out_tstpsi): New function. (avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3): New functions. (avr_out_plus_1, output_reload_in_const): Handle 3-byte types. (avr_simplify_comparison_p): Ditto. (adjust_insn_length): Handle ADJUST_LEN_RELOAD_IN24, ADJUST_LEN_MOV24, ADJUST_LEN_TSTPSI, ADJUST_LEN_ASHLPSI, ADJUST_LEN_ASHRPSI, ADJUST_LEN_LSHRPSI. (avr_rtx_costs_1): Report PSI costs. (avr_libcall_value): Handle odd-sized parameters. (avr_init_builtin_int24): New static function to define built-in 24-bit types __int24 and __uint24. (avr_init_builtins): Use it. libgcc/ PR target/50931 * config/t-avr (LIB1ASMFUNCS): Add _divmodpsi4, _udivmodpsi4. * config/lib1funcs.S (__udivmodpsi4, __divmodpsi4): New functions. From-SVN: r180962
This commit is contained in:
parent
2fcc5e6474
commit
e4fe948a6e
|
|
@ -1,4 +1,58 @@
|
||||||
2011-11-04 Thomas Doerfler <thomas.doerfler@embedded-brains.de>
|
2011-11-04 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/50931
|
||||||
|
* config/avr/avr-modes.def: New file defining PSImode.
|
||||||
|
* config/avr/avr-c.c (__INT24_MAX__, __INT24_MIN__,
|
||||||
|
__UINT24_MAX__): New built-in defines.
|
||||||
|
* config/avr/avr.md (adjust_len): Add tstpsi, mov24, reload_in24,
|
||||||
|
ashlpsi, ashrpsi, lshrpsi.
|
||||||
|
(QISO, QIDI, HISI, HIDI, MPUSH, rotx, rotsmode): Add PSI.
|
||||||
|
(MOVMODE): New mode iterator.
|
||||||
|
(movpsi): New expander.
|
||||||
|
(movqi, movhi, movsi, movsf, movpsi): Write as one using MOVMODE.
|
||||||
|
(*reload_inpsi, *movpsi): New insns.
|
||||||
|
(*reload_inpsi): New RTL peephole.
|
||||||
|
(addpsi3, *addpsi3_zero_extend.qi, *addpsi3_zero_extend.hi,
|
||||||
|
*addpsi3_sign_extend.hi): New insns.
|
||||||
|
(subpsi3, *subpsi3_zero_extend.qi, *subpsi3_zero_extend.hi,
|
||||||
|
*subpsi3_sign_extend.hi): New insns.
|
||||||
|
(divmodpsi4, udivmodpsi4): New define insn-and-split.
|
||||||
|
(*divmodpsi4_call, *udivmodpsi4_call): New insns.
|
||||||
|
(andpsi3, iorpsi3, xorpsi3): New insns.
|
||||||
|
(*rotlpsi2.1, *rotlpsi2.23): New insns.
|
||||||
|
(*rotw<mode>): Insn condition only allow even-sized modes.
|
||||||
|
(*rotb<mode>): Insn condition allows odd-sized modes.
|
||||||
|
(ashlpsi3, ashrpsi3, lshrpsi3, *addpsi3.lt0): New insns.
|
||||||
|
(negpsi2, one_cmplpsi2): New insns.
|
||||||
|
(extendqipsi2, extendhipsi2, extendpsisi2): New insns.
|
||||||
|
(zero_extendqipsi2, zero_extendhipsi2, zero_extendpsisi2): New
|
||||||
|
insn-and-splits.
|
||||||
|
(*cmppsi, *negated_tstpsi, *reversed_tstpsi): New insns.
|
||||||
|
(cbranchpsi4): New expander.
|
||||||
|
* config/avr/constraints.md (Ca3, Co3, Cx3): New constraints.
|
||||||
|
* config/avr/avr-protos.h (avr_out_tstpsi, avr_out_movpsi,
|
||||||
|
avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3,
|
||||||
|
avr_out_reload_inpsi): New prototypes.
|
||||||
|
|
||||||
|
* config/avr/avr.c (TARGET_SCALAR_MODE_SUPPORTED_P): Define to...
|
||||||
|
(avr_scalar_mode_supported_p): ...this new static function.
|
||||||
|
(avr_asm_len): Always return "".
|
||||||
|
(avr_out_load_psi, avr_out_store_psi): New static functions.
|
||||||
|
(avr_out_movpsi, avr_out_reload_inpsi): New functions.
|
||||||
|
(avr_out_tstpsi): New function.
|
||||||
|
(avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3): New functions.
|
||||||
|
(avr_out_plus_1, output_reload_in_const): Handle 3-byte types.
|
||||||
|
(avr_simplify_comparison_p): Ditto.
|
||||||
|
(adjust_insn_length): Handle ADJUST_LEN_RELOAD_IN24,
|
||||||
|
ADJUST_LEN_MOV24, ADJUST_LEN_TSTPSI, ADJUST_LEN_ASHLPSI,
|
||||||
|
ADJUST_LEN_ASHRPSI, ADJUST_LEN_LSHRPSI.
|
||||||
|
(avr_rtx_costs_1): Report PSI costs.
|
||||||
|
(avr_libcall_value): Handle odd-sized parameters.
|
||||||
|
(avr_init_builtin_int24): New static function to define built-in
|
||||||
|
24-bit types __int24 and __uint24.
|
||||||
|
(avr_init_builtins): Use it.
|
||||||
|
|
||||||
|
2011-11-04 Thomas Doerfler <thomas.doerfler@embedded-brains.de>
|
||||||
|
|
||||||
PR target/50989
|
PR target/50989
|
||||||
* config/arm/rtems-elf.h, config/arm/t-rtems: Add optional
|
* config/arm/rtems-elf.h, config/arm/t-rtems: Add optional
|
||||||
|
|
|
||||||
|
|
@ -105,4 +105,8 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
|
||||||
cpp_define (pfile, "__BUILTIN_AVR_FMUL");
|
cpp_define (pfile, "__BUILTIN_AVR_FMUL");
|
||||||
cpp_define (pfile, "__BUILTIN_AVR_FMULS");
|
cpp_define (pfile, "__BUILTIN_AVR_FMULS");
|
||||||
cpp_define (pfile, "__BUILTIN_AVR_FMULSU");
|
cpp_define (pfile, "__BUILTIN_AVR_FMULSU");
|
||||||
|
|
||||||
|
cpp_define (pfile, "__INT24_MAX__=8388607L");
|
||||||
|
cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
|
||||||
|
cpp_define (pfile, "__UINT24_MAX__=16777215UL");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
FRACTIONAL_INT_MODE (PSI, 24, 3);
|
||||||
|
|
@ -59,8 +59,10 @@ extern const char *out_movsi_mr_r (rtx insn, rtx op[], int *l);
|
||||||
extern const char *output_movsisf (rtx insn, rtx operands[], int *l);
|
extern const char *output_movsisf (rtx insn, rtx operands[], int *l);
|
||||||
extern const char *avr_out_tstsi (rtx, rtx*, int*);
|
extern const char *avr_out_tstsi (rtx, rtx*, int*);
|
||||||
extern const char *avr_out_tsthi (rtx, rtx*, int*);
|
extern const char *avr_out_tsthi (rtx, rtx*, int*);
|
||||||
|
extern const char *avr_out_tstpsi (rtx, rtx*, int*);
|
||||||
extern const char *avr_out_compare (rtx, rtx*, int*);
|
extern const char *avr_out_compare (rtx, rtx*, int*);
|
||||||
extern const char *ret_cond_branch (rtx x, int len, int reverse);
|
extern const char *ret_cond_branch (rtx x, int len, int reverse);
|
||||||
|
extern const char *avr_out_movpsi (rtx, rtx*, int*);
|
||||||
|
|
||||||
extern const char *ashlqi3_out (rtx insn, rtx operands[], int *len);
|
extern const char *ashlqi3_out (rtx insn, rtx operands[], int *len);
|
||||||
extern const char *ashlhi3_out (rtx insn, rtx operands[], int *len);
|
extern const char *ashlhi3_out (rtx insn, rtx operands[], int *len);
|
||||||
|
|
@ -73,6 +75,11 @@ extern const char *ashrsi3_out (rtx insn, rtx operands[], int *len);
|
||||||
extern const char *lshrqi3_out (rtx insn, rtx operands[], int *len);
|
extern const char *lshrqi3_out (rtx insn, rtx operands[], int *len);
|
||||||
extern const char *lshrhi3_out (rtx insn, rtx operands[], int *len);
|
extern const char *lshrhi3_out (rtx insn, rtx operands[], int *len);
|
||||||
extern const char *lshrsi3_out (rtx insn, rtx operands[], int *len);
|
extern const char *lshrsi3_out (rtx insn, rtx operands[], int *len);
|
||||||
|
|
||||||
|
extern const char *avr_out_ashlpsi3 (rtx, rtx*, int*);
|
||||||
|
extern const char *avr_out_ashrpsi3 (rtx, rtx*, int*);
|
||||||
|
extern const char *avr_out_lshrpsi3 (rtx, rtx*, int*);
|
||||||
|
|
||||||
extern bool avr_rotate_bytes (rtx operands[]);
|
extern bool avr_rotate_bytes (rtx operands[]);
|
||||||
|
|
||||||
extern void expand_prologue (void);
|
extern void expand_prologue (void);
|
||||||
|
|
@ -93,6 +100,7 @@ extern int extra_constraint_Q (rtx x);
|
||||||
extern int adjust_insn_length (rtx insn, int len);
|
extern int adjust_insn_length (rtx insn, int len);
|
||||||
extern const char* output_reload_inhi (rtx*, rtx, int*);
|
extern const char* output_reload_inhi (rtx*, rtx, int*);
|
||||||
extern const char* output_reload_insisf (rtx*, rtx, int*);
|
extern const char* output_reload_insisf (rtx*, rtx, int*);
|
||||||
|
extern const char* avr_out_reload_inpsi (rtx*, rtx, int*);
|
||||||
extern void notice_update_cc (rtx body, rtx insn);
|
extern void notice_update_cc (rtx body, rtx insn);
|
||||||
extern void print_operand (FILE *file, rtx x, int code);
|
extern void print_operand (FILE *file, rtx x, int code);
|
||||||
extern void print_operand_address (FILE *file, rtx addr);
|
extern void print_operand_address (FILE *file, rtx addr);
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,9 @@ bool avr_need_copy_data_p = false;
|
||||||
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
|
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
|
||||||
#define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
|
#define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
|
||||||
|
|
||||||
|
#undef TARGET_SCALAR_MODE_SUPPORTED_P
|
||||||
|
#define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Custom function to replace string prefix.
|
/* Custom function to replace string prefix.
|
||||||
|
|
@ -369,6 +372,17 @@ avr_regno_reg_class (int r)
|
||||||
return ALL_REGS;
|
return ALL_REGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
avr_scalar_mode_supported_p (enum machine_mode mode)
|
||||||
|
{
|
||||||
|
if (PSImode == mode)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return default_scalar_mode_supported_p (mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A helper for the subsequent function attribute used to dig for
|
/* A helper for the subsequent function attribute used to dig for
|
||||||
attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
|
attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
|
||||||
|
|
||||||
|
|
@ -1487,7 +1501,7 @@ avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
|
||||||
|
|
||||||
|
|
||||||
/* Helper function to print assembler resp. track instruction
|
/* Helper function to print assembler resp. track instruction
|
||||||
sequence lengths.
|
sequence lengths. Always return "".
|
||||||
|
|
||||||
If PLEN == NULL:
|
If PLEN == NULL:
|
||||||
Output assembler code from template TPL with operands supplied
|
Output assembler code from template TPL with operands supplied
|
||||||
|
|
@ -1499,7 +1513,7 @@ avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
|
||||||
Don't output anything.
|
Don't output anything.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static const char*
|
||||||
avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
|
avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
|
||||||
{
|
{
|
||||||
if (NULL == plen)
|
if (NULL == plen)
|
||||||
|
|
@ -1513,6 +1527,8 @@ avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
|
||||||
else
|
else
|
||||||
*plen += n_words;
|
*plen += n_words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1562,6 +1578,8 @@ cond_string (enum rtx_code code)
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output ADDR to FILE as address. */
|
/* Output ADDR to FILE as address. */
|
||||||
|
|
@ -1968,6 +1986,7 @@ avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
|
||||||
{
|
{
|
||||||
unsigned int max = (mode == QImode ? 0xff :
|
unsigned int max = (mode == QImode ? 0xff :
|
||||||
mode == HImode ? 0xffff :
|
mode == HImode ? 0xffff :
|
||||||
|
mode == PSImode ? 0xffffff :
|
||||||
mode == SImode ? 0xffffffff : 0);
|
mode == SImode ? 0xffffffff : 0);
|
||||||
if (max && op && GET_CODE (x) == CONST_INT)
|
if (max && op && GET_CODE (x) == CONST_INT)
|
||||||
{
|
{
|
||||||
|
|
@ -2956,6 +2975,306 @@ output_movsisf (rtx insn, rtx operands[], int *l)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle loads of 24-bit types from memory to register. */
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
avr_out_load_psi (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
rtx dest = op[0];
|
||||||
|
rtx src = op[1];
|
||||||
|
rtx base = XEXP (src, 0);
|
||||||
|
int reg_dest = true_regnum (dest);
|
||||||
|
int reg_base = true_regnum (base);
|
||||||
|
|
||||||
|
if (reg_base > 0)
|
||||||
|
{
|
||||||
|
if (reg_base == REG_X) /* (R26) */
|
||||||
|
{
|
||||||
|
if (reg_dest == REG_X)
|
||||||
|
/* "ld r26,-X" is undefined */
|
||||||
|
return avr_asm_len ("adiw r26,2" CR_TAB
|
||||||
|
"ld r28,X" CR_TAB
|
||||||
|
"ld __tmp_reg__,-X" CR_TAB
|
||||||
|
"sbiw r26,1" CR_TAB
|
||||||
|
"ld r26,X" CR_TAB
|
||||||
|
"mov r27,__tmp_reg__", op, plen, -6);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
avr_asm_len ("ld %A0,X+" CR_TAB
|
||||||
|
"ld %B0,X+" CR_TAB
|
||||||
|
"ld %C0,X", op, plen, -3);
|
||||||
|
|
||||||
|
if (reg_dest != REG_X - 2
|
||||||
|
&& !reg_unused_after (insn, base))
|
||||||
|
{
|
||||||
|
avr_asm_len ("sbiw r26,2", op, plen, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* reg_base != REG_X */
|
||||||
|
{
|
||||||
|
if (reg_dest == reg_base)
|
||||||
|
return avr_asm_len ("ldd %C0,%1+2" CR_TAB
|
||||||
|
"ldd __tmp_reg__,%1+1" CR_TAB
|
||||||
|
"ld %A0,%1" CR_TAB
|
||||||
|
"mov %B0,__tmp_reg__", op, plen, -4);
|
||||||
|
else
|
||||||
|
return avr_asm_len ("ld %A0,%1" CR_TAB
|
||||||
|
"ldd %B0,%1+1" CR_TAB
|
||||||
|
"ldd %C0,%1+2", op, plen, -3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (GET_CODE (base) == PLUS) /* (R + i) */
|
||||||
|
{
|
||||||
|
int disp = INTVAL (XEXP (base, 1));
|
||||||
|
|
||||||
|
if (disp > MAX_LD_OFFSET (GET_MODE (src)))
|
||||||
|
{
|
||||||
|
if (REGNO (XEXP (base, 0)) != REG_Y)
|
||||||
|
fatal_insn ("incorrect insn:",insn);
|
||||||
|
|
||||||
|
if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
|
||||||
|
return avr_asm_len ("adiw r28,%o1-61" CR_TAB
|
||||||
|
"ldd %A0,Y+61" CR_TAB
|
||||||
|
"ldd %B0,Y+62" CR_TAB
|
||||||
|
"ldd %C0,Y+63" CR_TAB
|
||||||
|
"sbiw r28,%o1-61", op, plen, -5);
|
||||||
|
|
||||||
|
return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
|
||||||
|
"sbci r29,hi8(-%o1)" CR_TAB
|
||||||
|
"ld %A0,Y" CR_TAB
|
||||||
|
"ldd %B0,Y+1" CR_TAB
|
||||||
|
"ldd %C0,Y+2" CR_TAB
|
||||||
|
"subi r28,lo8(%o1)" CR_TAB
|
||||||
|
"sbci r29,hi8(%o1)", op, plen, -7);
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_base = true_regnum (XEXP (base, 0));
|
||||||
|
if (reg_base == REG_X)
|
||||||
|
{
|
||||||
|
/* R = (X + d) */
|
||||||
|
if (reg_dest == REG_X)
|
||||||
|
{
|
||||||
|
/* "ld r26,-X" is undefined */
|
||||||
|
return avr_asm_len ("adiw r26,%o1+2" CR_TAB
|
||||||
|
"ld r28,X" CR_TAB
|
||||||
|
"ld __tmp_reg__,-X" CR_TAB
|
||||||
|
"sbiw r26,1" CR_TAB
|
||||||
|
"ld r26,X" CR_TAB
|
||||||
|
"mov r27,__tmp_reg__", op, plen, -6);
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_asm_len ("adiw r26,%o1" CR_TAB
|
||||||
|
"ld r24,X+" CR_TAB
|
||||||
|
"ld r25,X+" CR_TAB
|
||||||
|
"ld r26,X", op, plen, -4);
|
||||||
|
|
||||||
|
if (reg_dest != REG_X - 2)
|
||||||
|
avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg_dest == reg_base)
|
||||||
|
return avr_asm_len ("ldd %C0,%C1" CR_TAB
|
||||||
|
"ldd __tmp_reg__,%B1" CR_TAB
|
||||||
|
"ldd %A0,%A1" CR_TAB
|
||||||
|
"mov %B0,__tmp_reg__", op, plen, -4);
|
||||||
|
|
||||||
|
return avr_asm_len ("ldd %A0,%A1" CR_TAB
|
||||||
|
"ldd %B0,%B1" CR_TAB
|
||||||
|
"ldd %C0,%C1", op, plen, -3);
|
||||||
|
}
|
||||||
|
else if (GET_CODE (base) == PRE_DEC) /* (--R) */
|
||||||
|
return avr_asm_len ("ld %C0,%1" CR_TAB
|
||||||
|
"ld %B0,%1" CR_TAB
|
||||||
|
"ld %A0,%1", op, plen, -3);
|
||||||
|
else if (GET_CODE (base) == POST_INC) /* (R++) */
|
||||||
|
return avr_asm_len ("ld %A0,%1" CR_TAB
|
||||||
|
"ld %B0,%1" CR_TAB
|
||||||
|
"ld %C0,%1", op, plen, -3);
|
||||||
|
|
||||||
|
else if (CONSTANT_ADDRESS_P (base))
|
||||||
|
return avr_asm_len ("lds %A0,%m1" CR_TAB
|
||||||
|
"lds %B0,%m1+1" CR_TAB
|
||||||
|
"lds %C0,%m1+2", op, plen , -6);
|
||||||
|
|
||||||
|
fatal_insn ("unknown move insn:",insn);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle store of 24-bit type from register or zero to memory. */
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
avr_out_store_psi (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
rtx dest = op[0];
|
||||||
|
rtx src = op[1];
|
||||||
|
rtx base = XEXP (dest, 0);
|
||||||
|
int reg_base = true_regnum (base);
|
||||||
|
|
||||||
|
if (CONSTANT_ADDRESS_P (base))
|
||||||
|
return avr_asm_len ("sts %m0,%A1" CR_TAB
|
||||||
|
"sts %m0+1,%B1" CR_TAB
|
||||||
|
"sts %m0+2,%C1", op, plen, -6);
|
||||||
|
|
||||||
|
if (reg_base > 0) /* (r) */
|
||||||
|
{
|
||||||
|
if (reg_base == REG_X) /* (R26) */
|
||||||
|
{
|
||||||
|
gcc_assert (!reg_overlap_mentioned_p (base, src));
|
||||||
|
|
||||||
|
avr_asm_len ("st %0+,%A1" CR_TAB
|
||||||
|
"st %0+,%B1" CR_TAB
|
||||||
|
"st %0,%C1", op, plen, -3);
|
||||||
|
|
||||||
|
if (!reg_unused_after (insn, base))
|
||||||
|
avr_asm_len ("sbiw r26,2", op, plen, 1);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return avr_asm_len ("st %0,%A1" CR_TAB
|
||||||
|
"std %0+1,%B1" CR_TAB
|
||||||
|
"std %0+2,%C1", op, plen, -3);
|
||||||
|
}
|
||||||
|
else if (GET_CODE (base) == PLUS) /* (R + i) */
|
||||||
|
{
|
||||||
|
int disp = INTVAL (XEXP (base, 1));
|
||||||
|
reg_base = REGNO (XEXP (base, 0));
|
||||||
|
|
||||||
|
if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
|
||||||
|
{
|
||||||
|
if (reg_base != REG_Y)
|
||||||
|
fatal_insn ("incorrect insn:",insn);
|
||||||
|
|
||||||
|
if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
|
||||||
|
return avr_asm_len ("adiw r28,%o0-61" CR_TAB
|
||||||
|
"std Y+61,%A1" CR_TAB
|
||||||
|
"std Y+62,%B1" CR_TAB
|
||||||
|
"std Y+63,%C1" CR_TAB
|
||||||
|
"sbiw r28,%o0-60", op, plen, -5);
|
||||||
|
|
||||||
|
return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
|
||||||
|
"sbci r29,hi8(-%o0)" CR_TAB
|
||||||
|
"st Y,%A1" CR_TAB
|
||||||
|
"std Y+1,%B1" CR_TAB
|
||||||
|
"std Y+2,%C1" CR_TAB
|
||||||
|
"subi r28,lo8(%o0)" CR_TAB
|
||||||
|
"sbci r29,hi8(%o0)", op, plen, -7);
|
||||||
|
}
|
||||||
|
if (reg_base == REG_X)
|
||||||
|
{
|
||||||
|
/* (X + d) = R */
|
||||||
|
gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
|
||||||
|
|
||||||
|
avr_asm_len ("adiw r26,%o0" CR_TAB
|
||||||
|
"st X+,%A1" CR_TAB
|
||||||
|
"st X+,%B1" CR_TAB
|
||||||
|
"st X,%C1", op, plen, -4);
|
||||||
|
|
||||||
|
if (!reg_unused_after (insn, XEXP (base, 0)))
|
||||||
|
avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return avr_asm_len ("std %A0,%A1" CR_TAB
|
||||||
|
"std %B0,%B1" CR_TAB
|
||||||
|
"std %C0,%C1", op, plen, -3);
|
||||||
|
}
|
||||||
|
else if (GET_CODE (base) == PRE_DEC) /* (--R) */
|
||||||
|
return avr_asm_len ("st %0,%C1" CR_TAB
|
||||||
|
"st %0,%B1" CR_TAB
|
||||||
|
"st %0,%A1", op, plen, -3);
|
||||||
|
else if (GET_CODE (base) == POST_INC) /* (R++) */
|
||||||
|
return avr_asm_len ("st %0,%A1" CR_TAB
|
||||||
|
"st %0,%B1" CR_TAB
|
||||||
|
"st %0,%C1", op, plen, -3);
|
||||||
|
|
||||||
|
fatal_insn ("unknown move insn:",insn);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Move around 24-bit stuff. */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
avr_out_movpsi (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
rtx dest = op[0];
|
||||||
|
rtx src = op[1];
|
||||||
|
|
||||||
|
if (register_operand (dest, VOIDmode))
|
||||||
|
{
|
||||||
|
if (register_operand (src, VOIDmode)) /* mov r,r */
|
||||||
|
{
|
||||||
|
if (true_regnum (dest) > true_regnum (src))
|
||||||
|
{
|
||||||
|
avr_asm_len ("mov %C0,%C1", op, plen, -1);
|
||||||
|
|
||||||
|
if (AVR_HAVE_MOVW)
|
||||||
|
return avr_asm_len ("movw %A0,%A1", op, plen, 1);
|
||||||
|
else
|
||||||
|
return avr_asm_len ("mov %B0,%B1" CR_TAB
|
||||||
|
"mov %A0,%A1", op, plen, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (AVR_HAVE_MOVW)
|
||||||
|
avr_asm_len ("movw %A0,%A1", op, plen, -1);
|
||||||
|
else
|
||||||
|
avr_asm_len ("mov %A0,%A1" CR_TAB
|
||||||
|
"mov %B0,%B1", op, plen, -2);
|
||||||
|
|
||||||
|
return avr_asm_len ("mov %C0,%C1", op, plen, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CONST_INT_P (src))
|
||||||
|
{
|
||||||
|
return avr_out_reload_inpsi (op, NULL_RTX, plen);
|
||||||
|
}
|
||||||
|
else if (CONSTANT_P (src))
|
||||||
|
{
|
||||||
|
if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
|
||||||
|
{
|
||||||
|
return avr_asm_len ("ldi %A0,lo8(%1)" CR_TAB
|
||||||
|
"ldi %B0,hi8(%1)" CR_TAB
|
||||||
|
"ldi %C0,hh8(%1)", op, plen, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last resort, better than loading from memory. */
|
||||||
|
return avr_asm_len ("mov __tmp_reg__,r31" CR_TAB
|
||||||
|
"ldi r31,lo8(%1)" CR_TAB
|
||||||
|
"mov %A0,r31" CR_TAB
|
||||||
|
"ldi r31,hi8(%1)" CR_TAB
|
||||||
|
"mov %B0,r31" CR_TAB
|
||||||
|
"ldi r31,hh8(%1)" CR_TAB
|
||||||
|
"mov %C0,r31" CR_TAB
|
||||||
|
"mov r31,__tmp_reg__", op, plen, -8);
|
||||||
|
}
|
||||||
|
else if (MEM_P (src))
|
||||||
|
return avr_out_load_psi (insn, op, plen); /* mov r,m */
|
||||||
|
}
|
||||||
|
else if (MEM_P (dest))
|
||||||
|
{
|
||||||
|
if (src == CONST0_RTX (GET_MODE (dest)))
|
||||||
|
op[1] = zero_reg_rtx;
|
||||||
|
|
||||||
|
avr_out_store_psi (insn, op, plen);
|
||||||
|
|
||||||
|
op[1] = src;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal_insn ("invalid insn:", insn);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
out_movqi_mr_r (rtx insn, rtx op[], int *l)
|
out_movqi_mr_r (rtx insn, rtx op[], int *l)
|
||||||
{
|
{
|
||||||
|
|
@ -3280,22 +3599,24 @@ avr_out_compare (rtx insn, rtx *xop, int *plen)
|
||||||
avr_asm_len ("dec %A0" CR_TAB
|
avr_asm_len ("dec %A0" CR_TAB
|
||||||
"or %A0,%B0", xop, plen, 2);
|
"or %A0,%B0", xop, plen, 2);
|
||||||
|
|
||||||
if (n_bytes == 4)
|
if (n_bytes >= 3)
|
||||||
avr_asm_len ("or %A0,%C0" CR_TAB
|
avr_asm_len ("or %A0,%C0", xop, plen, 1);
|
||||||
"or %A0,%D0", xop, plen, 2);
|
|
||||||
|
if (n_bytes >= 4)
|
||||||
|
avr_asm_len ("or %A0,%D0", xop, plen, 1);
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
else if (xval == constm1_rtx)
|
else if (xval == constm1_rtx)
|
||||||
{
|
{
|
||||||
if (n_bytes == 4)
|
if (n_bytes >= 4)
|
||||||
avr_asm_len ("and %A0,%D0" CR_TAB
|
avr_asm_len ("and %A0,%D0", xop, plen, 1);
|
||||||
"and %A0,%C0", xop, plen, 2);
|
|
||||||
|
|
||||||
avr_asm_len ("and %A0,%B0" CR_TAB
|
if (n_bytes >= 3)
|
||||||
"com %A0", xop, plen, 2);
|
avr_asm_len ("and %A0,%C0", xop, plen, 1);
|
||||||
|
|
||||||
return "";
|
return avr_asm_len ("and %A0,%B0" CR_TAB
|
||||||
|
"com %A0", xop, plen, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3335,8 +3656,7 @@ avr_out_compare (rtx insn, rtx *xop, int *plen)
|
||||||
&& compare_eq_p (insn)
|
&& compare_eq_p (insn)
|
||||||
&& reg_unused_after (insn, xreg))
|
&& reg_unused_after (insn, xreg))
|
||||||
{
|
{
|
||||||
avr_asm_len ("adiw %0,%n1", xop, plen, 1);
|
return avr_asm_len ("adiw %0,%n1", xop, plen, 1);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3410,6 +3730,31 @@ avr_out_tsthi (rtx insn, rtx *op, int *plen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Output test instruction for PSImode. */
|
||||||
|
|
||||||
|
const char*
|
||||||
|
avr_out_tstpsi (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
if (compare_sign_p (insn))
|
||||||
|
{
|
||||||
|
avr_asm_len ("tst %C0", op, plen, -1);
|
||||||
|
}
|
||||||
|
else if (reg_unused_after (insn, op[0])
|
||||||
|
&& compare_eq_p (insn))
|
||||||
|
{
|
||||||
|
/* Faster than sbiw if we can clobber the operand. */
|
||||||
|
avr_asm_len ("or %A0,%B0" CR_TAB
|
||||||
|
"or %A0,%C0", op, plen, -2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
avr_out_compare (insn, op, plen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Output test instruction for SImode. */
|
/* Output test instruction for SImode. */
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
|
@ -3938,6 +4283,69 @@ ashlhi3_out (rtx insn, rtx operands[], int *len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 24-bit shift left */
|
||||||
|
|
||||||
|
const char*
|
||||||
|
avr_out_ashlpsi3 (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
if (plen)
|
||||||
|
*plen = 0;
|
||||||
|
|
||||||
|
if (CONST_INT_P (op[2]))
|
||||||
|
{
|
||||||
|
switch (INTVAL (op[2]))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
if (INTVAL (op[2]) < 24)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return avr_asm_len ("clr %A0" CR_TAB
|
||||||
|
"clr %B0" CR_TAB
|
||||||
|
"clr %C0", op, plen, 3);
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
int reg0 = REGNO (op[0]);
|
||||||
|
int reg1 = REGNO (op[1]);
|
||||||
|
|
||||||
|
if (reg0 >= reg1)
|
||||||
|
return avr_asm_len ("mov %C0,%B1" CR_TAB
|
||||||
|
"mov %B0,%A1" CR_TAB
|
||||||
|
"clr %A0", op, plen, 3);
|
||||||
|
else
|
||||||
|
return avr_asm_len ("clr %A0" CR_TAB
|
||||||
|
"mov %B0,%A1" CR_TAB
|
||||||
|
"mov %C0,%B1", op, plen, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
int reg0 = REGNO (op[0]);
|
||||||
|
int reg1 = REGNO (op[1]);
|
||||||
|
|
||||||
|
if (reg0 + 2 != reg1)
|
||||||
|
avr_asm_len ("mov %C0,%A0", op, plen, 1);
|
||||||
|
|
||||||
|
return avr_asm_len ("clr %B0" CR_TAB
|
||||||
|
"clr %A0", op, plen, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 23:
|
||||||
|
return avr_asm_len ("clr %C0" CR_TAB
|
||||||
|
"lsr %A0" CR_TAB
|
||||||
|
"ror %C0" CR_TAB
|
||||||
|
"clr %B0" CR_TAB
|
||||||
|
"clr %A0", op, plen, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_shift_with_cnt ("lsl %A0" CR_TAB
|
||||||
|
"rol %B0" CR_TAB
|
||||||
|
"rol %C0", insn, op, plen, 3);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 32bit shift left ((long)x << i) */
|
/* 32bit shift left ((long)x << i) */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
@ -4264,6 +4672,65 @@ ashrhi3_out (rtx insn, rtx operands[], int *len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 24-bit arithmetic shift right */
|
||||||
|
|
||||||
|
const char*
|
||||||
|
avr_out_ashrpsi3 (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
int dest = REGNO (op[0]);
|
||||||
|
int src = REGNO (op[1]);
|
||||||
|
|
||||||
|
if (CONST_INT_P (op[2]))
|
||||||
|
{
|
||||||
|
if (plen)
|
||||||
|
*plen = 0;
|
||||||
|
|
||||||
|
switch (INTVAL (op[2]))
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
if (dest <= src)
|
||||||
|
return avr_asm_len ("mov %A0,%B1" CR_TAB
|
||||||
|
"mov %B0,%C1" CR_TAB
|
||||||
|
"clr %C0" CR_TAB
|
||||||
|
"sbrc %B0,7" CR_TAB
|
||||||
|
"dec %C0", op, plen, 5);
|
||||||
|
else
|
||||||
|
return avr_asm_len ("clr %C0" CR_TAB
|
||||||
|
"sbrc %C1,7" CR_TAB
|
||||||
|
"dec %C0" CR_TAB
|
||||||
|
"mov %B0,%C1" CR_TAB
|
||||||
|
"mov %A0,%B1", op, plen, 5);
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
if (dest != src + 2)
|
||||||
|
avr_asm_len ("mov %A0,%C1", op, plen, 1);
|
||||||
|
|
||||||
|
return avr_asm_len ("clr %B0" CR_TAB
|
||||||
|
"sbrc %A0,7" CR_TAB
|
||||||
|
"com %B0" CR_TAB
|
||||||
|
"mov %C0,%B0", op, plen, 4);
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (INTVAL (op[2]) < 24)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case 31:
|
||||||
|
return avr_asm_len ("lsl %C0" CR_TAB
|
||||||
|
"sbc %A0,%A0" CR_TAB
|
||||||
|
"mov %B0,%A0" CR_TAB
|
||||||
|
"mov %C0,%A0", op, plen, 4);
|
||||||
|
} /* switch */
|
||||||
|
}
|
||||||
|
|
||||||
|
out_shift_with_cnt ("asr %C0" CR_TAB
|
||||||
|
"ror %B0" CR_TAB
|
||||||
|
"ror %A0", insn, op, plen, 3);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 32bit arithmetic shift right ((signed long)x >> i) */
|
/* 32bit arithmetic shift right ((signed long)x >> i) */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
@ -4714,6 +5181,61 @@ lshrhi3_out (rtx insn, rtx operands[], int *len)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 24-bit logic shift right */
|
||||||
|
|
||||||
|
const char*
|
||||||
|
avr_out_lshrpsi3 (rtx insn, rtx *op, int *plen)
|
||||||
|
{
|
||||||
|
int dest = REGNO (op[0]);
|
||||||
|
int src = REGNO (op[1]);
|
||||||
|
|
||||||
|
if (CONST_INT_P (op[2]))
|
||||||
|
{
|
||||||
|
if (plen)
|
||||||
|
*plen = 0;
|
||||||
|
|
||||||
|
switch (INTVAL (op[2]))
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
if (dest <= src)
|
||||||
|
return avr_asm_len ("mov %A0,%B1" CR_TAB
|
||||||
|
"mov %B0,%C1" CR_TAB
|
||||||
|
"clr %C0", op, plen, 3);
|
||||||
|
else
|
||||||
|
return avr_asm_len ("clr %C0" CR_TAB
|
||||||
|
"mov %B0,%C1" CR_TAB
|
||||||
|
"mov %A0,%B1", op, plen, 3);
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
if (dest != src + 2)
|
||||||
|
avr_asm_len ("mov %A0,%C1", op, plen, 1);
|
||||||
|
|
||||||
|
return avr_asm_len ("clr %B0" CR_TAB
|
||||||
|
"clr %C0", op, plen, 2);
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (INTVAL (op[2]) < 24)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case 23:
|
||||||
|
return avr_asm_len ("clr %A0" CR_TAB
|
||||||
|
"sbrc %C0,7" CR_TAB
|
||||||
|
"inc %A0" CR_TAB
|
||||||
|
"clr %B0" CR_TAB
|
||||||
|
"clr %C0", op, plen, 5);
|
||||||
|
} /* switch */
|
||||||
|
}
|
||||||
|
|
||||||
|
out_shift_with_cnt ("lsr %C0" CR_TAB
|
||||||
|
"ror %B0" CR_TAB
|
||||||
|
"ror %A0", insn, op, plen, 3);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 32bit logic shift right ((unsigned int)x >> i) */
|
/* 32bit logic shift right ((unsigned int)x >> i) */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
@ -4874,7 +5396,9 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
|
||||||
if (i && !started)
|
if (i && !started)
|
||||||
*pcc = CC_CLOBBER;
|
*pcc = CC_CLOBBER;
|
||||||
|
|
||||||
if (!started && i % 2 == 0
|
if (!started
|
||||||
|
&& i % 2 == 0
|
||||||
|
&& i + 2 <= n_bytes
|
||||||
&& test_hard_reg_class (ADDW_REGS, reg8))
|
&& test_hard_reg_class (ADDW_REGS, reg8))
|
||||||
{
|
{
|
||||||
rtx xval16 = simplify_gen_subreg (HImode, xval, mode, i);
|
rtx xval16 = simplify_gen_subreg (HImode, xval, mode, i);
|
||||||
|
|
@ -4911,11 +5435,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
|
||||||
else if ((val8 == 1 || val8 == 0xff)
|
else if ((val8 == 1 || val8 == 0xff)
|
||||||
&& !started
|
&& !started
|
||||||
&& i == n_bytes - 1)
|
&& i == n_bytes - 1)
|
||||||
{
|
{
|
||||||
avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
|
avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
|
||||||
op, plen, 1);
|
op, plen, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
|
|
@ -5399,6 +5923,7 @@ adjust_insn_length (rtx insn, int len)
|
||||||
switch (adjust_len)
|
switch (adjust_len)
|
||||||
{
|
{
|
||||||
case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
|
case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
|
||||||
|
case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
|
||||||
case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
|
case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
|
||||||
|
|
||||||
case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
|
case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
|
||||||
|
|
@ -5411,9 +5936,11 @@ adjust_insn_length (rtx insn, int len)
|
||||||
|
|
||||||
case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
|
case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
|
||||||
case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
|
case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
|
||||||
|
case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
|
||||||
case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
|
case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
|
||||||
|
|
||||||
case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
|
case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
|
||||||
|
case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
|
||||||
case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
|
case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
|
||||||
case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
|
case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
|
||||||
|
|
||||||
|
|
@ -5429,6 +5956,10 @@ adjust_insn_length (rtx insn, int len)
|
||||||
case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
|
case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
|
||||||
case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
|
case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
|
||||||
|
|
||||||
|
case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
|
||||||
|
case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
|
||||||
|
case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
|
||||||
|
|
||||||
case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
|
case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -6228,13 +6759,11 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
*total = COSTS_N_INSNS (1);
|
*total = COSTS_N_INSNS (1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HImode:
|
case HImode:
|
||||||
*total = COSTS_N_INSNS (3);
|
case PSImode:
|
||||||
break;
|
case SImode:
|
||||||
|
*total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
|
||||||
case SImode:
|
break;
|
||||||
*total = COSTS_N_INSNS (7);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -6320,6 +6849,19 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
*total = COSTS_N_INSNS (2);
|
*total = COSTS_N_INSNS (2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
if (!CONST_INT_P (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
|
||||||
|
speed);
|
||||||
|
}
|
||||||
|
else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
|
||||||
|
*total = COSTS_N_INSNS (2);
|
||||||
|
else
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||||
{
|
{
|
||||||
|
|
@ -6367,6 +6909,7 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
*total = COSTS_N_INSNS (1) + *total;
|
*total = COSTS_N_INSNS (1) + *total;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/* FALLTHRU */
|
||||||
case AND:
|
case AND:
|
||||||
case IOR:
|
case IOR:
|
||||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
|
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
|
||||||
|
|
@ -6437,6 +6980,13 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
if (!speed)
|
||||||
|
*total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
|
||||||
|
else
|
||||||
|
*total = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
if (AVR_HAVE_MUL)
|
if (AVR_HAVE_MUL)
|
||||||
{
|
{
|
||||||
|
|
@ -6611,6 +7161,31 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
if (!CONST_INT_P (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 6 : 73);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (INTVAL (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*total = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 8:
|
||||||
|
case 16:
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
*total = COSTS_N_INSNS (5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||||
{
|
{
|
||||||
|
|
@ -6721,6 +7296,33 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
if (!CONST_INT_P (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 6 : 73);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (INTVAL (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*total = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
case 8:
|
||||||
|
*total = COSTS_N_INSNS (5);
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
*total = COSTS_N_INSNS (4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||||
{
|
{
|
||||||
|
|
@ -6832,6 +7434,31 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
if (!CONST_INT_P (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 6 : 73);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (INTVAL (XEXP (x, 1)))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*total = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 8:
|
||||||
|
case 16:
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
*total = COSTS_N_INSNS (5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||||
{
|
{
|
||||||
|
|
@ -6889,6 +7516,12 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
|
||||||
*total += COSTS_N_INSNS (1);
|
*total += COSTS_N_INSNS (1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSImode:
|
||||||
|
*total = COSTS_N_INSNS (3);
|
||||||
|
if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
|
||||||
|
*total += COSTS_N_INSNS (2);
|
||||||
|
break;
|
||||||
|
|
||||||
case SImode:
|
case SImode:
|
||||||
*total = COSTS_N_INSNS (4);
|
*total = COSTS_N_INSNS (4);
|
||||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||||
|
|
@ -7310,8 +7943,10 @@ avr_libcall_value (enum machine_mode mode,
|
||||||
const_rtx func ATTRIBUTE_UNUSED)
|
const_rtx func ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
int offs = GET_MODE_SIZE (mode);
|
int offs = GET_MODE_SIZE (mode);
|
||||||
if (offs < 2)
|
|
||||||
offs = 2;
|
if (offs <= 4)
|
||||||
|
offs = (offs + 1) & ~1;
|
||||||
|
|
||||||
return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
|
return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7537,10 +8172,11 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
|
||||||
/* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
|
/* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
|
||||||
but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
|
but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
|
||||||
|
|
||||||
if (14 == REGNO (dest)
|
if (REGNO (dest) < 16
|
||||||
&& 4 == GET_MODE_SIZE (mode))
|
&& REGNO (dest) + GET_MODE_SIZE (mode) > 16)
|
||||||
{
|
{
|
||||||
clobber_reg = gen_rtx_REG (QImode, 17);
|
clobber_reg = gen_rtx_REG (QImode,
|
||||||
|
REGNO (dest) + GET_MODE_SIZE (mode) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We might need a clobber reg but don't have one. Look at the value
|
/* We might need a clobber reg but don't have one. Look at the value
|
||||||
|
|
@ -7577,6 +8213,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
|
||||||
/* Look if we can reuse the low word by means of MOVW. */
|
/* Look if we can reuse the low word by means of MOVW. */
|
||||||
|
|
||||||
if (n == 2
|
if (n == 2
|
||||||
|
&& GET_MODE_SIZE (mode) >= 4
|
||||||
&& AVR_HAVE_MOVW)
|
&& AVR_HAVE_MOVW)
|
||||||
{
|
{
|
||||||
rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
|
rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
|
||||||
|
|
@ -7820,6 +8457,16 @@ output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
|
||||||
|
{
|
||||||
|
gcc_assert (REG_P (op[0])
|
||||||
|
&& CONST_INT_P (op[1]));
|
||||||
|
|
||||||
|
output_reload_in_const (op, clobber_reg, len, false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
avr_output_bld (rtx operands[], int bit_nr)
|
avr_output_bld (rtx operands[], int bit_nr)
|
||||||
{
|
{
|
||||||
|
|
@ -8078,6 +8725,16 @@ enum avr_builtin_id
|
||||||
AVR_BUILTIN_DELAY_CYCLES
|
AVR_BUILTIN_DELAY_CYCLES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
avr_init_builtin_int24 (void)
|
||||||
|
{
|
||||||
|
tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
|
||||||
|
tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
|
||||||
|
|
||||||
|
(*lang_hooks.types.register_builtin_type) (int24_type, "__int24");
|
||||||
|
(*lang_hooks.types.register_builtin_type) (uint24_type, "__uint24");
|
||||||
|
}
|
||||||
|
|
||||||
#define DEF_BUILTIN(NAME, TYPE, CODE) \
|
#define DEF_BUILTIN(NAME, TYPE, CODE) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -8133,6 +8790,8 @@ avr_init_builtins (void)
|
||||||
AVR_BUILTIN_FMULS);
|
AVR_BUILTIN_FMULS);
|
||||||
DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar,
|
DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar,
|
||||||
AVR_BUILTIN_FMULSU);
|
AVR_BUILTIN_FMULSU);
|
||||||
|
|
||||||
|
avr_init_builtin_int24 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DEF_BUILTIN
|
#undef DEF_BUILTIN
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,12 @@
|
||||||
|
|
||||||
(define_attr "adjust_len"
|
(define_attr "adjust_len"
|
||||||
"out_bitop, out_plus, out_plus_noclobber, addto_sp,
|
"out_bitop, out_plus, out_plus_noclobber, addto_sp,
|
||||||
tsthi, tstsi, compare, call,
|
tsthi, tstpsi, tstsi, compare, call,
|
||||||
mov8, mov16, mov32, reload_in16, reload_in32,
|
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
|
||||||
ashlqi, ashrqi, lshrqi,
|
ashlqi, ashrqi, lshrqi,
|
||||||
ashlhi, ashrhi, lshrhi,
|
ashlhi, ashrhi, lshrhi,
|
||||||
ashlsi, ashrsi, lshrsi,
|
ashlsi, ashrsi, lshrsi,
|
||||||
|
ashlpsi, ashrpsi, lshrpsi,
|
||||||
no"
|
no"
|
||||||
(const_string "no"))
|
(const_string "no"))
|
||||||
|
|
||||||
|
|
@ -180,10 +181,13 @@
|
||||||
;; Define mode iterators
|
;; Define mode iterators
|
||||||
(define_mode_iterator QIHI [(QI "") (HI "")])
|
(define_mode_iterator QIHI [(QI "") (HI "")])
|
||||||
(define_mode_iterator QIHI2 [(QI "") (HI "")])
|
(define_mode_iterator QIHI2 [(QI "") (HI "")])
|
||||||
(define_mode_iterator QISI [(QI "") (HI "") (SI "")])
|
(define_mode_iterator QISI [(QI "") (HI "") (PSI "") (SI "")])
|
||||||
(define_mode_iterator QIDI [(QI "") (HI "") (SI "") (DI "")])
|
(define_mode_iterator QIDI [(QI "") (HI "") (PSI "") (SI "") (DI "")])
|
||||||
(define_mode_iterator HIDI [(HI "") (SI "") (DI "")])
|
(define_mode_iterator HIDI [(HI "") (PSI "") (SI "") (DI "")])
|
||||||
(define_mode_iterator HISI [(HI "") (SI "")])
|
(define_mode_iterator HISI [(HI "") (PSI "") (SI "")])
|
||||||
|
|
||||||
|
;; All supported move-modes
|
||||||
|
(define_mode_iterator MOVMODE [(QI "") (HI "") (SI "") (SF "") (PSI "")])
|
||||||
|
|
||||||
;; Define code iterators
|
;; Define code iterators
|
||||||
;; Define two incarnations so that we can build the cross product.
|
;; Define two incarnations so that we can build the cross product.
|
||||||
|
|
@ -279,6 +283,7 @@
|
||||||
(define_mode_iterator MPUSH
|
(define_mode_iterator MPUSH
|
||||||
[(CQI "")
|
[(CQI "")
|
||||||
(HI "") (CHI "")
|
(HI "") (CHI "")
|
||||||
|
(PSI "")
|
||||||
(SI "") (CSI "")
|
(SI "") (CSI "")
|
||||||
(DI "") (CDI "")
|
(DI "") (CDI "")
|
||||||
(SF "") (SC "")])
|
(SF "") (SC "")])
|
||||||
|
|
@ -309,6 +314,28 @@
|
||||||
[(set (reg:HI REG_SP) (reg:HI REG_Y))]
|
[(set (reg:HI REG_SP) (reg:HI REG_Y))]
|
||||||
"")
|
"")
|
||||||
|
|
||||||
|
;;========================================================================
|
||||||
|
|
||||||
|
;; "movqi"
|
||||||
|
;; "movhi"
|
||||||
|
;; "movsi"
|
||||||
|
;; "movsf"
|
||||||
|
;; "movpsi"
|
||||||
|
|
||||||
|
(define_expand "mov<mode>"
|
||||||
|
[(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
|
||||||
|
(match_operand:MOVMODE 1 "general_operand" ""))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
/* One of the ops has to be in a register. */
|
||||||
|
if (!register_operand (operands[0], <MODE>mode)
|
||||||
|
&& !(register_operand (operands[1], <MODE>mode)
|
||||||
|
|| CONST0_RTX (<MODE>mode) == operands[1]))
|
||||||
|
{
|
||||||
|
operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
;;========================================================================
|
;;========================================================================
|
||||||
;; move byte
|
;; move byte
|
||||||
;; The last alternative (any immediate constant to any register) is
|
;; The last alternative (any immediate constant to any register) is
|
||||||
|
|
@ -318,16 +345,6 @@
|
||||||
;; are call-saved registers, and most of LD_REGS are call-used registers,
|
;; are call-saved registers, and most of LD_REGS are call-used registers,
|
||||||
;; so this may still be a win for registers live across function calls.
|
;; so this may still be a win for registers live across function calls.
|
||||||
|
|
||||||
(define_expand "movqi"
|
|
||||||
[(set (match_operand:QI 0 "nonimmediate_operand" "")
|
|
||||||
(match_operand:QI 1 "general_operand" ""))]
|
|
||||||
""
|
|
||||||
"/* One of the ops has to be in a register. */
|
|
||||||
if (!register_operand(operand0, QImode)
|
|
||||||
&& ! (register_operand(operand1, QImode) || const0_rtx == operand1))
|
|
||||||
operands[1] = copy_to_mode_reg(QImode, operand1);
|
|
||||||
")
|
|
||||||
|
|
||||||
(define_insn "movqi_insn"
|
(define_insn "movqi_insn"
|
||||||
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
|
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
|
||||||
(match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))]
|
(match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))]
|
||||||
|
|
@ -365,21 +382,6 @@
|
||||||
;;============================================================================
|
;;============================================================================
|
||||||
;; move word (16 bit)
|
;; move word (16 bit)
|
||||||
|
|
||||||
(define_expand "movhi"
|
|
||||||
[(set (match_operand:HI 0 "nonimmediate_operand" "")
|
|
||||||
(match_operand:HI 1 "general_operand" ""))]
|
|
||||||
""
|
|
||||||
"
|
|
||||||
{
|
|
||||||
/* One of the ops has to be in a register. */
|
|
||||||
if (!register_operand(operand0, HImode)
|
|
||||||
&& !(register_operand(operand1, HImode) || const0_rtx == operands[1]))
|
|
||||||
{
|
|
||||||
operands[1] = copy_to_mode_reg(HImode, operand1);
|
|
||||||
}
|
|
||||||
}")
|
|
||||||
|
|
||||||
|
|
||||||
;; Move register $1 to the Stack Pointer register SP.
|
;; Move register $1 to the Stack Pointer register SP.
|
||||||
;; This insn is emit during function prologue/epilogue generation.
|
;; This insn is emit during function prologue/epilogue generation.
|
||||||
;; $2 = 0: We know that IRQs are off
|
;; $2 = 0: We know that IRQs are off
|
||||||
|
|
@ -460,25 +462,50 @@
|
||||||
operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
|
operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
|
||||||
})
|
})
|
||||||
|
|
||||||
|
;;==========================================================================
|
||||||
|
;; xpointer move (24 bit)
|
||||||
|
|
||||||
|
(define_peephole2 ; *reload_inpsi
|
||||||
|
[(match_scratch:QI 2 "d")
|
||||||
|
(set (match_operand:PSI 0 "l_register_operand" "")
|
||||||
|
(match_operand:PSI 1 "immediate_operand" ""))
|
||||||
|
(match_dup 2)]
|
||||||
|
"operands[1] != const0_rtx
|
||||||
|
&& operands[1] != constm1_rtx"
|
||||||
|
[(parallel [(set (match_dup 0)
|
||||||
|
(match_dup 1))
|
||||||
|
(clobber (match_dup 2))])]
|
||||||
|
"")
|
||||||
|
|
||||||
|
;; '*' because it is not used in rtl generation.
|
||||||
|
(define_insn "*reload_inpsi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(match_operand:PSI 1 "immediate_operand" "i"))
|
||||||
|
(clobber (match_operand:QI 2 "register_operand" "=&d"))]
|
||||||
|
"reload_completed"
|
||||||
|
{
|
||||||
|
return avr_out_reload_inpsi (operands, operands[2], NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "6")
|
||||||
|
(set_attr "adjust_len" "reload_in24")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
(define_insn "*movpsi"
|
||||||
|
[(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
|
||||||
|
(match_operand:PSI 1 "general_operand" "r,L,Qm,rL,i ,i"))]
|
||||||
|
"register_operand (operands[0], PSImode)
|
||||||
|
|| register_operand (operands[1], PSImode)
|
||||||
|
|| const0_rtx == operands[1]"
|
||||||
|
{
|
||||||
|
return avr_out_movpsi (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "3,3,8,9,4,10")
|
||||||
|
(set_attr "adjust_len" "mov24")
|
||||||
|
(set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
|
||||||
|
|
||||||
;;==========================================================================
|
;;==========================================================================
|
||||||
;; move double word (32 bit)
|
;; move double word (32 bit)
|
||||||
|
|
||||||
(define_expand "movsi"
|
|
||||||
[(set (match_operand:SI 0 "nonimmediate_operand" "")
|
|
||||||
(match_operand:SI 1 "general_operand" ""))]
|
|
||||||
""
|
|
||||||
"
|
|
||||||
{
|
|
||||||
/* One of the ops has to be in a register. */
|
|
||||||
if (!register_operand (operand0, SImode)
|
|
||||||
&& !(register_operand (operand1, SImode) || const0_rtx == operand1))
|
|
||||||
{
|
|
||||||
operands[1] = copy_to_mode_reg (SImode, operand1);
|
|
||||||
}
|
|
||||||
}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define_peephole2 ; *reload_insi
|
(define_peephole2 ; *reload_insi
|
||||||
[(match_scratch:QI 2 "d")
|
[(match_scratch:QI 2 "d")
|
||||||
(set (match_operand:SI 0 "l_register_operand" "")
|
(set (match_operand:SI 0 "l_register_operand" "")
|
||||||
|
|
@ -519,20 +546,6 @@
|
||||||
;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
;; move floating point numbers (32 bit)
|
;; move floating point numbers (32 bit)
|
||||||
|
|
||||||
(define_expand "movsf"
|
|
||||||
[(set (match_operand:SF 0 "nonimmediate_operand" "")
|
|
||||||
(match_operand:SF 1 "general_operand" ""))]
|
|
||||||
""
|
|
||||||
"
|
|
||||||
{
|
|
||||||
/* One of the ops has to be in a register. */
|
|
||||||
if (!register_operand (operand1, SFmode)
|
|
||||||
&& !register_operand (operand0, SFmode))
|
|
||||||
{
|
|
||||||
operands[1] = copy_to_mode_reg (SFmode, operand1);
|
|
||||||
}
|
|
||||||
}")
|
|
||||||
|
|
||||||
(define_insn "*movsf"
|
(define_insn "*movsf"
|
||||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
|
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
|
||||||
(match_operand:SF 1 "general_operand" "r,G,Qm,rG,F,F"))]
|
(match_operand:SF 1 "general_operand" "r,G,Qm,rG,F,F"))]
|
||||||
|
|
@ -914,6 +927,33 @@
|
||||||
(set_attr "adjust_len" "*,*,out_plus,out_plus")
|
(set_attr "adjust_len" "*,*,out_plus,out_plus")
|
||||||
(set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
|
(set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
|
||||||
|
|
||||||
|
(define_insn "*addpsi3_zero_extend.qi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))
|
||||||
|
(match_operand:PSI 2 "register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
|
(define_insn "*addpsi3_zero_extend.hi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
|
||||||
|
(match_operand:PSI 2 "register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
|
(define_insn "*addpsi3_sign_extend.hi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r"))
|
||||||
|
(match_operand:PSI 2 "register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0"
|
||||||
|
[(set_attr "length" "5")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
(define_insn "*addsi3_zero_extend"
|
(define_insn "*addsi3_zero_extend"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
|
(plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
|
||||||
|
|
@ -932,6 +972,66 @@
|
||||||
[(set_attr "length" "4")
|
[(set_attr "length" "4")
|
||||||
(set_attr "cc" "set_n")])
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
|
(define_insn "addpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,d ,d,r")
|
||||||
|
(plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0")
|
||||||
|
(match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
static const char * const asm_code[] =
|
||||||
|
{
|
||||||
|
"add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2",
|
||||||
|
"subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
if (*asm_code[which_alternative])
|
||||||
|
return asm_code [which_alternative];
|
||||||
|
|
||||||
|
return avr_out_plus (operands, NULL, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "3,3,3,6")
|
||||||
|
(set_attr "adjust_len" "*,*,out_plus,out_plus")
|
||||||
|
(set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
|
||||||
|
|
||||||
|
(define_insn "subpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(minus:PSI (match_operand:PSI 1 "register_operand" "0")
|
||||||
|
(match_operand:PSI 2 "register_operand" "r")))]
|
||||||
|
""
|
||||||
|
"sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_czn")])
|
||||||
|
|
||||||
|
(define_insn "*subpsi3_zero_extend.qi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(minus:PSI (match_operand:SI 1 "register_operand" "0")
|
||||||
|
(zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
|
||||||
|
""
|
||||||
|
"sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_czn")])
|
||||||
|
|
||||||
|
(define_insn "*subpsi3_zero_extend.hi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(minus:PSI (match_operand:PSI 1 "register_operand" "0")
|
||||||
|
(zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
|
||||||
|
""
|
||||||
|
"sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_czn")])
|
||||||
|
|
||||||
|
(define_insn "*subpsi3_sign_extend.hi"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(minus:PSI (match_operand:PSI 1 "register_operand" "0")
|
||||||
|
(sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
|
||||||
|
""
|
||||||
|
"sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0"
|
||||||
|
[(set_attr "length" "5")
|
||||||
|
(set_attr "cc" "set_czn")])
|
||||||
|
|
||||||
;-----------------------------------------------------------------------------
|
;-----------------------------------------------------------------------------
|
||||||
; sub bytes
|
; sub bytes
|
||||||
(define_insn "subqi3"
|
(define_insn "subqi3"
|
||||||
|
|
@ -1099,6 +1199,17 @@
|
||||||
[(set_attr "length" "2,3")
|
[(set_attr "length" "2,3")
|
||||||
(set_attr "cc" "clobber")])
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
(define_insn "*addpsi3.lt0"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "r")
|
||||||
|
(const_int 23))
|
||||||
|
(match_operand:PSI 2 "register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"mov __tmp_reg__,%C1\;lsl __tmp_reg__
|
||||||
|
adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__"
|
||||||
|
[(set_attr "length" "5")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
(define_insn "*addsi3.lt0"
|
(define_insn "*addsi3.lt0"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
|
(plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
|
@ -2062,7 +2173,7 @@
|
||||||
; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
|
; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
|
||||||
; divmod
|
; divmod
|
||||||
|
|
||||||
;; Generate libgcc.S calls ourselves, because:
|
;; Generate lib1funcs.S calls ourselves, because:
|
||||||
;; - we know exactly which registers are clobbered (for QI and HI
|
;; - we know exactly which registers are clobbered (for QI and HI
|
||||||
;; modes, some of the call-used registers are preserved)
|
;; modes, some of the call-used registers are preserved)
|
||||||
;; - we get both the quotient and the remainder at no extra cost
|
;; - we get both the quotient and the remainder at no extra cost
|
||||||
|
|
@ -2199,6 +2310,80 @@
|
||||||
[(set_attr "type" "xcall")
|
[(set_attr "type" "xcall")
|
||||||
(set_attr "cc" "clobber")])
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; 24-bit signed/unsigned division and modulo.
|
||||||
|
;; Notice that the libgcc implementation return the quotient in R22
|
||||||
|
;; and the remainder in R18 whereas the 32-bit [u]divmodsi4
|
||||||
|
;; implementation works the other way round.
|
||||||
|
|
||||||
|
(define_insn_and_split "divmodpsi4"
|
||||||
|
[(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
|
||||||
|
(div:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
|
||||||
|
(match_operand:PSI 2 "pseudo_register_operand" "")))
|
||||||
|
(set (match_operand:PSI 3 "pseudo_register_operand" "")
|
||||||
|
(mod:PSI (match_dup 1)
|
||||||
|
(match_dup 2)))
|
||||||
|
(clobber (reg:DI 18))
|
||||||
|
(clobber (reg:QI 26))])]
|
||||||
|
""
|
||||||
|
{ gcc_unreachable(); }
|
||||||
|
""
|
||||||
|
[(set (reg:PSI 22) (match_dup 1))
|
||||||
|
(set (reg:PSI 18) (match_dup 2))
|
||||||
|
(parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(clobber (reg:QI 21))
|
||||||
|
(clobber (reg:QI 25))
|
||||||
|
(clobber (reg:QI 26))])
|
||||||
|
(set (match_dup 0) (reg:PSI 22))
|
||||||
|
(set (match_dup 3) (reg:PSI 18))])
|
||||||
|
|
||||||
|
(define_insn "*divmodpsi4_call"
|
||||||
|
[(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(clobber (reg:QI 21))
|
||||||
|
(clobber (reg:QI 25))
|
||||||
|
(clobber (reg:QI 26))]
|
||||||
|
""
|
||||||
|
"%~call __divmodpsi4"
|
||||||
|
[(set_attr "type" "xcall")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
(define_insn_and_split "udivmodpsi4"
|
||||||
|
[(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
|
||||||
|
(udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "")
|
||||||
|
(match_operand:PSI 2 "pseudo_register_operand" "")))
|
||||||
|
(set (match_operand:PSI 3 "pseudo_register_operand" "")
|
||||||
|
(umod:PSI (match_dup 1)
|
||||||
|
(match_dup 2)))
|
||||||
|
(clobber (reg:DI 18))
|
||||||
|
(clobber (reg:QI 26))])]
|
||||||
|
""
|
||||||
|
{ gcc_unreachable(); }
|
||||||
|
""
|
||||||
|
[(set (reg:PSI 22) (match_dup 1))
|
||||||
|
(set (reg:PSI 18) (match_dup 2))
|
||||||
|
(parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(clobber (reg:QI 21))
|
||||||
|
(clobber (reg:QI 25))
|
||||||
|
(clobber (reg:QI 26))])
|
||||||
|
(set (match_dup 0) (reg:PSI 22))
|
||||||
|
(set (match_dup 3) (reg:PSI 18))])
|
||||||
|
|
||||||
|
(define_insn "*udivmodpsi4_call"
|
||||||
|
[(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
|
||||||
|
(clobber (reg:QI 21))
|
||||||
|
(clobber (reg:QI 25))
|
||||||
|
(clobber (reg:QI 26))]
|
||||||
|
""
|
||||||
|
"%~call __udivmodpsi4"
|
||||||
|
[(set_attr "type" "xcall")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define_insn_and_split "divmodsi4"
|
(define_insn_and_split "divmodsi4"
|
||||||
[(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
|
[(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
|
||||||
(div:SI (match_operand:SI 1 "pseudo_register_operand" "")
|
(div:SI (match_operand:SI 1 "pseudo_register_operand" "")
|
||||||
|
|
@ -2297,6 +2482,24 @@
|
||||||
(set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
|
(set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
|
||||||
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "andpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r")
|
||||||
|
(and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
|
||||||
|
(match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (which_alternative == 0)
|
||||||
|
return "and %A0,%A2" CR_TAB
|
||||||
|
"and %B0,%B2" CR_TAB
|
||||||
|
"and %C0,%C2";
|
||||||
|
|
||||||
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "3,3,6,6")
|
||||||
|
(set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
|
||||||
|
(set_attr "cc" "set_n,clobber,clobber,clobber")])
|
||||||
|
|
||||||
(define_insn "andsi3"
|
(define_insn "andsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
||||||
(and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
(and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
||||||
|
|
@ -2361,6 +2564,24 @@
|
||||||
(set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
|
(set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop")
|
||||||
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "iorpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r")
|
||||||
|
(ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0")
|
||||||
|
(match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (which_alternative == 0)
|
||||||
|
return "or %A0,%A2" CR_TAB
|
||||||
|
"or %B0,%B2" CR_TAB
|
||||||
|
"or %C0,%C2";
|
||||||
|
|
||||||
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "3,3,6,6")
|
||||||
|
(set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")
|
||||||
|
(set_attr "cc" "set_n,clobber,clobber,clobber")])
|
||||||
|
|
||||||
(define_insn "iorsi3"
|
(define_insn "iorsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
||||||
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
||||||
|
|
@ -2408,6 +2629,24 @@
|
||||||
(set_attr "adjust_len" "*,out_bitop,out_bitop")
|
(set_attr "adjust_len" "*,out_bitop,out_bitop")
|
||||||
(set_attr "cc" "set_n,clobber,clobber")])
|
(set_attr "cc" "set_n,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "xorpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r ,r")
|
||||||
|
(xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0")
|
||||||
|
(match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X ,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (which_alternative == 0)
|
||||||
|
return "eor %A0,%A2" CR_TAB
|
||||||
|
"eor %B0,%B2" CR_TAB
|
||||||
|
"eor %C0,%C2";
|
||||||
|
|
||||||
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "3,6,6")
|
||||||
|
(set_attr "adjust_len" "*,out_bitop,out_bitop")
|
||||||
|
(set_attr "cc" "set_n,clobber,clobber")])
|
||||||
|
|
||||||
(define_insn "xorsi3"
|
(define_insn "xorsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r ,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r ,r")
|
||||||
(xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0")
|
(xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0")
|
||||||
|
|
@ -2472,10 +2711,11 @@
|
||||||
;; HImode does not need scratch. Use attribute for this constraint.
|
;; HImode does not need scratch. Use attribute for this constraint.
|
||||||
;; Use QI scratch for DI mode as this is often split into byte sized operands.
|
;; Use QI scratch for DI mode as this is often split into byte sized operands.
|
||||||
|
|
||||||
(define_mode_attr rotx [(DI "&r,&r,X") (SI "&r,&r,X") (HI "X,X,X")])
|
(define_mode_attr rotx [(DI "&r,&r,X") (SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")])
|
||||||
(define_mode_attr rotsmode [(DI "QI") (SI "HI") (HI "QI")])
|
(define_mode_attr rotsmode [(DI "QI") (SI "HI") (PSI "QI") (HI "QI")])
|
||||||
|
|
||||||
;; "rotlhi3"
|
;; "rotlhi3"
|
||||||
|
;; "rotlpsi3"
|
||||||
;; "rotlsi3"
|
;; "rotlsi3"
|
||||||
;; "rotldi3"
|
;; "rotldi3"
|
||||||
(define_expand "rotl<mode>3"
|
(define_expand "rotl<mode>3"
|
||||||
|
|
@ -2531,6 +2771,24 @@
|
||||||
[(set_attr "length" "3")
|
[(set_attr "length" "3")
|
||||||
(set_attr "cc" "clobber")])
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
(define_insn "*rotlpsi2.1"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(rotate:PSI (match_operand:PSI 1 "register_operand" "0")
|
||||||
|
(const_int 1)))]
|
||||||
|
""
|
||||||
|
"lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__"
|
||||||
|
[(set_attr "length" "4")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
(define_insn "*rotlpsi2.23"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(rotate:PSI (match_operand:PSI 1 "register_operand" "0")
|
||||||
|
(const_int 23)))]
|
||||||
|
""
|
||||||
|
"bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7"
|
||||||
|
[(set_attr "length" "5")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
(define_insn "*rotlsi2.1"
|
(define_insn "*rotlsi2.1"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(rotate:SI (match_operand:SI 1 "register_operand" "0")
|
(rotate:SI (match_operand:SI 1 "register_operand" "0")
|
||||||
|
|
@ -2567,6 +2825,7 @@
|
||||||
(clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
|
(clobber (match_scratch:<rotsmode> 3 "=<rotx>"))]
|
||||||
"AVR_HAVE_MOVW
|
"AVR_HAVE_MOVW
|
||||||
&& CONST_INT_P (operands[2])
|
&& CONST_INT_P (operands[2])
|
||||||
|
&& GET_MODE_SIZE (<MODE>mode) % 2 == 0
|
||||||
&& 0 == INTVAL (operands[2]) % 16"
|
&& 0 == INTVAL (operands[2]) % 16"
|
||||||
"#"
|
"#"
|
||||||
"&& (reload_completed || <MODE>mode == DImode)"
|
"&& (reload_completed || <MODE>mode == DImode)"
|
||||||
|
|
@ -2580,6 +2839,7 @@
|
||||||
;; Split byte aligned rotates using scratch that is always QI mode.
|
;; Split byte aligned rotates using scratch that is always QI mode.
|
||||||
|
|
||||||
;; "*rotbhi"
|
;; "*rotbhi"
|
||||||
|
;; "*rotbpsi"
|
||||||
;; "*rotbsi"
|
;; "*rotbsi"
|
||||||
;; "*rotbdi"
|
;; "*rotbdi"
|
||||||
(define_insn_and_split "*rotb<mode>"
|
(define_insn_and_split "*rotb<mode>"
|
||||||
|
|
@ -2589,7 +2849,8 @@
|
||||||
(clobber (match_scratch:QI 3 "=<rotx>"))]
|
(clobber (match_scratch:QI 3 "=<rotx>"))]
|
||||||
"CONST_INT_P (operands[2])
|
"CONST_INT_P (operands[2])
|
||||||
&& (8 == INTVAL (operands[2]) % 16
|
&& (8 == INTVAL (operands[2]) % 16
|
||||||
|| (!AVR_HAVE_MOVW
|
|| ((!AVR_HAVE_MOVW
|
||||||
|
|| GET_MODE_SIZE (<MODE>mode) % 2 != 0)
|
||||||
&& 0 == INTVAL (operands[2]) % 16))"
|
&& 0 == INTVAL (operands[2]) % 16))"
|
||||||
"#"
|
"#"
|
||||||
"&& (reload_completed || <MODE>mode == DImode)"
|
"&& (reload_completed || <MODE>mode == DImode)"
|
||||||
|
|
@ -2830,6 +3091,18 @@
|
||||||
(set_attr "adjust_len" "ashlsi")
|
(set_attr "adjust_len" "ashlsi")
|
||||||
(set_attr "cc" "none,set_n,clobber,clobber")])
|
(set_attr "cc" "none,set_n,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "ashlpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r,r,r")
|
||||||
|
(ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0")
|
||||||
|
(match_operand:QI 2 "nonmemory_operand" "r,P,O,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
return avr_out_ashlpsi3 (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "adjust_len" "ashlpsi")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
|
;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
|
||||||
;; arithmetic shift right
|
;; arithmetic shift right
|
||||||
|
|
||||||
|
|
@ -2853,6 +3126,18 @@
|
||||||
(set_attr "adjust_len" "ashrhi")
|
(set_attr "adjust_len" "ashrhi")
|
||||||
(set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
|
(set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "ashrpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r")
|
||||||
|
(ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r,0")
|
||||||
|
(match_operand:QI 2 "nonmemory_operand" "r,P,K,O,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
return avr_out_ashrpsi3 (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "adjust_len" "ashrpsi")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
(define_insn "ashrsi3"
|
(define_insn "ashrsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
|
||||||
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
|
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
|
||||||
|
|
@ -2966,6 +3251,18 @@
|
||||||
(set_attr "adjust_len" "lshrhi")
|
(set_attr "adjust_len" "lshrhi")
|
||||||
(set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
|
(set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
|
||||||
|
|
||||||
|
(define_insn "lshrpsi3"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r")
|
||||||
|
(lshiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0,0")
|
||||||
|
(match_operand:QI 2 "nonmemory_operand" "r,P,O,K,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
return avr_out_lshrpsi3 (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "adjust_len" "lshrpsi")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
(define_insn "lshrsi3"
|
(define_insn "lshrsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
|
||||||
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
|
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
|
||||||
|
|
@ -3100,6 +3397,17 @@
|
||||||
[(set_attr "length" "3,4,4")
|
[(set_attr "length" "3,4,4")
|
||||||
(set_attr "cc" "set_czn,set_n,set_czn")])
|
(set_attr "cc" "set_czn,set_n,set_czn")])
|
||||||
|
|
||||||
|
(define_insn "negpsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=!d,r,&r")
|
||||||
|
(neg:PSI (match_operand:PSI 1 "register_operand" "0,0,r")))]
|
||||||
|
""
|
||||||
|
"@
|
||||||
|
com %C0\;com %B0\;neg %A0\;sbci %B0,-1\;sbci %C0,-1
|
||||||
|
com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__
|
||||||
|
clr %A0\;clr %B0\;clr %C0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1"
|
||||||
|
[(set_attr "length" "5,6,6")
|
||||||
|
(set_attr "cc" "set_czn,set_n,set_czn")])
|
||||||
|
|
||||||
(define_insn "negsi2"
|
(define_insn "negsi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r")
|
[(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r")
|
||||||
(neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
|
(neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
|
||||||
|
|
@ -3143,6 +3451,14 @@
|
||||||
[(set_attr "length" "2")
|
[(set_attr "length" "2")
|
||||||
(set_attr "cc" "set_n")])
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
|
(define_insn "one_cmplpsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(not:PSI (match_operand:PSI 1 "register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"com %0\;com %B0\;com %C0"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
(define_insn "one_cmplsi2"
|
(define_insn "one_cmplsi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(not:SI (match_operand:SI 1 "register_operand" "0")))]
|
(not:SI (match_operand:SI 1 "register_operand" "0")))]
|
||||||
|
|
@ -3174,6 +3490,16 @@
|
||||||
[(set_attr "length" "3,4")
|
[(set_attr "length" "3,4")
|
||||||
(set_attr "cc" "set_n,set_n")])
|
(set_attr "cc" "set_n,set_n")])
|
||||||
|
|
||||||
|
(define_insn "extendqipsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r")
|
||||||
|
(sign_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
|
||||||
|
""
|
||||||
|
"@
|
||||||
|
clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0
|
||||||
|
mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0"
|
||||||
|
[(set_attr "length" "4,5")
|
||||||
|
(set_attr "cc" "set_n,set_n")])
|
||||||
|
|
||||||
(define_insn "extendqisi2"
|
(define_insn "extendqisi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||||
(sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
|
(sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))]
|
||||||
|
|
@ -3184,6 +3510,18 @@
|
||||||
[(set_attr "length" "5,6")
|
[(set_attr "length" "5,6")
|
||||||
(set_attr "cc" "set_n,set_n")])
|
(set_attr "cc" "set_n,set_n")])
|
||||||
|
|
||||||
|
(define_insn "extendhipsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r,r ,r")
|
||||||
|
(sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
|
||||||
|
""
|
||||||
|
"@
|
||||||
|
clr %C0\;sbrc %B0,7\;com %C0
|
||||||
|
mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0
|
||||||
|
movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0"
|
||||||
|
[(set_attr "length" "3,5,4")
|
||||||
|
(set_attr "isa" "*,mov,movw")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
(define_insn "extendhisi2"
|
(define_insn "extendhisi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r ,r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r ,r")
|
||||||
(sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
|
(sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
|
||||||
|
|
@ -3196,6 +3534,14 @@
|
||||||
(set_attr "isa" "*,mov,movw")
|
(set_attr "isa" "*,mov,movw")
|
||||||
(set_attr "cc" "set_n")])
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
|
(define_insn "extendpsisi2"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(sign_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "0")))]
|
||||||
|
""
|
||||||
|
"clr %D0\;sbrc %C0,7\;com %D0"
|
||||||
|
[(set_attr "length" "3")
|
||||||
|
(set_attr "cc" "set_n")])
|
||||||
|
|
||||||
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
|
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
|
||||||
;; zero extend
|
;; zero extend
|
||||||
|
|
||||||
|
|
@ -3215,6 +3561,21 @@
|
||||||
operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off);
|
operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(define_insn_and_split "zero_extendqipsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
|
||||||
|
""
|
||||||
|
"#"
|
||||||
|
"reload_completed"
|
||||||
|
[(set (match_dup 2) (match_dup 1))
|
||||||
|
(set (match_dup 3) (const_int 0))
|
||||||
|
(set (match_dup 4) (const_int 0))]
|
||||||
|
{
|
||||||
|
operands[2] = simplify_gen_subreg (QImode, operands[0], PSImode, 0);
|
||||||
|
operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 1);
|
||||||
|
operands[4] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn_and_split "zero_extendqisi2"
|
(define_insn_and_split "zero_extendqisi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
|
(zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))]
|
||||||
|
|
@ -3231,6 +3592,19 @@
|
||||||
operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
|
operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(define_insn_and_split "zero_extendhipsi2"
|
||||||
|
[(set (match_operand:PSI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
|
||||||
|
""
|
||||||
|
"#"
|
||||||
|
"reload_completed"
|
||||||
|
[(set (match_dup 2) (match_dup 1))
|
||||||
|
(set (match_dup 3) (const_int 0))]
|
||||||
|
{
|
||||||
|
operands[2] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
|
||||||
|
operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn_and_split "zero_extendhisi2"
|
(define_insn_and_split "zero_extendhisi2"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
|
(zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
|
||||||
|
|
@ -3247,6 +3621,19 @@
|
||||||
operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
|
operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(define_insn_and_split "zero_extendpsisi2"
|
||||||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
|
(zero_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "r")))]
|
||||||
|
""
|
||||||
|
"#"
|
||||||
|
"reload_completed"
|
||||||
|
[(set (match_dup 2) (match_dup 1))
|
||||||
|
(set (match_dup 3) (const_int 0))]
|
||||||
|
{
|
||||||
|
operands[2] = simplify_gen_subreg (PSImode, operands[0], SImode, 0);
|
||||||
|
operands[3] = simplify_gen_subreg (QImode, operands[0], SImode, 3);
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn_and_split "zero_extendqidi2"
|
(define_insn_and_split "zero_extendqidi2"
|
||||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||||
(zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
|
(zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
|
||||||
|
|
@ -3340,6 +3727,25 @@
|
||||||
[(set_attr "cc" "compare")
|
[(set_attr "cc" "compare")
|
||||||
(set_attr "length" "2")])
|
(set_attr "length" "2")])
|
||||||
|
|
||||||
|
(define_insn "*negated_tstpsi"
|
||||||
|
[(set (cc0)
|
||||||
|
(compare (neg:PSI (match_operand:PSI 0 "register_operand" "r"))
|
||||||
|
(const_int 0)))]
|
||||||
|
"!flag_wrapv && !flag_trapv && flag_strict_overflow"
|
||||||
|
"cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
|
||||||
|
[(set_attr "cc" "compare")
|
||||||
|
(set_attr "length" "3")])
|
||||||
|
|
||||||
|
(define_insn "*reversed_tstpsi"
|
||||||
|
[(set (cc0)
|
||||||
|
(compare (const_int 0)
|
||||||
|
(match_operand:PSI 0 "register_operand" "r")))
|
||||||
|
(clobber (match_scratch:QI 1 "=X"))]
|
||||||
|
""
|
||||||
|
"cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0"
|
||||||
|
[(set_attr "cc" "compare")
|
||||||
|
(set_attr "length" "3")])
|
||||||
|
|
||||||
(define_insn "*negated_tstsi"
|
(define_insn "*negated_tstsi"
|
||||||
[(set (cc0)
|
[(set (cc0)
|
||||||
(compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
|
(compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
|
||||||
|
|
@ -3418,6 +3824,35 @@
|
||||||
(set_attr "length" "1,2,2,3,4,2,4")
|
(set_attr "length" "1,2,2,3,4,2,4")
|
||||||
(set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
|
(set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
|
||||||
|
|
||||||
|
(define_insn "*cmppsi"
|
||||||
|
[(set (cc0)
|
||||||
|
(compare (match_operand:PSI 0 "register_operand" "r,r,d ,r ,d,r")
|
||||||
|
(match_operand:PSI 1 "nonmemory_operand" "L,r,s ,s ,M,n")))
|
||||||
|
(clobber (match_scratch:QI 2 "=X,X,&d,&d ,X,&d"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
switch (which_alternative)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return avr_out_tstpsi (insn, operands, NULL);
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1";
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return reg_unused_after (insn, operands[0])
|
||||||
|
? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)\;sbci %C0,hh8(%1)"
|
||||||
|
: "cpi %A0,lo8(%1)\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2";
|
||||||
|
}
|
||||||
|
|
||||||
|
return avr_out_compare (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "cc" "compare")
|
||||||
|
(set_attr "length" "3,3,5,6,3,7")
|
||||||
|
(set_attr "adjust_len" "tstpsi,*,*,*,compare,compare")])
|
||||||
|
|
||||||
(define_insn "*cmpsi"
|
(define_insn "*cmpsi"
|
||||||
[(set (cc0)
|
[(set (cc0)
|
||||||
|
|
@ -3456,6 +3891,18 @@
|
||||||
(pc)))]
|
(pc)))]
|
||||||
"")
|
"")
|
||||||
|
|
||||||
|
(define_expand "cbranchpsi4"
|
||||||
|
[(parallel [(set (cc0)
|
||||||
|
(compare (match_operand:PSI 1 "register_operand" "")
|
||||||
|
(match_operand:PSI 2 "nonmemory_operand" "")))
|
||||||
|
(clobber (match_scratch:QI 4 ""))])
|
||||||
|
(set (pc)
|
||||||
|
(if_then_else (match_operator 0 "ordered_comparison_operator" [(cc0)
|
||||||
|
(const_int 0)])
|
||||||
|
(label_ref (match_operand 3 "" ""))
|
||||||
|
(pc)))]
|
||||||
|
"")
|
||||||
|
|
||||||
(define_expand "cbranchhi4"
|
(define_expand "cbranchhi4"
|
||||||
[(parallel [(set (cc0)
|
[(parallel [(set (cc0)
|
||||||
(compare (match_operand:HI 1 "register_operand" "")
|
(compare (match_operand:HI 1 "register_operand" "")
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<7) | (1<<8))")))
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<7) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Ca3"
|
||||||
|
"Constant 3-byte integer that allows AND without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 3, (1<<0) | (1<<7) | (1<<8))")))
|
||||||
|
|
||||||
(define_constraint "Ca4"
|
(define_constraint "Ca4"
|
||||||
"Constant 4-byte integer that allows AND without clobber register."
|
"Constant 4-byte integer that allows AND without clobber register."
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
|
|
@ -143,6 +148,11 @@
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<1) | (1<<8))")))
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<1) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Co3"
|
||||||
|
"Constant 3-byte integer that allows OR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 3, (1<<0) | (1<<1) | (1<<8))")))
|
||||||
|
|
||||||
(define_constraint "Co4"
|
(define_constraint "Co4"
|
||||||
"Constant 4-byte integer that allows OR without clobber register."
|
"Constant 4-byte integer that allows OR without clobber register."
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
|
|
@ -153,6 +163,11 @@
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<8))")))
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Cx3"
|
||||||
|
"Constant 3-byte integer that allows XOR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 3, (1<<0) | (1<<8))")))
|
||||||
|
|
||||||
(define_constraint "Cx4"
|
(define_constraint "Cx4"
|
||||||
"Constant 4-byte integer that allows XOR without clobber register."
|
"Constant 4-byte integer that allows XOR without clobber register."
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2011-11-04 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/50931
|
||||||
|
* config/t-avr (LIB1ASMFUNCS): Add _divmodpsi4, _udivmodpsi4.
|
||||||
|
* config/lib1funcs.S (__udivmodpsi4, __divmodpsi4): New functions.
|
||||||
|
|
||||||
2011-11-04 Joel Sherrill <joel.sherrill@oarcorp.com>
|
2011-11-04 Joel Sherrill <joel.sherrill@oarcorp.com>
|
||||||
|
|
||||||
PR target/50989
|
PR target/50989
|
||||||
|
|
|
||||||
|
|
@ -599,7 +599,142 @@ ENDF __divmodhi4
|
||||||
#undef r_arg2L
|
#undef r_arg2L
|
||||||
|
|
||||||
#undef r_cnt
|
#undef r_cnt
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
Division 24 / 24 => (result + remainder)
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
;; A[0..2]: In: Dividend; Out: Quotient
|
||||||
|
#define A0 22
|
||||||
|
#define A1 A0+1
|
||||||
|
#define A2 A0+2
|
||||||
|
|
||||||
|
;; B[0..2]: In: Divisor; Out: Remainder
|
||||||
|
#define B0 18
|
||||||
|
#define B1 B0+1
|
||||||
|
#define B2 B0+2
|
||||||
|
|
||||||
|
;; C[0..2]: Expand remainder
|
||||||
|
#define C0 __zero_reg__
|
||||||
|
#define C1 26
|
||||||
|
#define C2 25
|
||||||
|
|
||||||
|
;; Loop counter
|
||||||
|
#define r_cnt 21
|
||||||
|
|
||||||
|
#if defined (L_udivmodpsi4)
|
||||||
|
;; R24:R22 = R24:R22 udiv R20:R18
|
||||||
|
;; R20:R18 = R24:R22 umod R20:R18
|
||||||
|
;; Clobbers: R21, R25, R26
|
||||||
|
|
||||||
|
DEFUN __udivmodpsi4
|
||||||
|
; init loop counter
|
||||||
|
ldi r_cnt, 24+1
|
||||||
|
; Clear remainder and carry. C0 is already 0
|
||||||
|
clr C1
|
||||||
|
sub C2, C2
|
||||||
|
; jump to entry point
|
||||||
|
rjmp __udivmodpsi4_start
|
||||||
|
__udivmodpsi4_loop:
|
||||||
|
; shift dividend into remainder
|
||||||
|
rol C0
|
||||||
|
rol C1
|
||||||
|
rol C2
|
||||||
|
; compare remainder & divisor
|
||||||
|
cp C0, B0
|
||||||
|
cpc C1, B1
|
||||||
|
cpc C2, B2
|
||||||
|
brcs __udivmodpsi4_start ; remainder <= divisor
|
||||||
|
sub C0, B0 ; restore remainder
|
||||||
|
sbc C1, B1
|
||||||
|
sbc C2, B2
|
||||||
|
__udivmodpsi4_start:
|
||||||
|
; shift dividend (with CARRY)
|
||||||
|
rol A0
|
||||||
|
rol A1
|
||||||
|
rol A2
|
||||||
|
; decrement loop counter
|
||||||
|
dec r_cnt
|
||||||
|
brne __udivmodpsi4_loop
|
||||||
|
com A0
|
||||||
|
com A1
|
||||||
|
com A2
|
||||||
|
; div/mod results to return registers
|
||||||
|
; remainder
|
||||||
|
mov B0, C0
|
||||||
|
mov B1, C1
|
||||||
|
mov B2, C2
|
||||||
|
clr __zero_reg__ ; C0
|
||||||
|
ret
|
||||||
|
ENDF __udivmodpsi4
|
||||||
|
#endif /* defined (L_udivmodpsi4) */
|
||||||
|
|
||||||
|
#if defined (L_divmodpsi4)
|
||||||
|
;; R24:R22 = R24:R22 div R20:R18
|
||||||
|
;; R20:R18 = R24:R22 mod R20:R18
|
||||||
|
;; Clobbers: T, __tmp_reg__, R21, R25, R26
|
||||||
|
|
||||||
|
DEFUN __divmodpsi4
|
||||||
|
; R0.7 will contain the sign of the result:
|
||||||
|
; R0.7 = A.sign ^ B.sign
|
||||||
|
mov __tmp_reg__, B2
|
||||||
|
; T-flag = sign of dividend
|
||||||
|
bst A2, 7
|
||||||
|
brtc 0f
|
||||||
|
com __tmp_reg__
|
||||||
|
; Adjust dividend's sign
|
||||||
|
rcall __divmodpsi4_negA
|
||||||
|
0:
|
||||||
|
; Adjust divisor's sign
|
||||||
|
sbrc B2, 7
|
||||||
|
rcall __divmodpsi4_negB
|
||||||
|
|
||||||
|
; Do the unsigned div/mod
|
||||||
|
XCALL __udivmodpsi4
|
||||||
|
|
||||||
|
; Adjust quotient's sign
|
||||||
|
sbrc __tmp_reg__, 7
|
||||||
|
rcall __divmodpsi4_negA
|
||||||
|
|
||||||
|
; Adjust remainder's sign
|
||||||
|
brtc __divmodpsi4_end
|
||||||
|
|
||||||
|
__divmodpsi4_negB:
|
||||||
|
; Correct divisor/remainder sign
|
||||||
|
com B2
|
||||||
|
com B1
|
||||||
|
neg B0
|
||||||
|
sbci B1, -1
|
||||||
|
sbci B2, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Correct dividend/quotient sign
|
||||||
|
__divmodpsi4_negA:
|
||||||
|
com A2
|
||||||
|
com A1
|
||||||
|
neg A0
|
||||||
|
sbci A1, -1
|
||||||
|
sbci A2, -1
|
||||||
|
__divmodpsi4_end:
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDF __divmodpsi4
|
||||||
|
#endif /* defined (L_divmodpsi4) */
|
||||||
|
|
||||||
|
#undef A0
|
||||||
|
#undef A1
|
||||||
|
#undef A2
|
||||||
|
|
||||||
|
#undef B0
|
||||||
|
#undef B1
|
||||||
|
#undef B2
|
||||||
|
|
||||||
|
#undef C0
|
||||||
|
#undef C1
|
||||||
|
#undef C2
|
||||||
|
|
||||||
|
#undef r_cnt
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
Division 32 / 32 => (result + remainder)
|
Division 32 / 32 => (result + remainder)
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ LIB1ASMFUNCS = \
|
||||||
_divmodqi4 \
|
_divmodqi4 \
|
||||||
_udivmodhi4 \
|
_udivmodhi4 \
|
||||||
_divmodhi4 \
|
_divmodhi4 \
|
||||||
|
_divmodpsi4 _udivmodpsi4 \
|
||||||
_udivmodsi4 \
|
_udivmodsi4 \
|
||||||
_divmodsi4 \
|
_divmodsi4 \
|
||||||
_prologue \
|
_prologue \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue