blocks.c 4.3 KB

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