summaryrefslogtreecommitdiffhomepage
path: root/mixlib/xmix_vm.h
blob: af1d0aeaabcdbef08da9232fd3eff7433d4dcc9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* ---------------------- xmix_vm.h :
 * This file contains internal declarations used in the implementation
 * of the mix_vm_t type.
 * ------------------------------------------------------------------
 * Copyright (C) 2000 jose antonio ortega ruiz <jaortega@acm.org>
 *  
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *  
 */


#ifndef XMIX_VM_H
#define XMIX_VM_H

#include "mix_symbol_table.h"
#include "mix_device.h"
#include "mix_src_file.h"
#include "mix_vm.h"

/* The mix_vm_t type */
enum {IREG_NO_ = 6, BD_NO_ = 21, MEM_CELLS_NO_ = MIX_VM_CELL_NO};
struct mix_vm_t 
{
  mix_word_t reg[IREG_NO_+3];
  mix_word_t cell[MEM_CELLS_NO_];
  gboolean overflow;
  mix_cmpflag_t cmpflag;
  mix_short_t loc_count;
  gboolean is_halted;
  mix_device_t * devices[BD_NO_]; 
  mix_address_t start_addr;	/* start address of loaded file */
  GTree *line_table;		/* source line no -> address  */
  GTree *address_table;		/* adress -> source line no */
  gint8 bp[MEM_CELLS_NO_/8];	/* each bit signals a break point */
  mix_vm_clock_t *clock;		/* the vm clock */
  mix_symbol_table_t *symbol_table;
  mix_src_file_t *src_file;	/* source of last loaded code file */
};

/* Macros for accessing/modifying the above structure.
 * Warning: the arguments of these macros must not have side-effects.
 */
#define IOK_(idx) ( (idx) > 0 && (idx) < IREG_NO_+1 )
#define MEMOK_(addr) ( mix_short_is_positive(addr) && (addr) < MEM_CELLS_NO_ )
#define REGOK_(r) ( (r) >= 0 && (r) < IREG_NO_ + 3 )

enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ };

#define get_reg_(vm, r) ((vm)->reg[r])
#define get_rA_(vm)  get_reg_(vm, A_)
#define get_rX_(vm)  get_reg_(vm, X_)
#define get_rJ_(vm)  get_reg_(vm, J_)
#define get_rI_(vm,idx) get_reg_(vm, I1_ + (idx) - 1)
#define get_cell_(vm,addr) ( MEMOK_(addr) ? vm->cell[addr] : MIX_WORD_ZERO )
#define get_cell_ptr_(vm,addr) ( MEMOK_(addr) ? (vm->cell) + addr : NULL )
#define get_cmp_(vm) (vm->cmpflag)
#define get_over_(vm) (vm->overflow)
#define get_loc_(vm)  (vm->loc_count)
#define get_clock_(vm) (vm->clock)

#define set_reg_(vm,r,x)			\
do {						\
  if ( REGOK_(r) ) vm->reg[r] = (x);		\
} while (FALSE)

#define set_rA_(vm,x)  set_reg_(vm,A_,x)
#define set_rX_(vm,x)  set_reg_(vm,X_,x)
#define set_rJ_(vm,x)  set_reg_(vm,J_,(x)&MIX_SHORT_MAX)
#define set_rI_(vm,idx,x)  set_reg_(vm,(idx) + I1_ - 1,x)

#define set_cell_(vm,addr,x) 			\
do {						\
  if ( MEMOK_(addr) ) (vm)->cell[addr] = (x);	\
} while (FALSE)

#define set_cmp_(vm,x) (vm)->cmpflag = (x)
#define set_over_(vm,x) (vm)->overflow = (x)
#define set_loc_(vm,x)  (vm)->loc_count = (x)&MIX_SHORT_MAX

#define inc_loc_(vm)   				\
do {						\
  vm->loc_count++;				\
  vm->loc_count &= MIX_SHORT_MAX;		\
} while(FALSE)

#define is_halted_(vm) ((vm)->is_halted)
#define halt_(vm,val) ((vm)->is_halted = (val))
#define set_start_(vm,val) ((vm)->start_addr = (val))
#define reset_loc_(vm) set_loc_ (vm, vm->start_addr)
#define update_time_(vm,ins) mix_vm_clock_add_lapse (get_clock_(vm), ins)

/* Breakpoints handling */
#define bp_clear_all_(vm)	memset (vm->bp, 0, MEM_CELLS_NO_/8)
#define bp_set_(vm,addr)	vm->bp[(addr)>>3] |= 1 << ((addr)&7)
#define bp_clear_(vm,addr)	vm->bp[(addr)>>3] &= ~(1 << ((addr)&7))
#define bp_is_set_(vm,addr)	vm->bp[(addr)>>3] & (1 << ((addr)&7))

/* Instruction handlers */
typedef gboolean (*ins_handler_t_)(mix_vm_t *,const mix_ins_t *);

extern ins_handler_t_ ins_handlers_[MIX_BYTE_MAX + 1];


#endif /* XMIX_VM_H */