123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /* $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, 0, 0 } /* 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);
- }
|