/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* $Header$ */ /* B L O C K S T O R I N G A N D L O A D I N G */ #include #include "arith.h" #include "sizes.h" #include "atw.h" #ifndef STB #include "label.h" #include "stack.h" #endif STB /* Because EM does not support the loading and storing of objects having other sizes than word fragment and multiple, we need to have a way of transferring these objects, whereby we simulate "loi" and "sti": the address of the source resp. destination is located on top of stack and a call is done to load_block() resp. store_block(). =============================================================== # Loadblock() works on the stack as follows: ([ ] indicates the # position of the stackpointer) # lower address---> # 1) | &object # 2) | ... ATW(sz) bytes ... | sz | &stack_block | &object # 3) | ... ATW(sz) bytes ... =============================================================== Loadblock() pushes ATW(sz) bytes directly onto the stack! Store_block() works on the stack as follows: lower address---> 1) | ... ATW(sz) bytes ... | &object 2) | ... ATW(sz) bytes ... | &object | &stack_block | sz 3) If sz is a legal argument for "loi" or "sti", just one EM instruction is generated. In the other cases, the notion of alignment is taken into account: we only push an object of the size accepted by EM onto the stack, while we need a loop to store the stack block into a memory object. */ store_block(sz, al) arith sz; int al; { if ( ((sz == al) && (word_align % al == 0)) || ( (sz % word_size == 0 || word_size % sz == 0) && (al % word_align == 0) ) ) /* Lots of Irritating Stupid Parentheses */ C_sti(sz); else { #ifndef STB arith src, dst, src_offs, dst_offs; /* allocate two pointer temporaries */ src = tmp_pointer_var(&src_offs); dst = tmp_pointer_var(&dst_offs); /* load the addresses */ C_lal(dst); C_sti(pointer_size); C_lor((arith)1); /* push current sp */ C_lal(src); C_sti(pointer_size); copy_loop(sz, src, dst); C_asp(ATW(sz)); free_tmp_var(dst_offs); free_tmp_var(src_offs); #else STB /* address of destination lies on the stack */ /* push address of first byte of block on stack onto the stack by computing it from the current stack pointer position */ C_lor((arith)1); /* push current sp */ C_adp(pointer_size); /* set & to 1st byte of block */ C_loc(sz); /* number of bytes to transfer */ C_cal("__stb"); /* call transfer routine */ C_asp(pointer_size + pointer_size + int_size + ATW(sz)); #endif STB } } load_block(sz, al) arith sz; int al; { arith esz = ATW(sz); /* effective size == actual # pushed bytes */ if ((sz == al) && (word_align % al == 0)) C_loi(sz); else if (al % word_align == 0) C_loi(esz); else { #ifndef STB arith src, dst, src_offs, dst_offs; /* allocate two pointer temporaries */ src = tmp_pointer_var(&src_offs); dst = tmp_pointer_var(&dst_offs); C_lal(src); C_sti(pointer_size); C_asp(-esz); /* allocate stack block */ C_lor((arith)1); /* push & of stack block as dst */ C_lal(dst); C_sti(pointer_size); copy_loop(sz, src, dst); free_tmp_var(dst_offs); free_tmp_var(src_offs); #else STB C_asp(-(esz - pointer_size)); /* allocate stack block */ C_lor((arith)1); /* push & of stack block as dst */ C_dup(pointer_size); /* fetch source address */ C_adp(esz - pointer_size); C_loi(pointer_size); C_loc(sz); /* # bytes to copy */ C_cal("__stb"); /* library copy routine */ C_asp(int_size + pointer_size + pointer_size); #endif STB } } #ifndef STB copy_loop(sz, src, dst) arith sz, src, dst; { /* generate inline byte-copy loop */ label l_cont = text_label(), l_stop = text_label(); C_loc(sz); /* amount of bytes */ C_df_ilb(l_cont); C_dup(word_size); C_zle(l_stop); C_dec(); C_lal(src); C_loi(pointer_size); C_dup(pointer_size); C_adp((arith)1); C_lal(src); C_sti(pointer_size); C_loi((arith)1); C_lal(dst); C_loi(pointer_size); C_dup(pointer_size); C_adp((arith)1); C_lal(dst); C_sti(pointer_size); C_sti((arith)1); C_bra(l_cont); C_df_ilb(l_stop); C_asp(word_size); } #endif STB