blocks.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* B L O C K S T O R I N G A N D L O A D I N G */
  7. #include "lint.h"
  8. #ifndef LINT
  9. #include <em.h>
  10. #include <em_reg.h>
  11. #include "arith.h"
  12. #include "sizes.h"
  13. #include "atw.h"
  14. #include "align.h"
  15. #ifndef STB
  16. #include "label.h"
  17. #include "stack.h"
  18. #include "Lpars.h"
  19. #include "util_loc.h"
  20. #include "error.h"
  21. #include "idf_loc.h"
  22. #include "def.h"
  23. #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
  24. #define LocalIntVar() NewLocal(int_size, int_align, reg_any, REGISTER)
  25. static void copy_loop(arith sz, arith src, arith dst);
  26. #endif /* STB */
  27. /* Because EM does not support the loading and storing of
  28. objects having other sizes than word fragment and multiple,
  29. we need to have a way of transferring these objects, whereby
  30. we simulate "loi" and "sti": the address of the source resp.
  31. destination is located on top of stack and a call is done
  32. to load_block() resp. store_block().
  33. ===============================================================
  34. # Loadblock() works on the stack as follows: ([ ] indicates the
  35. # position of the stackpointer)
  36. # lower address--->
  37. # 1) | &object
  38. # 2) | ... ATW(sz) bytes ... | sz | &stack_block | &object
  39. # 3) | ... ATW(sz) bytes ...
  40. ===============================================================
  41. Loadblock() pushes ATW(sz) bytes directly onto the stack!
  42. Store_block() works on the stack as follows:
  43. lower address--->
  44. 1) | ... ATW(sz) bytes ... | &object
  45. 2) | ... ATW(sz) bytes ... | &object | &stack_block | sz
  46. 3) <empty>
  47. If sz is a legal argument for "loi" or "sti", just one EM
  48. instruction is generated.
  49. In the other cases, the notion of alignment is taken into account:
  50. we only push an object of the size accepted by EM onto the stack,
  51. while we need a loop to store the stack block into a memory object.
  52. */
  53. static int suitable_sz(arith sz, int al)
  54. {
  55. return ((int)sz % (int)word_size == 0 && al % word_align == 0) ||
  56. (
  57. word_size % sz == 0 &&
  58. (al >= (int)sz || al >= word_align)
  59. /* Lots of Irritating Stupid Parentheses */
  60. );
  61. }
  62. void store_block(arith sz, int al)
  63. {
  64. if (suitable_sz(sz, al))
  65. C_sti(sz);
  66. else {
  67. #ifndef STB
  68. arith src, dst;
  69. /* allocate two pointer temporaries */
  70. src = LocalPtrVar();
  71. dst = LocalPtrVar();
  72. /* load the addresses */
  73. StoreLocal(dst, pointer_size);
  74. C_lor((arith)1); /* push current sp */
  75. StoreLocal(src, pointer_size);
  76. copy_loop(sz, src, dst);
  77. C_asp(ATW(sz));
  78. FreeLocal(dst);
  79. FreeLocal(src);
  80. #else /* STB */
  81. /* address of destination lies on the stack */
  82. /* push address of first byte of block on stack onto
  83. the stack by computing it from the current stack
  84. pointer position
  85. */
  86. C_lor((arith)1); /* push current sp */
  87. C_adp(pointer_size); /* set & to 1st byte of block */
  88. C_loc(sz); /* number of bytes to transfer */
  89. C_cal("__stb"); /* call transfer routine */
  90. C_asp(pointer_size + pointer_size + int_size + ATW(sz));
  91. #endif /* STB */
  92. }
  93. }
  94. void load_block(arith sz, int al)
  95. {
  96. if (suitable_sz(sz, al))
  97. C_loi(sz);
  98. else {
  99. #ifndef STB
  100. arith src, dst;
  101. /* allocate two pointer temporaries */
  102. src = LocalPtrVar();
  103. dst = LocalPtrVar();
  104. StoreLocal(src, pointer_size);
  105. C_asp(-ATW(sz)); /* allocate stack block */
  106. C_lor((arith)1); /* push & of stack block as dst */
  107. StoreLocal(dst, pointer_size);
  108. copy_loop(sz, src, dst);
  109. FreeLocal(dst);
  110. FreeLocal(src);
  111. #else /* STB */
  112. arith esz = ATW(sz) - pointer_size;
  113. C_asp(-esz); /* allocate stack block */
  114. C_lor((arith)1); /* push & of stack block as dst */
  115. C_dup(pointer_size); /* fetch source address */
  116. C_adp(esz);
  117. C_loi(pointer_size);
  118. C_loc(sz); /* # bytes to copy */
  119. C_cal("__stb"); /* library copy routine */
  120. C_asp(int_size + pointer_size + pointer_size);
  121. #endif /* STB */
  122. }
  123. }
  124. void copy_block(arith sz, int al)
  125. {
  126. if (suitable_sz(sz, al))
  127. C_blm(sz);
  128. else {
  129. #ifndef STB
  130. arith src, dst;
  131. /* allocate two pointer temporaries */
  132. src = LocalPtrVar();
  133. dst = LocalPtrVar();
  134. StoreLocal(dst, pointer_size);
  135. StoreLocal(src, pointer_size);
  136. copy_loop(sz, src, dst);
  137. FreeLocal(dst);
  138. FreeLocal(src);
  139. #else /* STB */
  140. C_loc(sz); /* # bytes to copy */
  141. C_cal("__stb"); /* library copy routine */
  142. C_asp(int_size + pointer_size + pointer_size);
  143. #endif /* STB */
  144. }
  145. }
  146. #ifndef STB
  147. static void copy_loop(arith sz, arith src, arith dst)
  148. {
  149. /* generate inline byte-copy loop */
  150. label l_cont = text_label(), l_stop = text_label();
  151. arith tmp_sz = LocalIntVar();
  152. C_loc(sz); /* amount of bytes */
  153. StoreLocal(tmp_sz, int_size);
  154. C_df_ilb(l_cont);
  155. LoadLocal(tmp_sz, int_size);
  156. C_zle(l_stop);
  157. C_del(tmp_sz);
  158. LoadLocal(src, pointer_size);
  159. C_dup(pointer_size);
  160. C_adp((arith)1);
  161. StoreLocal(src, pointer_size);
  162. C_loi((arith)1);
  163. LoadLocal(dst, pointer_size);
  164. C_dup(pointer_size);
  165. C_adp((arith)1);
  166. StoreLocal(dst, pointer_size);
  167. C_sti((arith)1);
  168. C_bra(l_cont);
  169. C_df_ilb(l_stop);
  170. FreeLocal(tmp_sz);
  171. }
  172. #endif /* STB */
  173. #endif /* LINT */