diff options
Diffstat (limited to 'gcc/config/avr/avr.md')
| -rw-r--r-- | gcc/config/avr/avr.md | 262 |
1 files changed, 254 insertions, 8 deletions
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 858b39f..6635856 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -21,6 +21,16 @@ ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. +;; Special characters after '%': +;; A No effect (add 0). +;; B Add 1 to REG number, MEM address or CONST_INT. +;; C Add 2. +;; D Add 3. +;; j Branch condition. +;; k Reverse branch condition. +;; o Displacement for (mem (plus (reg) (const_int))) operands. +;; ~ Output 'r' if not AVR_MEGA. + ;; UNSPEC usage: ;; 0 Length of a string, see "strlenhi". ;; 1 Read from a word address in program memory, see "casesi". @@ -634,7 +644,20 @@ ;****************************************************************************** ; mul -(define_insn "mulqi3" +(define_expand "mulqi3" + [(set (match_operand:QI 0 "register_operand" "") + (mult:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "register_operand" "")))] + "" + "{ + if (!AVR_ENHANCED) + { + emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2])); + DONE; + } +}") + +(define_insn "*mulqi3_enh" [(set (match_operand:QI 0 "register_operand" "=r") (mult:QI (match_operand:QI 1 "register_operand" "r") (match_operand:QI 2 "register_operand" "r")))] @@ -645,6 +668,25 @@ [(set_attr "length" "3") (set_attr "cc" "clobber")]) +(define_expand "mulqi3_call" + [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) + (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) + (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 22))]) + (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))] + "" + "") + +(define_insn "*mulqi3_call" + [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 22))] + "!AVR_ENHANCED" + "%~call __mulqi3" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + (define_insn "mulqihi3" [(set (match_operand:HI 0 "register_operand" "=r") (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d")) @@ -667,7 +709,21 @@ [(set_attr "length" "3") (set_attr "cc" "clobber")]) -(define_insn "mulhi3" +(define_expand "mulhi3" + [(set (match_operand:HI 0 "register_operand" "") + (mult:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "register_operand" "")))] + "" + " +{ + if (!AVR_ENHANCED) + { + emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2])); + DONE; + } +}") + +(define_insn "*mulhi3_enh" [(set (match_operand:HI 0 "register_operand" "=&r") (mult:HI (match_operand:HI 1 "register_operand" "r") (match_operand:HI 2 "register_operand" "r")))] @@ -682,6 +738,200 @@ [(set_attr "length" "7") (set_attr "cc" "clobber")]) +(define_expand "mulhi3_call" + [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) + (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 22)) + (clobber (reg:QI 21))]) + (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))] + "" + "") + +(define_insn "*mulhi3_call" + [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 22)) + (clobber (reg:QI 21))] + "!AVR_ENHANCED" + "%~call __mulhi3" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +;; Operand 2 (reg:SI 18) not clobbered on the enhanced core. +;; All call-used registers clobbered otherwise - normal library call. +(define_expand "mulsi3" + [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) + (set (reg:SI 18) (match_operand:SI 2 "register_operand" "")) + (parallel [(set (reg:SI 22) (mult:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))]) + (set (match_operand:SI 0 "register_operand" "") (reg:SI 22))] + "AVR_ENHANCED" + "") + +(define_insn "*mulsi3_call" + [(set (reg:SI 22) (mult:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))] + "AVR_ENHANCED" + "%~call __mulsi3" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % +; divmod + +;; Generate libgcc.S calls ourselves, because: +;; - we know exactly which registers are clobbered (for QI and HI +;; modes, some of the call-used registers are preserved) +;; - we get both the quotient and the remainder at no extra cost + +(define_expand "divmodqi4" + [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) + (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) + (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22))) + (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 23))]) + (set (match_operand:QI 0 "register_operand" "") (reg:QI 24)) + (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))] + "" + "") + +(define_insn "*divmodqi4_call" + [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22))) + (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 22)) + (clobber (reg:QI 23))] + "" + "%~call __divmodqi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +(define_expand "udivmodqi4" + [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) + (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) + (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22))) + (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 23))]) + (set (match_operand:QI 0 "register_operand" "") (reg:QI 24)) + (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))] + "" + "") + +(define_insn "*udivmodqi4_call" + [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22))) + (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22))) + (clobber (reg:QI 23))] + "" + "%~call __udivmodqi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +(define_expand "divmodhi4" + [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) + (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) + (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 26)) + (clobber (reg:QI 21))]) + (set (match_operand:HI 0 "register_operand" "") (reg:HI 22)) + (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))] + "" + "") + +(define_insn "*divmodhi4_call" + [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) + (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 26)) + (clobber (reg:QI 21))] + "" + "%~call __divmodhi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +(define_expand "udivmodhi4" + [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) + (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) + (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 26)) + (clobber (reg:QI 21))]) + (set (match_operand:HI 0 "register_operand" "") (reg:HI 22)) + (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))] + "" + "") + +(define_insn "*udivmodhi4_call" + [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) + (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) + (clobber (reg:HI 26)) + (clobber (reg:QI 21))] + "" + "%~call __udivmodhi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +(define_expand "divmodsi4" + [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) + (set (reg:SI 18) (match_operand:SI 2 "register_operand" "")) + (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18))) + (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))]) + (set (match_operand:SI 0 "register_operand" "") (reg:SI 18)) + (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))] + "" + "") + +(define_insn "*divmodsi4_call" + [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18))) + (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))] + "" + "%~call __divmodsi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + +(define_expand "udivmodsi4" + [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) + (set (reg:SI 18) (match_operand:SI 2 "register_operand" "")) + (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18))) + (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))]) + (set (match_operand:SI 0 "register_operand" "") (reg:SI 18)) + (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))] + "" + "") + +(define_insn "*udivmodsi4_call" + [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18))) + (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18))) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))] + "" + "%~call __udivmodsi4" + [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no") + (const_int 1) + (const_int 2))) + (set_attr "cc" "clobber")]) + ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; and @@ -1794,9 +2044,7 @@ AS2 (mov, r31, %B0) CR_TAB \"icall\"); } - else if (!AVR_MEGA) - return AS1(rcall,%c0); - return AS1(call,%c0); + return AS1(%~call,%c0); }" [(set_attr "cc" "clobber,clobber,clobber") (set_attr_alternative "length" @@ -1829,9 +2077,7 @@ AS2 (mov, r31, %B1) CR_TAB \"icall\"); } - else if (!AVR_MEGA) - return AS1(rcall,%c1); - return AS1(call,%c1); + return AS1(%~call,%c1); }" [(set_attr "cc" "clobber,clobber,clobber") (set_attr_alternative "length" |
