/gcc/config/rx/predicates.md

https://github.com/ser8210/gcc-4.5.2-PS3 · Markdown · 295 lines · 252 code · 43 blank · 0 comment · 0 complexity · fefe62ad9727777f70fc8597e234fadb MD5 · raw file

  1. ;; Predicate definitions for Renesas RX.
  2. ;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
  3. ;; Contributed by Red Hat.
  4. ;;
  5. ;; This file is part of GCC.
  6. ;;
  7. ;; GCC is free software; you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation; either version 3, or (at your option)
  10. ;; any later version.
  11. ;;
  12. ;; GCC is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;;
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GCC; see the file COPYING3. If not see
  19. ;; <http://www.gnu.org/licenses/>.
  20. ;; Check that the operand is suitable for a call insn.
  21. ;; Only registers and symbol refs are allowed.
  22. (define_predicate "rx_call_operand"
  23. (match_code "symbol_ref,reg")
  24. )
  25. ;; For sibcall operations we can only use a symbolic address.
  26. (define_predicate "rx_symbolic_call_operand"
  27. (match_code "symbol_ref")
  28. )
  29. ;; Check that the operand is suitable for a shift insn
  30. ;; Only small integers or a value in a register are permitted.
  31. (define_predicate "rx_shift_operand"
  32. (match_code "const_int,reg")
  33. {
  34. if (CONST_INT_P (op))
  35. return IN_RANGE (INTVAL (op), 0, 31);
  36. return true;
  37. }
  38. )
  39. (define_predicate "rx_constshift_operand"
  40. (match_code "const_int")
  41. {
  42. return IN_RANGE (INTVAL (op), 0, 31);
  43. }
  44. )
  45. ;; Check that the operand is suitable as the source operand
  46. ;; for a logic or arithmeitc instruction. Registers, integers
  47. ;; and a restricted subset of memory addresses are allowed.
  48. (define_predicate "rx_source_operand"
  49. (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem")
  50. {
  51. if (CONSTANT_P (op))
  52. return rx_is_legitimate_constant (op);
  53. if (! MEM_P (op))
  54. return true;
  55. /* Do not allow size conversions whilst accessing memory. */
  56. if (GET_MODE (op) != mode)
  57. return false;
  58. return rx_is_restricted_memory_address (XEXP (op, 0), mode);
  59. }
  60. )
  61. ;; Check that the operand is suitable as the source operand
  62. ;; for a comparison instruction. This is the same as
  63. ;; rx_source_operand except that SUBREGs are allowed but
  64. ;; CONST_INTs are not.
  65. (define_predicate "rx_compare_operand"
  66. (match_code "subreg,reg,mem")
  67. {
  68. if (GET_CODE (op) == SUBREG)
  69. return REG_P (XEXP (op, 0));
  70. if (! MEM_P (op))
  71. return true;
  72. return rx_is_restricted_memory_address (XEXP (op, 0), mode);
  73. }
  74. )
  75. ;; Return true if OP is a store multiple operation. This looks like:
  76. ;;
  77. ;; [(set (SP) (MINUS (SP) (INT)))
  78. ;; (set (MEM (SP)) (REG))
  79. ;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
  80. ;; ]
  81. (define_special_predicate "rx_store_multiple_vector"
  82. (match_code "parallel")
  83. {
  84. int count = XVECLEN (op, 0);
  85. unsigned int src_regno;
  86. rtx element;
  87. int i;
  88. /* Perform a quick check so we don't blow up below. */
  89. if (count <= 2)
  90. return false;
  91. /* Check that the first element of the vector is the stack adjust. */
  92. element = XVECEXP (op, 0, 0);
  93. if ( ! SET_P (element)
  94. || ! REG_P (SET_DEST (element))
  95. || REGNO (SET_DEST (element)) != SP_REG
  96. || GET_CODE (SET_SRC (element)) != MINUS
  97. || ! REG_P (XEXP (SET_SRC (element), 0))
  98. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  99. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  100. return false;
  101. /* Check that the next element is the first push. */
  102. element = XVECEXP (op, 0, 1);
  103. if ( ! SET_P (element)
  104. || ! REG_P (SET_SRC (element))
  105. || GET_MODE (SET_SRC (element)) != SImode
  106. || ! MEM_P (SET_DEST (element))
  107. || GET_MODE (SET_DEST (element)) != SImode
  108. || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
  109. || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
  110. || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
  111. || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
  112. || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
  113. != GET_MODE_SIZE (SImode))
  114. return false;
  115. src_regno = REGNO (SET_SRC (element));
  116. /* Check that the remaining elements use SP-<disp>
  117. addressing and decreasing register numbers. */
  118. for (i = 2; i < count; i++)
  119. {
  120. element = XVECEXP (op, 0, i);
  121. if ( ! SET_P (element)
  122. || ! REG_P (SET_SRC (element))
  123. || GET_MODE (SET_SRC (element)) != SImode
  124. || REGNO (SET_SRC (element)) != src_regno - (i - 1)
  125. || ! MEM_P (SET_DEST (element))
  126. || GET_MODE (SET_DEST (element)) != SImode
  127. || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
  128. || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
  129. || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
  130. || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
  131. || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
  132. != i * GET_MODE_SIZE (SImode))
  133. return false;
  134. }
  135. return true;
  136. })
  137. ;; Return true if OP is a load multiple operation.
  138. ;; This looks like:
  139. ;; [(set (SP) (PLUS (SP) (INT)))
  140. ;; (set (REG) (MEM (SP)))
  141. ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
  142. ;; ]
  143. (define_special_predicate "rx_load_multiple_vector"
  144. (match_code "parallel")
  145. {
  146. int count = XVECLEN (op, 0);
  147. unsigned int dest_regno;
  148. rtx element;
  149. int i;
  150. /* Perform a quick check so we don't blow up below. */
  151. if (count <= 2)
  152. return false;
  153. /* Check that the first element of the vector is the stack adjust. */
  154. element = XVECEXP (op, 0, 0);
  155. if ( ! SET_P (element)
  156. || ! REG_P (SET_DEST (element))
  157. || REGNO (SET_DEST (element)) != SP_REG
  158. || GET_CODE (SET_SRC (element)) != PLUS
  159. || ! REG_P (XEXP (SET_SRC (element), 0))
  160. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  161. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  162. return false;
  163. /* Check that the next element is the first push. */
  164. element = XVECEXP (op, 0, 1);
  165. if ( ! SET_P (element)
  166. || ! REG_P (SET_DEST (element))
  167. || ! MEM_P (SET_SRC (element))
  168. || ! REG_P (XEXP (SET_SRC (element), 0))
  169. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
  170. return false;
  171. dest_regno = REGNO (SET_DEST (element));
  172. /* Check that the remaining elements use SP+<disp>
  173. addressing and incremental register numbers. */
  174. for (i = 2; i < count; i++)
  175. {
  176. element = XVECEXP (op, 0, i);
  177. if ( ! SET_P (element)
  178. || ! REG_P (SET_DEST (element))
  179. || GET_MODE (SET_DEST (element)) != SImode
  180. || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
  181. || ! MEM_P (SET_SRC (element))
  182. || GET_MODE (SET_SRC (element)) != SImode
  183. || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
  184. || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
  185. || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
  186. || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
  187. || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
  188. != (i - 1) * GET_MODE_SIZE (SImode))
  189. return false;
  190. }
  191. return true;
  192. })
  193. ;; Return true if OP is a pop-and-return load multiple operation.
  194. ;; This looks like:
  195. ;; [(set (SP) (PLUS (SP) (INT)))
  196. ;; (set (REG) (MEM (SP)))
  197. ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
  198. ;; (return)
  199. ;; ]
  200. (define_special_predicate "rx_rtsd_vector"
  201. (match_code "parallel")
  202. {
  203. int count = XVECLEN (op, 0);
  204. unsigned int dest_regno;
  205. rtx element;
  206. int i;
  207. /* Perform a quick check so we don't blow up below. */
  208. if (count <= 2)
  209. return false;
  210. /* Check that the first element of the vector is the stack adjust. */
  211. element = XVECEXP (op, 0, 0);
  212. if ( ! SET_P (element)
  213. || ! REG_P (SET_DEST (element))
  214. || REGNO (SET_DEST (element)) != SP_REG
  215. || GET_CODE (SET_SRC (element)) != PLUS
  216. || ! REG_P (XEXP (SET_SRC (element), 0))
  217. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  218. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  219. return false;
  220. /* Check that the next element is the first push. */
  221. element = XVECEXP (op, 0, 1);
  222. if ( ! SET_P (element)
  223. || ! REG_P (SET_DEST (element))
  224. || ! MEM_P (SET_SRC (element))
  225. || ! REG_P (XEXP (SET_SRC (element), 0))
  226. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
  227. return false;
  228. dest_regno = REGNO (SET_DEST (element));
  229. /* Check that the remaining elements, if any, and except
  230. for the last one, use SP+<disp> addressing and incremental
  231. register numbers. */
  232. for (i = 2; i < count - 1; i++)
  233. {
  234. element = XVECEXP (op, 0, i);
  235. if ( ! SET_P (element)
  236. || ! REG_P (SET_DEST (element))
  237. || GET_MODE (SET_DEST (element)) != SImode
  238. || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
  239. || ! MEM_P (SET_SRC (element))
  240. || GET_MODE (SET_SRC (element)) != SImode
  241. || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
  242. || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
  243. || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
  244. || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
  245. || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
  246. != (i - 1) * GET_MODE_SIZE (SImode))
  247. return false;
  248. }
  249. /* The last element must be a RETURN. */
  250. element = XVECEXP (op, 0, count - 1);
  251. return GET_CODE (element) == RETURN;
  252. })