blocks.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. extern arith NewLocal();
  20. #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
  21. #endif /* STB */
  22. /* Because EM does not support the loading and storing of
  23. objects having other sizes than word fragment and multiple,
  24. we need to have a way of transferring these objects, whereby
  25. we simulate "loi" and "sti": the address of the source resp.
  26. destination is located on top of stack and a call is done
  27. to load_block() resp. store_block().
  28. ===============================================================
  29. # Loadblock() works on the stack as follows: ([ ] indicates the
  30. # position of the stackpointer)
  31. # lower address--->
  32. # 1) | &object
  33. # 2) | ... ATW(sz) bytes ... | sz | &stack_block | &object
  34. # 3) | ... ATW(sz) bytes ...
  35. ===============================================================
  36. Loadblock() pushes ATW(sz) bytes directly onto the stack!
  37. Store_block() works on the stack as follows:
  38. lower address--->
  39. 1) | ... ATW(sz) bytes ... | &object
  40. 2) | ... ATW(sz) bytes ... | &object | &stack_block | sz
  41. 3) <empty>
  42. If sz is a legal argument for "loi" or "sti", just one EM
  43. instruction is generated.
  44. In the other cases, the notion of alignment is taken into account:
  45. we only push an object of the size accepted by EM onto the stack,
  46. while we need a loop to store the stack block into a memory object.
  47. */
  48. store_block(sz, al)
  49. arith sz;
  50. int al;
  51. {
  52. if (
  53. ((sz == al) && (word_align % al == 0)) ||
  54. (
  55. (sz % word_size == 0 || word_size % sz == 0) &&
  56. (al % word_align == 0)
  57. )
  58. ) /* Lots of Irritating Stupid Parentheses */
  59. C_sti(sz);
  60. else {
  61. #ifndef STB
  62. arith src, dst;
  63. /* allocate two pointer temporaries */
  64. src = LocalPtrVar();
  65. dst = LocalPtrVar();
  66. /* load the addresses */
  67. StoreLocal(dst, pointer_size);
  68. C_lor((arith)1); /* push current sp */
  69. StoreLocal(src, pointer_size);
  70. copy_loop(sz, src, dst);
  71. C_asp(ATW(sz));
  72. FreeLocal(dst);
  73. FreeLocal(src);
  74. #else /* STB *?
  75. /* address of destination lies on the stack */
  76. /* push address of first byte of block on stack onto
  77. the stack by computing it from the current stack
  78. pointer position
  79. */
  80. C_lor((arith)1); /* push current sp */
  81. C_adp(pointer_size); /* set & to 1st byte of block */
  82. C_loc(sz); /* number of bytes to transfer */
  83. C_cal("__stb"); /* call transfer routine */
  84. C_asp(pointer_size + pointer_size + int_size + ATW(sz));
  85. #endif /* STB */
  86. }
  87. }
  88. load_block(sz, al)
  89. arith sz;
  90. int al;
  91. {
  92. arith esz = ATW(sz); /* effective size == actual # pushed bytes */
  93. if (
  94. ((sz == al) && (word_align % al == 0)) ||
  95. (
  96. (sz % word_size == 0 || word_size % sz == 0) &&
  97. (al % word_align == 0)
  98. )
  99. ) /* Lots of Irritating Stupid Parentheses */
  100. C_loi(sz);
  101. else {
  102. #ifndef STB
  103. arith src, dst;
  104. /* allocate two pointer temporaries */
  105. src = LocalPtrVar();
  106. dst = LocalPtrVar();
  107. StoreLocal(src, pointer_size);
  108. C_asp(-esz); /* allocate stack block */
  109. C_lor((arith)1); /* push & of stack block as dst */
  110. StoreLocal(dst, pointer_size);
  111. copy_loop(sz, src, dst);
  112. FreeLocal(dst);
  113. FreeLocal(src);
  114. #else /* STB */
  115. C_asp(-(esz - pointer_size)); /* allocate stack block */
  116. C_lor((arith)1); /* push & of stack block as dst */
  117. C_dup(pointer_size); /* fetch source address */
  118. C_adp(esz - pointer_size);
  119. C_loi(pointer_size);
  120. C_loc(sz); /* # bytes to copy */
  121. C_cal("__stb"); /* library copy routine */
  122. C_asp(int_size + pointer_size + pointer_size);
  123. #endif /* STB */
  124. }
  125. }
  126. #ifndef STB
  127. copy_loop(sz, src, dst)
  128. arith sz, src, dst;
  129. {
  130. /* generate inline byte-copy loop */
  131. label l_cont = text_label(), l_stop = text_label();
  132. C_loc(sz); /* amount of bytes */
  133. C_df_ilb(l_cont);
  134. C_dup(word_size);
  135. C_zle(l_stop);
  136. C_dec();
  137. LoadLocal(src, pointer_size);
  138. C_dup(pointer_size);
  139. C_adp((arith)1);
  140. StoreLocal(src, pointer_size);
  141. C_loi((arith)1);
  142. LoadLocal(dst, pointer_size);
  143. C_dup(pointer_size);
  144. C_adp((arith)1);
  145. StoreLocal(dst, pointer_size);
  146. C_sti((arith)1);
  147. C_bra(l_cont);
  148. C_df_ilb(l_stop);
  149. C_asp(word_size);
  150. }
  151. #endif /* STB */
  152. #endif /* LINT */