summaryrefslogtreecommitdiffhomepage
path: root/mixlib/mix_ins.h
blob: a9267ad8e4bf8a474420b991a79f833a50372f4c (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/* -*-c-*- -------------------- mix_ins.h:
 * This file declares types and functions for manipulating MIX
 * instructions
 * ------------------------------------------------------------------
 * Copyright (C) 2000, 2006, 2007, 2010 Free Software Foundation, Inc.
 *
 * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */


#ifndef MIX_INS_H
#define MIX_INS_H

#include "mix_types.h"


/* Initialise and free mix_ins data */
extern void
mix_init_ins(void);

extern void
mix_release_ins(void);

/* A MIX instruction is made up of address, index, fspec and op_code */

/*-- Address field: contains two bytes */
typedef mix_short_t  mix_address_t;

/*-- Index field: a value between 0 and 6 */
typedef enum {
  mix_I0, mix_I1, mix_I2, mix_I3, mix_I4, mix_I5, mix_I6 } mix_index_t;

/*-- Instruction id: enumeration of MIX instruction set */
typedef enum {
  mix_NOP,  mix_ADD, mix_SUB, mix_MUL, mix_DIV,
  mix_NUM, mix_CHAR, mix_HLT,
  mix_SLA, mix_SRA, mix_SLAX, mix_SRAX, mix_SLC, mix_SRC, mix_SLB, mix_SRB,
  mix_MOVE, mix_LDA, mix_LD1, mix_LD2, mix_LD3, mix_LD4, mix_LD5,
  mix_LD6,  mix_LDX, mix_LDAN, mix_LD1N, mix_LD2N, mix_LD3N, mix_LD4N,
  mix_LD5N, mix_LD6N, mix_LDXN, mix_STA, mix_ST1, mix_ST2, mix_ST3, mix_ST4,
  mix_ST5, mix_ST6, mix_STX, mix_STJ, mix_STZ, mix_JBUS, mix_IOC, mix_IN,
  mix_OUT, mix_JRED,
  mix_JMP, mix_JSJ, mix_JOV, mix_JNOV, mix_JL, mix_JE, mix_JG, mix_JGE,
  mix_JNE, mix_JLE,
  mix_JAN, mix_JAZ, mix_JAP, mix_JANN, mix_JANZ, mix_JANP,
  mix_JAE, mix_JAO,
  mix_J1N, mix_J1Z, mix_J1P, mix_J1NN, mix_J1NZ, mix_J1NP,
  mix_J2N, mix_J2Z, mix_J2P, mix_J2NN, mix_J2NZ, mix_J2NP,
  mix_J3N, mix_J3Z, mix_J3P, mix_J3NN, mix_J3NZ, mix_J3NP,
  mix_J4N, mix_J4Z, mix_J4P, mix_J4NN, mix_J4NZ, mix_J4NP,
  mix_J5N, mix_J5Z, mix_J5P, mix_J5NN, mix_J5NZ, mix_J5NP,
  mix_J6N, mix_J6Z, mix_J6P, mix_J6NN, mix_J6NZ, mix_J6NP,
  mix_JXN, mix_JXZ, mix_JXP, mix_JXNN, mix_JXNZ, mix_JXNP,
  mix_JXE, mix_JXO,
  mix_INCA, mix_DECA, mix_ENTA, mix_ENNA,
  mix_INC1, mix_DEC1, mix_ENT1, mix_ENN1,
  mix_INC2, mix_DEC2, mix_ENT2, mix_ENN2,
  mix_INC3, mix_DEC3, mix_ENT3, mix_ENN3,
  mix_INC4, mix_DEC4, mix_ENT4, mix_ENN4,
  mix_INC5, mix_DEC5, mix_ENT5, mix_ENN5,
  mix_INC6, mix_DEC6, mix_ENT6, mix_ENN6,
  mix_INCX, mix_DECX, mix_ENTX, mix_ENNX,
  mix_CMPA, mix_CMP1, mix_CMP2, mix_CMP3, mix_CMP4,
  mix_CMP5, mix_CMP6, mix_CMPX, mix_INVALID_INS
} mix_ins_id_t;

/* each one of the above id's has associated an opcode, a default
   fspec and a string representation */
/* the opcode fits in a byte */
typedef mix_byte_t mix_opcode_t;

/* labels for each opcode */
enum {
  mix_opNOP = 0, mix_opADD, mix_opSUB, mix_opMUL, mix_opDIV,
  mix_opSPC, mix_opSLx, mix_opMOVE,
  mix_opLDA, mix_opLD1, mix_opLD2, mix_opLD3, mix_opLD4, mix_opLD5,
  mix_opLD6, mix_opLDX, mix_opLDAN, mix_opLD1N, mix_opLD2N, mix_opLD3N,
  mix_opLD4N, mix_opLD5N, mix_opLD6N, mix_opLDXN,
  mix_opSTA, mix_opST1, mix_opST2, mix_opST3, mix_opST4,
  mix_opST5, mix_opST6, mix_opSTX, mix_opSTJ, mix_opSTZ,
  mix_opJBUS, mix_opIOC, mix_opIN, mix_opOUT, mix_opJRED,
  mix_opJMP, mix_opJAx, mix_opJ1x, mix_opJ2x, mix_opJ3x,
  mix_opJ4x, mix_opJ5x, mix_opJ6x, mix_opJXx,
  mix_opINCA, mix_opINC1, mix_opINC2, mix_opINC3,
  mix_opINC4, mix_opINC5, mix_opINC6, mix_opINCX,
  mix_opCMPA, mix_opCMP1, mix_opCMP2, mix_opCMP3, mix_opCMP4,
  mix_opCMP5, mix_opCMP6, mix_opCMPX
};

extern mix_opcode_t
mix_get_opcode_from_id(mix_ins_id_t id);

extern mix_fspec_t
mix_get_fspec_from_id(mix_ins_id_t id);

/* For extended instructions, both the opcode and fspec determine
   the id (i.e., an explicit fspec cannot be used)
*/
extern gboolean
mix_ins_id_is_extended(mix_ins_id_t id);

extern const gchar *
mix_get_string_from_id(mix_ins_id_t id);

extern mix_ins_id_t
mix_get_id_from_string(const gchar *name);

extern mix_ins_id_t
mix_get_ins_id(mix_opcode_t code, mix_fspec_t fspec);


/*--  MIX instruction type */
typedef struct mix_ins_t mix_ins_t;
struct mix_ins_t
{
  mix_address_t address;
  mix_index_t   index;
  mix_fspec_t   fspec;
  mix_opcode_t  opcode;
};

#define mix_ins_fill_from_id(ins,id)		\
   do {						\
     (ins).opcode = mix_get_opcode_from_id(id);	\
     (ins).fspec = mix_get_fspec_from_id(id);	\
   } while(FALSE)


/* A mix ins can be codified into a word */
extern mix_word_t
mix_ins_to_word(const mix_ins_t *ins);

extern mix_ins_id_t
mix_word_to_ins(mix_word_t w, mix_ins_t *ins);

#define mix_word_add_address(word,addr) (word) |= ((addr)<<18)

/* decompose an instruction codified in a word into its parts */
#define mix_get_ins_address(word) ((mix_address_t)((word)>>18))
#define mix_get_ins_index(word)   ((mix_index_t)(((word)>>12)&7))
#define mix_get_ins_fspec(word)   ((mix_fspec_t)(mix_byte_new((word)>>6)))
#define mix_get_ins_opcode(word)  ((mix_opcode_t)(mix_byte_new(word)))

/* unchecked versions for speed */
#define mix_ins_to_word_uncheck(ins)					\
 (mix_word_t)(((ins).address<<18)|					\
	      (((ins).index)<<12)|((ins).fspec<<6)|((ins).opcode))

#define mix_word_to_ins_uncheck(word,ins)	\
  do {						\
    (ins).address = mix_get_ins_address(word);	\
    (ins).index = mix_get_ins_index(word);	\
    (ins).fspec = mix_get_ins_fspec(word);	\
    (ins).opcode = mix_get_ins_opcode(word);	\
  } while(FALSE)

#define mix_ins_id_from_ins(ins)  mix_get_ins_id((ins).opcode,(ins).fspec)


/* Printable representation */
extern gchar * /* this pointer must be freed by caller */
mix_ins_to_string(const mix_ins_t *ins);

extern void
mix_ins_to_string_in_buffer (const mix_ins_t *ins, gchar *buf, guint len);

extern void
mix_ins_print(const mix_ins_t *ins);


#endif /* MIX_INS_H */