m68000-output.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* Subroutines for insn-output.c for Motorola 68000 family.
  2. Copyright (C) 1987 Free Software Foundation, Inc.
  3. This file is part of GNU CC.
  4. GNU CC is distributed in the hope that it will be useful,
  5. but WITHOUT ANY WARRANTY. No author or distributor
  6. accepts responsibility to anyone for the consequences of using it
  7. or for whether it serves any particular purpose or works at all,
  8. unless he says so in writing. Refer to the GNU CC General Public
  9. License for full details.
  10. Everyone is granted permission to copy, modify and redistribute
  11. GNU CC, but only under the conditions described in the
  12. GNU CC General Public License. A copy of this license is
  13. supposed to have been given to you along with GNU CC so you
  14. can know your rights and responsibilities. It should be in a
  15. file named COPYING. Among other things, the copyright notice
  16. and this notice must be preserved on all copies. */
  17. char *
  18. output_btst (operands, countop, dataop, insn, signpos)
  19. rtx *operands;
  20. rtx countop, dataop;
  21. rtx insn;
  22. int signpos;
  23. {
  24. operands[0] = countop;
  25. operands[1] = dataop;
  26. if (GET_CODE (countop) == CONST_INT)
  27. {
  28. register int count = INTVAL (countop);
  29. if (count == signpos)
  30. cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
  31. else
  32. cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
  33. if (count == 31
  34. && next_insn_tests_no_inequality (insn))
  35. return "tstl %1";
  36. if (count == 15
  37. && next_insn_tests_no_inequality (insn))
  38. return "tstw %1";
  39. if (count == 7
  40. && next_insn_tests_no_inequality (insn))
  41. return "tstb %1";
  42. cc_status.flags = CC_NOT_NEGATIVE;
  43. }
  44. return "btst %0,%1";
  45. }
  46. char *
  47. output_move_double (operands)
  48. rtx *operands;
  49. {
  50. int addr0 = 0, addr1 = 0;
  51. int inc0 = 0, inc1 = 0;
  52. rtx reg0 = 0, reg1 = 0;
  53. char *finish0, *finish1;
  54. int good1 = 0;
  55. if (CONSTANT_ADDRESS_P (operands[1]))
  56. {
  57. if (ADDRESS_REG_P (operands[0]))
  58. output_asm_insn ("movw #0,%0", operands);
  59. else
  60. output_asm_insn ("clrl %0", operands);
  61. }
  62. else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  63. {
  64. rtx xoperands[2];
  65. xoperands[0] = operands[0];
  66. xoperands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0));
  67. if (XINT (operands[1], 0) == 0)
  68. output_asm_insn ("clrl %0", xoperands);
  69. else
  70. output_asm_insn ("movl %1,%0", xoperands);
  71. }
  72. else
  73. output_asm_insn ("movl %1,%0", operands);
  74. /* If operand 0 is not offsettable, load its address
  75. into a0. Then likewise for a1. */
  76. if (!REG_P (operands[0]) && !offsetable_address_p (operands[0]))
  77. {
  78. if (GET_CODE (operands[0]) == MEM
  79. && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  80. {
  81. inc0 = 4;
  82. reg0 = XEXP (XEXP (operands[0], 0), 0);
  83. operands[0] = gen_rtx (MEM, DFmode, reg0);
  84. }
  85. if (GET_CODE (operands[0]) == MEM
  86. && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  87. {
  88. inc0 = -4;
  89. reg0 = XEXP (XEXP (operands[0], 0), 0);
  90. operands[0] = gen_rtx (MEM, DFmode, gen_rtx (PLUS, SImode, reg0,
  91. gen_rtx (CONST_INT, VOIDmode, 4)));
  92. }
  93. else
  94. {
  95. output_asm_insn ("movl a0,sp@-;lea %0,a0", operands);
  96. addr0 = 1;
  97. operands[0] = gen_rtx (MEM, DFmode, gen_rtx (REG, SImode, 8));
  98. }
  99. }
  100. if (!REG_P (operands[1]) && !offsetable_address_p (operands[1]))
  101. {
  102. if (GET_CODE (operands[1]) == MEM
  103. && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  104. {
  105. inc1 = 4;
  106. reg1 = XEXP (XEXP (operands[1], 0), 0);
  107. operands[1] = gen_rtx (MEM, DFmode, reg1);
  108. }
  109. if (GET_CODE (operands[1]) == MEM
  110. && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  111. {
  112. inc1 = -4;
  113. reg1 = XEXP (XEXP (operands[1], 0), 0);
  114. operands[1] = gen_rtx (MEM, DFmode, gen_rtx (PLUS, SImode, reg1,
  115. gen_rtx (CONST_INT, VOIDmode, 4)));
  116. }
  117. else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  118. {
  119. operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1));
  120. good1 = 1;
  121. }
  122. else
  123. {
  124. output_asm_insn ("movl a1,sp@-;lea %1,a1", operands);
  125. addr1 = 1;
  126. operands[1] = gen_rtx (MEM, DFmode, gen_rtx (REG, SImode, 9));
  127. }
  128. }
  129. /* ADDR1 nonzero if must restore a1; likewise ADDR0 for a0. */
  130. /* Now set up the operands for the second-half words,
  131. assuming both operands are offsetable. */
  132. if (REG_P (operands[0]))
  133. operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  134. else
  135. operands[0] = adj_offsetable_operand (operands[0], 4);
  136. if (good1)
  137. ;
  138. else if (REG_P (operands[1]))
  139. operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  140. else
  141. operands[1] = adj_offsetable_operand (operands[1], 4);
  142. /* Now copy the second word. */
  143. {
  144. char *s;
  145. if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0)
  146. s = "clrl %0";
  147. else
  148. s = "movl %1,%0";
  149. if (!addr0 && !addr1 && inc0 == 0 && inc1 == 0)
  150. return s;
  151. output_asm_insn (s, operands);
  152. }
  153. /* Now restore regs we saved or increment or decrement regs that need it. */
  154. operands[0] = reg0;
  155. operands[1] = reg1;
  156. if (addr0)
  157. finish0 = "movl sp@+,a0";
  158. else if (inc0 > 0)
  159. finish0 = "addql #4,%0";
  160. else if (inc0 < 0)
  161. finish0 = "subql #4,%0";
  162. else
  163. finish0 = 0;
  164. if (addr1)
  165. finish1 = "movl sp@+,a1";
  166. else if (inc1 > 0)
  167. finish1 = "addql #4,%1";
  168. else if (inc1 < 0)
  169. finish1 = "subql #4,%1";
  170. else
  171. finish1 = 0;
  172. if (finish0 == 0)
  173. return finish1;
  174. if (finish1 != 0)
  175. output_asm_insn (finish1, operands);
  176. return finish0;
  177. }
  178. char *
  179. output_move_const_double (operands)
  180. rtx *operands;
  181. {
  182. int code = standard_68881_constant_p (operands[1]);
  183. if (code != 0)
  184. {
  185. static char buf[40];
  186. sprintf (buf, "fmovecr #0x%x,%%0", code & 0xff);
  187. return buf;
  188. }
  189. return "fmoved %1,%0";
  190. }
  191. /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
  192. from the "fmovecr" instruction.
  193. The value, anded with 0xff, gives the code to use in fmovecr
  194. to get the desired constant. */
  195. int
  196. standard_68881_constant_p (x)
  197. rtx x;
  198. {
  199. union {double d; int i[2];} u;
  200. register double d;
  201. u.i[0] = XINT (x, 0);
  202. u.i[1] = XINT (x, 1);
  203. d = u.d;
  204. if (d == 0)
  205. return 0x0f;
  206. /* Note: there are various other constants available
  207. but it is a nuisance to put in their values here. */
  208. if (d == 1)
  209. return 0x32;
  210. if (d == 10)
  211. return 0x33;
  212. if (d == 100)
  213. return 0x34;
  214. if (d == 10000)
  215. return 0x35;
  216. if (d == 1e8)
  217. return 0x36;
  218. if (d == 1e16)
  219. return 0x37;
  220. if (d == 1e32)
  221. return 0x38;
  222. if (d == 1e64)
  223. return 0x39;
  224. if (d == 1e128)
  225. return 0x3a;
  226. if (d == 1e256)
  227. return 0x3b;
  228. return 0;
  229. }