ack/lang/cem/cemcom.ansi/blocks.c

195 lines
4.9 KiB
C
Raw Normal View History

1989-02-07 11:04:05 +00:00
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1994-06-27 08:03:14 +00:00
/* $Id$ */
1989-02-07 11:04:05 +00:00
/* B L O C K S T O R I N G A N D L O A D I N G */
#include "parameters.h"
1989-02-07 11:04:05 +00:00
#ifndef LINT
#include <em.h>
#include <em_reg.h>
#include "arith.h"
#include "sizes.h"
#include "atw.h"
#include "align.h"
#ifndef STB
#include "label.h"
#include "stack.h"
#include "Lpars.h"
#include "blocks.h"
#include "macro.h"
#include "util.h"
1989-02-07 11:04:05 +00:00
#define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
1991-08-26 14:26:07 +00:00
#define LocalIntVar() NewLocal(int_size, int_align, reg_any, REGISTER)
#endif /* STB */
1989-02-07 11:04:05 +00:00
/* 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) <empty>
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.
*/
int suitable_sz(arith sz, int al)
1989-02-07 11:04:05 +00:00
{
return ((int)sz % (int)word_size == 0 && al % word_align == 0) ||
1989-02-07 11:04:05 +00:00
(
word_size % sz == 0 &&
(al >= (int)sz || al >= word_align)
/* Lots of Irritating Stupid Parentheses */
);
}
void store_block(arith sz, int al)
{
if (suitable_sz(sz, al))
1989-02-07 11:04:05 +00:00
C_sti(sz);
else {
#ifndef STB
arith src, dst;
/* allocate two pointer temporaries */
src = LocalPtrVar();
dst = LocalPtrVar();
/* load the addresses */
StoreLocal(dst, pointer_size);
C_lor((arith)1); /* push current sp */
StoreLocal(src, pointer_size);
copy_loop(sz, src, dst);
C_asp(ATW(sz));
FreeLocal(dst);
FreeLocal(src);
#else /* STB */
1989-02-07 11:04:05 +00:00
/* 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 */
1989-02-07 11:04:05 +00:00
}
}
void load_block(arith sz, int al)
1989-02-07 11:04:05 +00:00
{
if (suitable_sz(sz, al))
1989-02-07 11:04:05 +00:00
C_loi(sz);
else {
#ifndef STB
arith src, dst;
/* allocate two pointer temporaries */
src = LocalPtrVar();
dst = LocalPtrVar();
StoreLocal(src, pointer_size);
C_asp(-ATW(sz)); /* allocate stack block */
1989-02-07 11:04:05 +00:00
C_lor((arith)1); /* push & of stack block as dst */
StoreLocal(dst, pointer_size);
copy_loop(sz, src, dst);
FreeLocal(dst);
FreeLocal(src);
#else /* STB */
arith esz = ATW(sz) - pointer_size;
C_asp(-esz); /* allocate stack block */
1989-02-07 11:04:05 +00:00
C_lor((arith)1); /* push & of stack block as dst */
C_dup(pointer_size); /* fetch source address */
C_adp(esz);
1989-02-07 11:04:05 +00:00
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 */
1989-02-07 11:04:05 +00:00
}
}
void copy_block(arith sz, int al)
1991-08-26 14:26:07 +00:00
{
if (suitable_sz(sz, al))
C_blm(sz);
else {
#ifndef STB
arith src, dst;
/* allocate two pointer temporaries */
src = LocalPtrVar();
dst = LocalPtrVar();
StoreLocal(dst, pointer_size);
1991-10-29 15:57:26 +00:00
StoreLocal(src, pointer_size);
1991-08-26 14:26:07 +00:00
copy_loop(sz, src, dst);
FreeLocal(dst);
FreeLocal(src);
#else /* STB */
1991-08-26 14:26:07 +00:00
C_loc(sz); /* # bytes to copy */
C_cal("__stb"); /* library copy routine */
C_asp(int_size + pointer_size + pointer_size);
#endif /* STB */
1991-08-26 14:26:07 +00:00
}
}
1989-02-07 11:04:05 +00:00
#ifndef STB
void copy_loop(arith sz, arith src, arith dst)
1989-02-07 11:04:05 +00:00
{
/* generate inline byte-copy loop */
label l_cont = text_label(), l_stop = text_label();
1991-08-26 14:26:07 +00:00
arith tmp_sz = LocalIntVar();
1989-02-07 11:04:05 +00:00
C_loc(sz); /* amount of bytes */
1991-08-26 14:26:07 +00:00
StoreLocal(tmp_sz, int_size);
1989-02-07 11:04:05 +00:00
C_df_ilb(l_cont);
1991-08-26 14:26:07 +00:00
LoadLocal(tmp_sz, int_size);
1989-02-07 11:04:05 +00:00
C_zle(l_stop);
1991-08-26 14:26:07 +00:00
C_del(tmp_sz);
1989-02-07 11:04:05 +00:00
LoadLocal(src, pointer_size);
C_dup(pointer_size);
C_adp((arith)1);
StoreLocal(src, pointer_size);
C_loi((arith)1);
LoadLocal(dst, pointer_size);
C_dup(pointer_size);
C_adp((arith)1);
StoreLocal(dst, pointer_size);
C_sti((arith)1);
C_bra(l_cont);
C_df_ilb(l_stop);
1991-08-26 14:26:07 +00:00
FreeLocal(tmp_sz);
1989-02-07 11:04:05 +00:00
}
#endif /* STB */
1989-02-07 11:04:05 +00:00
#endif /* LINT */
1989-02-07 11:04:05 +00:00