/gcc/config/rx/predicates.md

https://bitbucket.org/codefirex/toolchain_gcc-4.8 · Markdown · 307 lines · 261 code · 46 blank · 0 comment · 0 complexity · 369653340b11f0aa3d262b11a19ea0f4 MD5 · raw file

  1. ;; Predicate definitions for Renesas RX.
  2. ;; Copyright (C) 2008-2013 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. (ior (match_operand 0 "register_operand")
  33. (and (match_code "const_int")
  34. (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
  35. )
  36. (define_predicate "rx_constshift_operand"
  37. (and (match_code "const_int")
  38. (match_test "IN_RANGE (INTVAL (op), 0, 31)"))
  39. )
  40. (define_predicate "rx_restricted_mem_operand"
  41. (and (match_code "mem")
  42. (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
  43. )
  44. ;; Check that the operand is suitable as the source operand
  45. ;; for a logic or arithmeitc instruction. Registers, integers
  46. ;; and a restricted subset of memory addresses are allowed.
  47. (define_predicate "rx_source_operand"
  48. (ior (match_operand 0 "register_operand")
  49. (match_operand 0 "immediate_operand")
  50. (match_operand 0 "rx_restricted_mem_operand"))
  51. )
  52. ;; Check that the operand is suitable as the source operand
  53. ;; for a comparison instruction. This is the same as
  54. ;; rx_source_operand except that SUBREGs are allowed but
  55. ;; CONST_INTs are not.
  56. (define_predicate "rx_compare_operand"
  57. (ior (match_operand 0 "register_operand")
  58. (match_operand 0 "rx_restricted_mem_operand"))
  59. )
  60. ;; Check that the operand is suitable as the source operand
  61. ;; for a min/max instruction. This is the same as
  62. ;; rx_source_operand except that CONST_INTs are allowed but
  63. ;; REGs and SUBREGs are not.
  64. (define_predicate "rx_minmaxex_operand"
  65. (ior (match_operand 0 "immediate_operand")
  66. (match_operand 0 "rx_restricted_mem_operand"))
  67. )
  68. ;; Return true if OP is a store multiple operation. This looks like:
  69. ;;
  70. ;; [(set (SP) (MINUS (SP) (INT)))
  71. ;; (set (MEM (SP)) (REG))
  72. ;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
  73. ;; ]
  74. (define_special_predicate "rx_store_multiple_vector"
  75. (match_code "parallel")
  76. {
  77. int count = XVECLEN (op, 0);
  78. unsigned int src_regno;
  79. rtx element;
  80. int i;
  81. /* Perform a quick check so we don't blow up below. */
  82. if (count <= 2)
  83. return false;
  84. /* Check that the first element of the vector is the stack adjust. */
  85. element = XVECEXP (op, 0, 0);
  86. if ( ! SET_P (element)
  87. || ! REG_P (SET_DEST (element))
  88. || REGNO (SET_DEST (element)) != SP_REG
  89. || GET_CODE (SET_SRC (element)) != MINUS
  90. || ! REG_P (XEXP (SET_SRC (element), 0))
  91. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  92. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  93. return false;
  94. /* Check that the next element is the first push. */
  95. element = XVECEXP (op, 0, 1);
  96. if ( ! SET_P (element)
  97. || ! REG_P (SET_SRC (element))
  98. || GET_MODE (SET_SRC (element)) != SImode
  99. || ! MEM_P (SET_DEST (element))
  100. || GET_MODE (SET_DEST (element)) != SImode
  101. || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
  102. || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
  103. || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
  104. || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
  105. || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
  106. != GET_MODE_SIZE (SImode))
  107. return false;
  108. src_regno = REGNO (SET_SRC (element));
  109. /* Check that the remaining elements use SP-<disp>
  110. addressing and decreasing register numbers. */
  111. for (i = 2; i < count; i++)
  112. {
  113. element = XVECEXP (op, 0, i);
  114. if ( ! SET_P (element)
  115. || ! REG_P (SET_SRC (element))
  116. || GET_MODE (SET_SRC (element)) != SImode
  117. || REGNO (SET_SRC (element)) != src_regno - (i - 1)
  118. || ! MEM_P (SET_DEST (element))
  119. || GET_MODE (SET_DEST (element)) != SImode
  120. || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
  121. || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
  122. || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
  123. || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
  124. || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
  125. != i * GET_MODE_SIZE (SImode))
  126. return false;
  127. }
  128. return true;
  129. })
  130. ;; Return true if OP is a load multiple operation.
  131. ;; This looks like:
  132. ;; [(set (SP) (PLUS (SP) (INT)))
  133. ;; (set (REG) (MEM (SP)))
  134. ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
  135. ;; ]
  136. (define_special_predicate "rx_load_multiple_vector"
  137. (match_code "parallel")
  138. {
  139. int count = XVECLEN (op, 0);
  140. unsigned int dest_regno;
  141. rtx element;
  142. int i;
  143. /* Perform a quick check so we don't blow up below. */
  144. if (count <= 2)
  145. return false;
  146. /* Check that the first element of the vector is the stack adjust. */
  147. element = XVECEXP (op, 0, 0);
  148. if ( ! SET_P (element)
  149. || ! REG_P (SET_DEST (element))
  150. || REGNO (SET_DEST (element)) != SP_REG
  151. || GET_CODE (SET_SRC (element)) != PLUS
  152. || ! REG_P (XEXP (SET_SRC (element), 0))
  153. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  154. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  155. return false;
  156. /* Check that the next element is the first push. */
  157. element = XVECEXP (op, 0, 1);
  158. if ( ! SET_P (element)
  159. || ! REG_P (SET_DEST (element))
  160. || ! MEM_P (SET_SRC (element))
  161. || ! REG_P (XEXP (SET_SRC (element), 0))
  162. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
  163. return false;
  164. dest_regno = REGNO (SET_DEST (element));
  165. /* Check that the remaining elements use SP+<disp>
  166. addressing and incremental register numbers. */
  167. for (i = 2; i < count; i++)
  168. {
  169. element = XVECEXP (op, 0, i);
  170. if ( ! SET_P (element)
  171. || ! REG_P (SET_DEST (element))
  172. || GET_MODE (SET_DEST (element)) != SImode
  173. || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
  174. || ! MEM_P (SET_SRC (element))
  175. || GET_MODE (SET_SRC (element)) != SImode
  176. || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
  177. || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
  178. || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
  179. || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
  180. || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
  181. != (i - 1) * GET_MODE_SIZE (SImode))
  182. return false;
  183. }
  184. return true;
  185. })
  186. ;; Return true if OP is a pop-and-return load multiple operation.
  187. ;; This looks like:
  188. ;; [(set (SP) (PLUS (SP) (INT)))
  189. ;; (set (REG) (MEM (SP)))
  190. ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
  191. ;; (return)
  192. ;; ]
  193. (define_special_predicate "rx_rtsd_vector"
  194. (match_code "parallel")
  195. {
  196. int count = XVECLEN (op, 0);
  197. unsigned int dest_regno;
  198. rtx element;
  199. int i;
  200. /* Perform a quick check so we don't blow up below. */
  201. if (count <= 2)
  202. return false;
  203. /* Check that the first element of the vector is the stack adjust. */
  204. element = XVECEXP (op, 0, 0);
  205. if ( ! SET_P (element)
  206. || ! REG_P (SET_DEST (element))
  207. || REGNO (SET_DEST (element)) != SP_REG
  208. || GET_CODE (SET_SRC (element)) != PLUS
  209. || ! REG_P (XEXP (SET_SRC (element), 0))
  210. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
  211. || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
  212. return false;
  213. /* Check that the next element is the first push. */
  214. element = XVECEXP (op, 0, 1);
  215. if ( ! SET_P (element)
  216. || ! REG_P (SET_DEST (element))
  217. || ! MEM_P (SET_SRC (element))
  218. || ! REG_P (XEXP (SET_SRC (element), 0))
  219. || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
  220. return false;
  221. dest_regno = REGNO (SET_DEST (element));
  222. /* Check that the remaining elements, if any, and except
  223. for the last one, use SP+<disp> addressing and incremental
  224. register numbers. */
  225. for (i = 2; i < count - 1; i++)
  226. {
  227. element = XVECEXP (op, 0, i);
  228. if ( ! SET_P (element)
  229. || ! REG_P (SET_DEST (element))
  230. || GET_MODE (SET_DEST (element)) != SImode
  231. || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
  232. || ! MEM_P (SET_SRC (element))
  233. || GET_MODE (SET_SRC (element)) != SImode
  234. || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
  235. || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
  236. || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
  237. || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
  238. || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
  239. != (i - 1) * GET_MODE_SIZE (SImode))
  240. return false;
  241. }
  242. /* The last element must be a RETURN. */
  243. element = XVECEXP (op, 0, count - 1);
  244. return GET_CODE (element) == RETURN;
  245. })
  246. (define_predicate "label_ref_operand"
  247. (match_code "label_ref")
  248. )
  249. (define_predicate "rx_z_comparison_operator"
  250. (match_code "eq,ne")
  251. )
  252. (define_predicate "rx_zs_comparison_operator"
  253. (match_code "eq,ne,lt,ge")
  254. )
  255. ;; GT and LE omitted due to operand swap required.
  256. (define_predicate "rx_fp_comparison_operator"
  257. (match_code "eq,ne,lt,ge,ordered,unordered")
  258. )
  259. (define_predicate "rshift_operator"
  260. (match_code "ashiftrt,lshiftrt")
  261. )