10 #include "symbol_tbl.h"
13 static char *get_opcode(char *line
, unsigned long line_nr
,
14 struct opcode
**opcode
)
18 p
= strchr(line
, '\n');
22 endp
= strchr(line
, '\0');
24 p
= strchr(line
, ' ');
28 *opcode
= opcode_lookup(line
);
30 error(line_nr
, "instruction '%s' is not known", line
);
34 p
= strchr(line
, '\0');
36 if (p
== endp
&& ((*opcode
)->nr_operands
> 0)) {
37 error(line_nr
, "instruction requires operands");
44 static char *eat_immediate(oper_t
*op_value
, char *line
, int line_nr
)
50 for (i
= 0; isdigit(line
[i
]); i
++)
54 error(line_nr
, "no immediate in line");
58 p
= get_line_end(&line
[i
], strlen(&line
[i
]), line_nr
);
63 ret
= strtol(line
, NULL
, 10);
65 error(line_nr
, "immediate value overflow");
69 error(line_nr
, "negative immediate value not suported yet");
75 *op_value
= (oper_t
) ret
;
80 static char *eat_register(oper_t
*op_value
, char *line
, int line_nr
)
91 *op_value
= (oper_t
) strtol(&line
[1], NULL
, 10);
92 if (*op_value
< 1 || *op_value
> 4)
96 return get_line_end(&line
[2], len
, line_nr
);
99 error(line_nr
, "invalid register specified");
103 static char *eat_label(oper_t
*op_value
, char *line
, int line_nr
)
108 for (i
= 0; isalpha(line
[i
]) || isdigit(line
[i
]); i
++)
114 ret
= symbol_tbl_lookup(line
);
116 error(line_nr
, "undefined symbol %s", line
);
120 *op_value
= (oper_t
) ret
;
123 return get_line_end(&line
[i
], strlen(&line
[i
]), line_nr
);
126 static char *get_next_operand(char *line
, struct operand
*operand
,
131 for (p
= line
; *p
!= '\0'; p
++, line_nr
++) {
139 operand
->type
= OP_IMM
;
140 p
= eat_immediate(&operand
->value
, ++p
, line_nr
);
143 operand
->type
= OP_REG
;
144 p
= eat_register(&operand
->value
, ++p
, line_nr
);
148 operand
->type
= OP_IMM
;
149 p
= eat_label(&operand
->value
, p
, line_nr
);
158 static void encode_arit(const struct operand
*operands
, inst_t
*instruction
)
163 dest
= operands
[2].value
;
164 set_reg(instruction
, dest
, OFF_DEST
);
166 type
= operands
[0].type
| operands
[1].type
;
170 if (operands
[0].type
== OP_IMM
) {
171 imm
= operands
[0].value
;
172 src1
= operands
[1].value
;
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
);
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
,
197 dest
= operands
[0].value
;
199 if (operands
[0].type
& OP_IMM
)
200 set_imm(instruction
, dest
);
202 set_reg(instruction
, dest
, OFF_MEM_REG_SRC1
);
205 static void encode_store_imm(const struct operand
*operands
,
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
)
228 for (i
= 0; i
< OP_MAX
; i
++)
229 if (operands
[i
].type
== OP_IMM
)
234 static void encode_mem(const struct operand
*operands
,
239 /* Fix this hack... */
240 if (inst_is_store(*instruction
) &&
241 operands_has_imm(operands
)) {
242 encode_store_imm(operands
, instruction
);
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
);
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
,
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
);
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
)
285 if (operand_nr
> opcode
->nr_operands
) {
286 error(line_nr
, "instruction only supports %d operands",
287 opcode
->nr_operands
);
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
);
299 if (operands
[i
].type
== OP_INV
&&
300 opcode
->operands
[i
].type
!= OP_INV
) {
301 error(line_nr
, "operand %d is missing", i
+ 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);
315 static int assembly(const struct opcode
*opcode
,
316 const struct operand
*operands
,
317 int operand_nr
, inst_t
*instruction
, int line_nr
)
321 err
= check_operands(opcode
, operands
, operand_nr
, line_nr
);
325 encode_inst(opcode
, instruction
);
327 switch (opcode
->type
) {
329 encode_arit(operands
, instruction
);
332 encode_mem(operands
, instruction
);
335 encode_branch(operands
, instruction
);
338 encode_comp(operands
, instruction
);
348 static int read_operands(char *line
, int line_nr
, int operand_nr
,
349 struct operand
*operands
)
355 for (i
= 0; i
< OP_MAX
; i
++) {
356 operands
[i
].value
= 0;
357 operands
[i
].type
= OP_INV
;
363 for (i
= 0; i
< operand_nr
; i
++) {
364 p
= get_next_operand(p
, &operands
[i
], line_nr
);
368 if (*p
== '\0' || *p
== ASM_COMMENT
)
372 // number of operands doesn't start at 0
382 * Perform assembler second pass
384 * o assembly instructions
387 * interfp: intermediate FILE pointer (input)
388 * binfp: binary FILE pointer (output)
391 int das_pass2(FILE *interfp
, FILE *binfp
, int debug
)
394 int line_nr
, err
, ret
;
395 struct opcode
*opcode
;
396 char line
[DEF_LINE_LEN
], *p
;
397 struct operand operands
[OP_MAX
];
401 for (line_nr
= 1; ; line_nr
++) {
402 ret
= file_read_line(interfp
, line
, DEF_LINE_LEN
);
406 if (is_comment(*line
) || is_newline(*line
))
409 remove_comment(line
, strlen(line
));
411 p
= get_opcode(line
, line_nr
, &opcode
);
417 ret
= read_operands(p
, line_nr
, opcode
->nr_operands
, operands
);
423 ret
= assembly(opcode
, operands
, ret
, &instruction
, line_nr
);
429 file_write_bin(&instruction
, sizeof(instruction
), binfp
);
432 printf("%#x\n", instruction
);