1 /* ---------------------- xmix_vm.h :
2  * This file contains internal declarations used in the implementation
3  * of the mix_vm_t type.
4  * ------------------------------------------------------------------
5  * Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 
24 #ifndef XMIX_VM_H
25 #define XMIX_VM_H
26 
27 #include <string.h>
28 
29 #include "mix_symbol_table.h"
30 #include "mix_device.h"
31 #include "mix_src_file.h"
32 #include "mix_predicate_list.h"
33 #include "mix_vm.h"
34 
35 /* The mix_vm_t type */
36 enum {
37   IREG_NO_ = 6,
38   BD_NO_ = 21,
39   MEM_CELLS_NO_ = MIX_VM_CELL_NO,
40   MEM_CELLS_MAX_ = MIX_VM_CELL_NO - 1
41 };
42 
43 struct mix_vm_t
44 {
45   mix_word_t reg[IREG_NO_+3];
46   mix_word_t cell[MEM_CELLS_NO_];
47   gboolean overflow;
48   mix_cmpflag_t cmpflag;
49   mix_short_t loc_count;
50   mix_vm_status_t status;
51   mix_vm_error_t last_error;
52   mix_device_t * devices[BD_NO_];
53   gint max_backtrace_amount;    /* the limit of backtraces */
54   mix_address_t start_addr;	/* start address of loaded file */
55   GTree *line_table;		/* source line no -> address  */
56   GTree *address_table;		/* adress -> source line no */
57   gint8 bp[MEM_CELLS_NO_/8];	/* each bit signals a break point */
58   mix_vm_clock_t *clock;		/* the vm clock */
59   mix_symbol_table_t *symbol_table;
60   mix_src_file_t *src_file;	/* source of last loaded code file */
61   mix_device_factory_t factory; /* the factory for new devices */
62   mix_predicate_list_t *pred_list; /* predicates for conditional bps */
63   GQueue *address_list;		/* list of executed addresses */
64 };
65 
66 /* Macros for accessing/modifying the above structure.
67  * Warning: the arguments of these macros must not have side-effects.
68  */
69 #define IOK_(idx) ( (idx) > 0 && (idx) < IREG_NO_+1 )
70 #define MEMOK_(addr) ( mix_short_is_positive(addr) && (addr) < MEM_CELLS_NO_ )
71 #define REGOK_(r) ( (r) >= 0 && (r) < IREG_NO_ + 3 )
72 
73 enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ };
74 
75 #define get_reg_(vm, r) ((vm)->reg[r])
76 #define get_rA_(vm)  get_reg_(vm, A_)
77 #define get_rX_(vm)  get_reg_(vm, X_)
78 #define get_rJ_(vm)  get_reg_(vm, J_)
79 #define get_rI_(vm,idx) get_reg_(vm, I1_ + (idx) - 1)
80 #define get_cell_(vm,addr) ( MEMOK_(addr) ? vm->cell[addr] : MIX_WORD_ZERO )
81 #define get_cell_ptr_(vm,addr) ( MEMOK_(addr) ? (vm->cell) + addr : NULL )
82 #define get_cmp_(vm) (vm->cmpflag)
83 #define get_over_(vm) (vm->overflow)
84 #define get_loc_(vm)  (vm->loc_count)
85 #define get_clock_(vm) (vm->clock)
86 #define get_pred_list_(vm) (vm->pred_list)
87 #define get_address_list_(vm) (vm->address_list)
88 #define get_status_(vm) (vm->status)
89 #define get_last_error_(vm) (vm->last_error)
90 #define set_last_error_(vm,error) ((vm)->last_error = (error))
91 
92 #define set_reg_(vm,r,x)			\
93 do {						\
94   if ( REGOK_(r) ) vm->reg[r] = (x);		\
95 } while (FALSE)
96 
97 #define set_rA_(vm,x)  set_reg_(vm,A_,x)
98 #define set_rX_(vm,x)  set_reg_(vm,X_,x)
99 #define set_rJ_(vm,x)  set_reg_(vm,J_,(x)&MIX_SHORT_MAX)
100 #define set_rI_(vm,idx,x)  set_reg_(vm,(idx) + I1_ - 1,x)
101 
102 #define set_cell_(vm,addr,x) 			\
103 do {						\
104   if ( MEMOK_(addr) ) (vm)->cell[addr] = (x);	\
105 } while (FALSE)
106 
107 #define set_cmp_(vm,x) (vm)->cmpflag = (x)
108 #define set_over_(vm,x) (vm)->overflow = (x)
109 #define set_loc_(vm,x)  (vm)->loc_count = (MEMOK_(x)? (x) : MIX_SHORT_ZERO)
110 
111 #define set_status_(vm,s) ((vm)->status = (s))
112 #define is_halted_(vm) ((vm)->status == MIX_VM_HALT)
113 #define halt_(vm,val) ((vm)->status = (val)? MIX_VM_HALT : MIX_VM_RUNNING)
114 
115 #define inc_loc_(vm)				\
116 do {						\
117   if (++(vm->loc_count) == MEM_CELLS_NO_)	\
118     { vm->loc_count--; halt_(vm, TRUE); }	\
119 } while(FALSE)
120 
121 #define set_start_(vm,val) ((vm)->start_addr = (val))
122 #define reset_loc_(vm) set_loc_ (vm, vm->start_addr)
123 #define update_time_(vm,ins) mix_vm_clock_add_lapse (get_clock_(vm), ins)
124 
125 /* Breakpoints handling */
126 #define bp_clear_all_(vm)	memset (vm->bp, 0, MEM_CELLS_NO_/8)
127 #define bp_set_(vm,addr)	vm->bp[(addr)>>3] |= 1 << ((addr)&7)
128 #define bp_clear_(vm,addr)	vm->bp[(addr)>>3] &= ~(1 << ((addr)&7))
129 #define bp_is_set_(vm,addr)	vm->bp[(addr)>>3] & (1 << ((addr)&7))
130 
131 /* Instruction handlers */
132 typedef gboolean (*ins_handler_t_)(mix_vm_t *,const mix_ins_t *);
133 
134 extern ins_handler_t_ ins_handlers_[MIX_BYTE_MAX + 1];
135 
136 
137 #endif /* XMIX_VM_H */
138 
139