Introduces jpeg-recovery source-code
[lcapit-junk-code.git] / DLW-1e / das / pass2.c
blob76af30406e41009389fa340732b6605875f4cce7
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
7 #include "pass2.h"
8 #include "file.h"
9 #include "opcode.h"
10 #include "symbol_tbl.h"
11 #include "error.h"
13 static char *get_opcode(char *line, unsigned long line_nr,
14 struct opcode **opcode)
16 char *endp, *p;
18 p = strchr(line, '\n');
19 if (p)
20 *p = '\0';
22 endp = strchr(line, '\0');
24 p = strchr(line, ' ');
25 if (p)
26 *p = '\0';
28 *opcode = opcode_lookup(line);
29 if (!*opcode) {
30 error(line_nr, "instruction '%s' is not known", line);
31 return NULL;
34 p = strchr(line, '\0');
36 if (p == endp && ((*opcode)->nr_operands > 0)) {
37 error(line_nr, "instruction requires operands");
38 return NULL;
41 return ++p;
44 static char *eat_immediate(oper_t *op_value, char *line, int line_nr)
46 int i;
47 long ret;
48 char c, *p;
50 for (i = 0; isdigit(line[i]); i++)
51 /* NOTHING */ ;
53 if (i == 0) {
54 error(line_nr, "no immediate in line");
55 return NULL;
58 p = get_line_end(&line[i], strlen(&line[i]), line_nr);
60 c = *p;
61 *p = '\0';
63 ret = strtol(line, NULL, 10);
64 if (ret > 255) {
65 error(line_nr, "immediate value overflow");
66 return NULL;
68 if (ret < 0) {
69 error(line_nr, "negative immediate value not suported yet");
70 return NULL;
73 *p = c;
75 *op_value = (oper_t) ret;
77 return p;
80 static char *eat_register(oper_t *op_value, char *line, int line_nr)
82 size_t len;
84 len = strlen(line);
85 if (len < 2)
86 goto out_err;
88 if (line[0] != 'r')
89 goto out_err;
91 *op_value = (oper_t) strtol(&line[1], NULL, 10);
92 if (*op_value < 1 || *op_value > 4)
93 goto out_err;
95 *op_value -= 1;
96 return get_line_end(&line[2], len, line_nr);
98 out_err:
99 error(line_nr, "invalid register specified");
100 return NULL;
103 static char *eat_label(oper_t *op_value, char *line, int line_nr)
105 char c;
106 int ret, i;
108 for (i = 0; isalpha(line[i]) || isdigit(line[i]); i++)
109 /* NOTHING */ ;
111 c = line[i];
112 line[i] = '\0';
114 ret = symbol_tbl_lookup(line);
115 if (ret < 0) {
116 error(line_nr, "undefined symbol %s", line);
117 return NULL;
120 *op_value = (oper_t) ret;
121 line[i] = c;
123 return get_line_end(&line[i], strlen(&line[i]), line_nr);
126 static char *get_next_operand(char *line, struct operand *operand,
127 int line_nr)
129 char *p;
131 for (p = line; *p != '\0'; p++, line_nr++) {
132 switch (*p) {
133 case ASM_SPACE:
134 case ASM_OP_SEP:
135 break;
136 case ASM_COMMENT:
137 goto out;
138 case ASM_OP_IMM:
139 operand->type = OP_IMM;
140 p = eat_immediate(&operand->value, ++p, line_nr);
141 goto out;
142 case ASM_OP_REG:
143 operand->type = OP_REG;
144 p = eat_register(&operand->value, ++p, line_nr);
145 goto out;
146 default:
147 /* label */
148 operand->type = OP_IMM;
149 p = eat_label(&operand->value, p, line_nr);
150 goto out;
154 out:
155 return p;
158 static void encode_arit(const struct operand *operands, inst_t *instruction)
160 int type;
161 oper_t dest;
163 dest = operands[2].value;
164 set_reg(instruction, dest, OFF_DEST);
166 type = operands[0].type | operands[1].type;
167 if (type & OP_IMM) {
168 oper_t imm, src1;
170 if (operands[0].type == OP_IMM) {
171 imm = operands[0].value;
172 src1 = operands[1].value;
173 } else {
174 imm = operands[1].value;
175 src1 = operands[0].value;
178 set_reg(instruction, src1, OFF_SRC1);
179 set_reg(instruction, dest, OFF_IMM_DEST);
180 set_imm(instruction, imm);
181 } else {
182 oper_t reg;
184 reg = operands[0].value;
185 set_reg(instruction, reg, OFF_SRC1);
187 reg = operands[1].value;
188 set_reg(instruction, reg, OFF_SRC2);
192 static void encode_branch(const struct operand *operands,
193 inst_t *instruction)
195 oper_t dest;
197 dest = operands[0].value;
199 if (operands[0].type & OP_IMM)
200 set_imm(instruction, dest);
201 else
202 set_reg(instruction, dest, OFF_MEM_REG_SRC1);
205 static void encode_store_imm(const struct operand *operands,
206 inst_t *instruction)
208 oper_t imm, src;
210 src = operands[0].value;
211 set_reg(instruction, src, OFF_SRC1);
213 imm = operands[1].value;
214 set_imm(instruction, imm);
217 static int inst_is_store(inst_t instruction)
219 const int store = 0x3000;
221 return instruction == store;
224 static int operands_has_imm(const struct operand *operands)
226 int i;
228 for (i = 0; i < OP_MAX; i++)
229 if (operands[i].type == OP_IMM)
230 return 1;
231 return 0;
234 static void encode_mem(const struct operand *operands,
235 inst_t *instruction)
237 oper_t src1, dest;
239 /* Fix this hack... */
240 if (inst_is_store(*instruction) &&
241 operands_has_imm(operands)) {
242 encode_store_imm(operands, instruction);
243 return;
246 src1 = operands[0].value;
247 dest = operands[1].value;
249 if (operands[0].type & OP_IMM) {
250 set_imm(instruction, src1);
251 set_reg(instruction, dest, OFF_MEM_IMM_DEST);
252 } else {
253 set_reg(instruction, src1, OFF_MEM_REG_SRC1);
254 set_reg(instruction, dest, OFF_MEM_REG_DEST);
258 static void encode_comp(const struct operand *operands,
259 inst_t *instruction)
261 oper_t src1, src2;
263 src1 = operands[0].value;
265 src2 = operands[1].value;
266 set_reg(instruction, src2, OFF_SRC2);
268 if (operands[0].type & OP_IMM)
269 set_imm(instruction, src1);
270 else
271 set_reg(instruction, src1, OFF_SRC1);
274 static void encode_inst(const struct opcode *opcode, inst_t *instruction)
276 *instruction = (inst_t) opcode->opcode << OFF_INST;
279 static int check_operands(const struct opcode *opcode,
280 const struct operand *operands,
281 int operand_nr, int line_nr)
283 int i;
285 if (operand_nr > opcode->nr_operands) {
286 error(line_nr, "instruction only supports %d operands",
287 opcode->nr_operands);
288 return 1;
291 for (i = 0; i < opcode->nr_operands; i++) {
292 if (opcode->operands[i].type == OP_INV &&
293 operands[i].type != OP_INV) {
294 error(line_nr, "instruction only accepts %d operands",
295 opcode->nr_operands);
296 return 1;
299 if (operands[i].type == OP_INV &&
300 opcode->operands[i].type != OP_INV) {
301 error(line_nr, "operand %d is missing", i + 1);
302 return 1;
305 if ((opcode->operands[i].type != OP_INV) &&
306 !(opcode->operands[i].type & operands[i].type)) {
307 error(line_nr, "wrong type for operand %d", i + 1);
308 return 1;
312 return 0;
315 static int assembly(const struct opcode *opcode,
316 const struct operand *operands,
317 int operand_nr, inst_t *instruction, int line_nr)
319 int err;
321 err = check_operands(opcode, operands, operand_nr, line_nr);
322 if (err)
323 return -1;
325 encode_inst(opcode, instruction);
327 switch (opcode->type) {
328 case INST_ARIT:
329 encode_arit(operands, instruction);
330 break;
331 case INST_MEM:
332 encode_mem(operands, instruction);
333 break;
334 case INST_BRAN:
335 encode_branch(operands, instruction);
336 break;
337 case INST_COMP:
338 encode_comp(operands, instruction);
339 break;
340 case INST_NARG:
341 /* do nothing */
342 break;
345 return 0;
348 static int read_operands(char *line, int line_nr, int operand_nr,
349 struct operand *operands)
351 int i;
352 char *p;
354 // initialize
355 for (i = 0; i < OP_MAX; i++) {
356 operands[i].value = 0;
357 operands[i].type = OP_INV;
360 p = line;
362 /* read operands */
363 for (i = 0; i < operand_nr; i++) {
364 p = get_next_operand(p, &operands[i], line_nr);
365 if (!p)
366 return -1;
368 if (*p == '\0' || *p == ASM_COMMENT)
369 break;
372 // number of operands doesn't start at 0
373 if (i)
374 ++i;
376 return i;
380 * das_pass2()
382 * Perform assembler second pass
384 * o assembly instructions
385 * o report errors
387 * interfp: intermediate FILE pointer (input)
388 * binfp: binary FILE pointer (output)
389 * debug: debug mode
391 int das_pass2(FILE *interfp, FILE *binfp, int debug)
393 inst_t instruction;
394 int line_nr, err, ret;
395 struct opcode *opcode;
396 char line[DEF_LINE_LEN], *p;
397 struct operand operands[OP_MAX];
399 err = 0;
401 for (line_nr = 1; ; line_nr++) {
402 ret = file_read_line(interfp, line, DEF_LINE_LEN);
403 if (ret == 1)
404 break;
406 if (is_comment(*line) || is_newline(*line))
407 continue;
409 remove_comment(line, strlen(line));
411 p = get_opcode(line, line_nr, &opcode);
412 if (!p) {
413 err = 1;
414 continue;
417 ret = read_operands(p, line_nr, opcode->nr_operands, operands);
418 if (ret < 0) {
419 err = 1;
420 continue;
423 ret = assembly(opcode, operands, ret, &instruction, line_nr);
424 if (ret) {
425 err = 1;
426 continue;
429 file_write_bin(&instruction, sizeof(instruction), binfp);
431 if (debug)
432 printf("%#x\n", instruction);
435 return err;