-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopcodes.c
156 lines (146 loc) · 3.78 KB
/
opcodes.c
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
#include <string.h>
#include <ctype.h>
#include "opcodes.h"
#include "globals.h"
int num_operands(char *line);
const int
opcodes[OPCODE_NUM][4] =
{
/* {OPCODE, SOURCE , DESTINATION, OPERANDS_NUM} */
{MOV, ADDMODE_ALL, ADDMODE_123, 2}, /* index 0 */
{CMP, ADDMODE_ALL, ADDMODE_ALL, 2}, /* index 1 */
{ADD, ADDMODE_ALL, ADDMODE_123, 2}, /* index 2 */
{SUB, ADDMODE_ALL, ADDMODE_123, 2}, /* index 3 */
{NOT, ADDMODE_NONE, ADDMODE_123, 1}, /* index 4 */
{CLR, ADDMODE_NONE, ADDMODE_123, 1}, /* index 5 */
{LEA, ADDMODE_12, ADDMODE_123, 2}, /* index 6 */
{INC, ADDMODE_NONE, ADDMODE_123, 1}, /* index 7 */
{DEC, ADDMODE_NONE, ADDMODE_123, 1}, /* index 8 */
{JMP, ADDMODE_NONE, ADDMODE_13, 1}, /* index 9 */
{BNE, ADDMODE_NONE, ADDMODE_13, 1}, /* index 10 */
{RED, ADDMODE_NONE, ADDMODE_123, 1}, /* index 11 */
{PRN, ADDMODE_NONE, ADDMODE_ALL, 1}, /* index 12 */
{JSR, ADDMODE_NONE, ADDMODE_13, 1}, /* index 13 */
{RTS, ADDMODE_NONE, ADDMODE_NONE, 0}, /* index 14 */
{STOP, ADDMODE_NONE, ADDMODE_NONE, 0} /* index 15 */
};
int
check_operands(char *line, unsigned ins)
{
int ops = num_operands(line);
int c_ops = opcodes[ins][OPERANDS_NUM];
if(c_ops == ops)
{
return ops;
}
else if (c_ops > ops)
{
ERROR_NUM("Not enough operands", c_ops)
return ERROR;
}
else
{
ERROR_NUM("Too many operands", c_ops)
return ERROR;
}
}
/**
* Count all commas in line after label.
* number of operands equal to the number of commas plus 1.
*/
int
num_operands(char *line)
{
int ops = 1;
const char *c = line;
if(strcmp_hash(line, "stop") || strcmp_hash(line, "rts"))
return 0;
while(*c)
{
if(*c++ == ',')
ops++;
}
return ops;
}
/**
* parse the operand for the correct addressing mode used
*/
int
get_addmode(char *operand, unsigned code, int mode, int *abs, char *p_macro)
{
/* Supported addressing mode for current opcode */
int sup_mode = opcodes[code][mode];
int tmplen;
char tmp[LINE_LEN];
char *macro;
strcpy(tmp, operand);
tmplen = strlen(tmp);
if((sup_mode & ADDMODE_0) && *(tmp) == '#' && (is_name(++operand) || is_num(operand)))
{
if(is_num(tmp))
*abs = TRUE;
else
*abs = FALSE;
return ADDMODE_0;
}
else if((sup_mode & ADDMODE_3) && (is_register(operand) != ERROR))
{
*abs = TRUE;
return ADDMODE_3;
}
else if ((sup_mode & ADDMODE_2) && is_name(strtok(tmp, "[")) && (tmplen != strlen(tmp)))
{
strcpy(p_macro, tmp);
macro = strtok(NULL, "]");
if(is_name(macro))
{
*abs = FALSE;
return ADDMODE_2;
}
else if (is_num(macro))
{
*abs = TRUE;
return ADDMODE_2;
}
else
{
ERROR_MSG("Failed to interpret the appropriate addressing mode")
return ERROR;
}
}
else if((sup_mode & ADDMODE_1) && is_name(operand))
{
return ADDMODE_1;
}
else
{
ERROR_MSG("Failed to interpret the appropriate addressing mode\n\tMost likely unsupported addressing mode for the requested opcode")
return ERROR;
}
return ERROR;
}
int
addmod_sz(int mode)
{
if(mode & ADDMODE_2)
return 2;
return 1;
}
int
get_are(int mode)
{
switch (mode)
{
case ADDMODE_0:
return ABSOLUTE;
case ADDMODE_3:
return ABSOLUTE;
case ADDMODE_1:
return RELOCATABLE | EXTERNAL;
case ADDMODE_2:
return RELOCATABLE | EXTERNAL;
default:
break;
}
return ERROR;
}