231 lines
4.9 KiB
C
231 lines
4.9 KiB
C
/* $Id$ */
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
#include <em_mnem.h>
|
|
#include "../share/types.h"
|
|
#include "../share/aux.h"
|
|
#include "../share/debug.h"
|
|
#include "../share/global.h"
|
|
#include "cs.h"
|
|
#include "cs_aux.h"
|
|
#include "cs_entity.h"
|
|
#include "cs_stack.h"
|
|
|
|
#define WS1 0
|
|
#define WS2 1
|
|
#define PS 2
|
|
#define ARGW 3
|
|
#define ARDESC3 4
|
|
|
|
STATIC struct inf_entity {
|
|
byte inf_instr; /* Key. */
|
|
byte inf_used; /* Kind of entity used by key. */
|
|
byte inf_size; /* Indication of the size. */
|
|
} inf_table[] = {
|
|
op_adp, ENAOFFSETTED, PS,
|
|
op_dee, ENEXTERNAL, WS1,
|
|
op_del, ENLOCAL, WS1,
|
|
op_ine, ENEXTERNAL, WS1,
|
|
op_inl, ENLOCAL, WS1,
|
|
op_lae, ENAEXTERNAL, PS,
|
|
op_lal, ENALOCAL, PS,
|
|
op_lar, ENARRELEM, ARDESC3,
|
|
op_ldc, ENCONST, WS2,
|
|
op_lde, ENEXTERNAL, WS2,
|
|
op_ldf, ENOFFSETTED, WS2,
|
|
op_ldl, ENLOCAL, WS2,
|
|
op_lil, ENINDIR, WS1,
|
|
op_lim, ENIGNMASK, WS1,
|
|
op_loc, ENCONST, WS1,
|
|
op_loe, ENEXTERNAL, WS1,
|
|
op_lof, ENOFFSETTED, WS1,
|
|
op_loi, ENINDIR, ARGW,
|
|
op_lol, ENLOCAL, WS1,
|
|
op_lpi, ENPROC, PS,
|
|
op_lxa, ENAARGBASE, PS,
|
|
op_lxl, ENALOCBASE, PS,
|
|
op_sar, ENARRELEM, ARDESC3,
|
|
op_sde, ENEXTERNAL, WS2,
|
|
op_sdf, ENOFFSETTED, WS2,
|
|
op_sdl, ENLOCAL, WS2,
|
|
op_sil, ENINDIR, WS1,
|
|
op_sim, ENIGNMASK, WS1,
|
|
op_ste, ENEXTERNAL, WS1,
|
|
op_stf, ENOFFSETTED, WS1,
|
|
op_sti, ENINDIR, ARGW,
|
|
op_stl, ENLOCAL, WS1,
|
|
op_zer, ENCONST, ARGW,
|
|
op_zre, ENEXTERNAL, WS1,
|
|
op_zrf, ENFZER, ARGW,
|
|
op_zrl, ENLOCAL, WS1,
|
|
op_nop /* Delimitor. */
|
|
};
|
|
|
|
#define INFKEY(ip) (ip->inf_instr & BMASK)
|
|
#define ENKIND(ip) ip->inf_used
|
|
#define SIZEINF(ip) ip->inf_size
|
|
|
|
STATIC struct inf_entity *getinf(n)
|
|
int n;
|
|
{
|
|
struct inf_entity *ip;
|
|
|
|
for (ip = &inf_table[0]; INFKEY(ip) != op_nop; ip++) {
|
|
if (INFKEY(ip) == n) return ip;
|
|
}
|
|
return (struct inf_entity *) 0;
|
|
}
|
|
|
|
entity_p getentity(lnp, l_out)
|
|
line_p lnp, *l_out;
|
|
{
|
|
/* Build the entities where lnp refers to, and enter them.
|
|
* If a token needs to be popped, the first line that pushed
|
|
* it is stored in *l_out.
|
|
* The main entity lnp refers to, is returned.
|
|
*/
|
|
struct entity en;
|
|
struct token tk;
|
|
struct inf_entity *ip;
|
|
valnum vn;
|
|
offset indexsize;
|
|
struct token adesc, index, arbase;
|
|
|
|
*l_out = lnp;
|
|
|
|
/* Lor is a special case. */
|
|
if (INSTR(lnp) == op_lor) {
|
|
offset off = off_set(lnp);
|
|
|
|
en.en_static = FALSE;
|
|
en.en_size = ps;
|
|
switch ((int) off == off ? (int) off : 3) {
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
case 0:
|
|
en.en_kind = ENLOCBASE;
|
|
break;
|
|
case 1:
|
|
return (entity_p) 0;
|
|
case 2:
|
|
en.en_kind = ENHEAPPTR;
|
|
break;
|
|
}
|
|
return en_enter(&en);
|
|
}
|
|
|
|
if ( (ip = getinf(INSTR(lnp))) == (struct inf_entity *) 0)
|
|
return (entity_p) 0; /* It does not refer to any entity. */
|
|
|
|
/* Lil and sil refer to two entities. */
|
|
if (INSTR(lnp) == op_lil || INSTR(lnp) == op_sil) {
|
|
en.en_static = FALSE;
|
|
en.en_kind = ENLOCAL;
|
|
en.en_size = ps; /* Local must be a pointer. */
|
|
en.en_loc = off_set(lnp);
|
|
vn = en_enter(&en)->en_vn;
|
|
}
|
|
|
|
en.en_static = FALSE;
|
|
en.en_kind = ENKIND(ip);
|
|
|
|
/* Fill in the size of the entity. */
|
|
switch (SIZEINF(ip)) {
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
case WS1:
|
|
en.en_size = ws;
|
|
break;
|
|
case WS2:
|
|
en.en_size = 2*ws;
|
|
break;
|
|
case PS:
|
|
en.en_size = ps;
|
|
break;
|
|
case ARGW:
|
|
if (TYPE(lnp) != OPNO) {
|
|
en.en_size = off_set(lnp);
|
|
} else {
|
|
Pop(&tk, (offset) ws);
|
|
*l_out = tk.tk_lfirst;
|
|
en.en_size = UNKNOWN_SIZE;
|
|
}
|
|
break;
|
|
case ARDESC3:
|
|
assert(en.en_kind == ENARRELEM);
|
|
if (TYPE(lnp) != OPNO) {
|
|
indexsize = off_set(lnp);
|
|
} else {
|
|
Pop(&tk, (offset) ws);
|
|
indexsize = UNKNOWN_SIZE;
|
|
}
|
|
Pop(&adesc, (offset) ps);
|
|
en.en_adesc = adesc.tk_vn;
|
|
Pop(&index, indexsize);
|
|
en.en_index = index.tk_vn;
|
|
Pop(&arbase, (offset) ps);
|
|
en.en_arbase = arbase.tk_vn;
|
|
*l_out = arbase.tk_lfirst;
|
|
en.en_size = array_elemsize(adesc.tk_vn);
|
|
break;
|
|
}
|
|
|
|
/* Fill in additional information. */
|
|
switch (en.en_kind) {
|
|
case ENFZER:
|
|
en.en_static = TRUE;
|
|
break;
|
|
case ENCONST:
|
|
en.en_static = TRUE;
|
|
en.en_val = off_set(lnp);
|
|
break;
|
|
case ENALOCAL:
|
|
en.en_static = TRUE;
|
|
case ENLOCAL:
|
|
en.en_loc = off_set(lnp);
|
|
break;
|
|
case ENAEXTERNAL:
|
|
en.en_static = TRUE;
|
|
case ENEXTERNAL:
|
|
en.en_ext = OBJ(lnp);
|
|
break;
|
|
case ENINDIR:
|
|
if (INSTR(lnp) == op_loi || INSTR(lnp) == op_sti) {
|
|
Pop(&tk, (offset) ps);
|
|
*l_out = tk.tk_lfirst;
|
|
vn = tk.tk_vn;
|
|
}
|
|
en.en_ind = vn;
|
|
break;
|
|
case ENAOFFSETTED:
|
|
en.en_static = TRUE;
|
|
case ENOFFSETTED:
|
|
Pop(&tk, (offset) ps);
|
|
*l_out = tk.tk_lfirst;
|
|
en.en_base = tk.tk_vn;
|
|
en.en_off = off_set(lnp);
|
|
break;
|
|
case ENALOCBASE:
|
|
case ENAARGBASE:
|
|
en.en_levels = off_set(lnp);
|
|
if (en.en_levels == 0) {
|
|
/* otherwise the program could change it */
|
|
en.en_static = TRUE;
|
|
}
|
|
break;
|
|
case ENPROC:
|
|
en.en_pro = PROC(lnp);
|
|
break;
|
|
case ENARRELEM:
|
|
/* We gathered the information in the previous switch.
|
|
*/
|
|
break;
|
|
}
|
|
|
|
return en_enter(&en);
|
|
}
|