]>
Commit | Line | Data |
---|---|---|
a39116f1 | 1 | /* tc-h8300.c -- Assemble code for the Hitachi H8/300 |
cd8761e1 | 2 | Copyright (C) 1991 Free Software Foundation. |
a39116f1 RP |
3 | |
4 | This file is part of GAS, the GNU Assembler. | |
5 | ||
6 | GAS is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GAS is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GAS; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
f5e8a8f9 SC |
19 | |
20 | ||
cd8761e1 SC |
21 | /* |
22 | Written By Steve Chamberlain | |
5d9f0ecf | 23 | sac@cygnus.com |
a39116f1 | 24 | */ |
cd8761e1 SC |
25 | |
26 | #include <stdio.h> | |
27 | #include "as.h" | |
28 | #include "bfd.h" | |
5d9f0ecf | 29 | #include "opcode/h8300.h" |
cd8761e1 | 30 | #include <ctype.h> |
5d9f0ecf | 31 | #include "listing.h" |
cd8761e1 SC |
32 | |
33 | char comment_chars[] = { ';',0 }; | |
17b81479 | 34 | char line_separator_chars[] = { '$' ,0}; |
cd8761e1 SC |
35 | |
36 | /* This table describes all the machine specific pseudo-ops the assembler | |
37 | has to support. The fields are: | |
5d9f0ecf SC |
38 | pseudo-op name without dot |
39 | function to call to execute this pseudo-op | |
40 | Integer arg to pass to the function | |
a39116f1 | 41 | */ |
17b81479 SC |
42 | |
43 | void cons(); | |
5d9f0ecf | 44 | |
cd8761e1 | 45 | const pseudo_typeS md_pseudo_table[] = { |
a39116f1 RP |
46 | { "int", cons, 2 }, |
47 | { 0,0,0 } | |
cd8761e1 SC |
48 | }; |
49 | ||
50 | int md_reloc_size ; | |
a39116f1 | 51 | |
cd8761e1 SC |
52 | const char EXP_CHARS[] = "eE"; |
53 | ||
54 | /* Chars that mean this number is a floating point constant */ | |
55 | /* As in 0f12.456 */ | |
56 | /* or 0d1.2345e12 */ | |
a39116f1 | 57 | char FLT_CHARS[] = "rRsSfFdDxXpP"; |
cd8761e1 SC |
58 | |
59 | ||
60 | const relax_typeS md_relax_table[1]; | |
61 | ||
62 | ||
63 | static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ | |
cd8761e1 SC |
64 | |
65 | ||
66 | /* | |
a39116f1 RP |
67 | This function is called once, at assembler startup time. This should |
68 | set up all the tables, etc that the MD part of the assembler needs | |
69 | */ | |
70 | #if 0 | |
5d9f0ecf SC |
71 | /* encode the size and number into the number field |
72 | xxnnnn | |
73 | 00 8 bit | |
74 | 01 16 bit | |
75 | 10 ccr | |
a39116f1 RP |
76 | nnnnreg number |
77 | */ | |
5d9f0ecf SC |
78 | #define WORD_REG 0x10 |
79 | #define BYTE_REG 0x00 | |
80 | #define CCR_REG 0x20 | |
a39116f1 | 81 | struct reg_entry |
5d9f0ecf | 82 | { |
a39116f1 RP |
83 | char *name; |
84 | char number; | |
5d9f0ecf SC |
85 | }; |
86 | ||
87 | struct reg_entry reg_list[] = { | |
a39116f1 RP |
88 | "r0",WORD_REG +0, |
89 | "r1",WORD_REG +1, | |
90 | "r2",WORD_REG +2, | |
91 | "r3",WORD_REG +3, | |
92 | "r4",WORD_REG +4, | |
93 | "r5",WORD_REG +5, | |
94 | "r6",WORD_REG +6, | |
95 | "r7",WORD_REG +7, | |
96 | "fp",WORD_REG +6, | |
97 | "sp",WORD_REG +7, | |
98 | "r0h",BYTE_REG + 0, | |
99 | "r0l",BYTE_REG + 1, | |
100 | "r1h",BYTE_REG + 2, | |
101 | "r1l",BYTE_REG + 3, | |
102 | "r2h",BYTE_REG + 4, | |
103 | "r2l",BYTE_REG + 5, | |
104 | "r3h",BYTE_REG + 6, | |
105 | "r3l",BYTE_REG + 7, | |
106 | "r4h",BYTE_REG + 8, | |
107 | "r4l",BYTE_REG + 9, | |
108 | "r5h",BYTE_REG + 10, | |
109 | "r5l",BYTE_REG + 11, | |
110 | "r6h",BYTE_REG + 12, | |
111 | "r6l",BYTE_REG + 13, | |
112 | "r7h",BYTE_REG + 14, | |
113 | "r7l",BYTE_REG + 15, | |
114 | "ccr",CCR_REG, | |
115 | 0,0 | |
116 | } | |
5d9f0ecf SC |
117 | ; |
118 | ||
119 | ||
a39116f1 | 120 | #endif |
5d9f0ecf | 121 | |
cd8761e1 SC |
122 | |
123 | void md_begin () | |
124 | { | |
a39116f1 RP |
125 | struct h8_opcode *opcode; |
126 | const struct reg_entry *reg; | |
127 | char prev_buffer[100]; | |
128 | int idx = 0; | |
129 | ||
130 | opcode_hash_control = hash_new(); | |
131 | prev_buffer[0] = 0; | |
132 | ||
133 | for (opcode = h8_opcodes; opcode->name; opcode++) | |
134 | { | |
135 | /* Strip off any . part when inserting the opcode and only enter | |
136 | unique codes into the hash table | |
137 | */ | |
138 | char *src= opcode->name; | |
139 | unsigned int len = strlen(src); | |
140 | char *dst = malloc(len+1); | |
141 | char *buffer = dst; | |
142 | opcode->size = 0; | |
143 | while (*src) { | |
144 | if (*src == '.') { | |
145 | *dst++ = 0; | |
146 | src++; | |
147 | opcode->size = *src; | |
148 | break; | |
149 | } | |
150 | *dst++ = *src++; | |
151 | } | |
152 | if (strcmp(buffer, prev_buffer)) | |
153 | { | |
154 | hash_insert(opcode_hash_control, buffer, (char *)opcode); | |
155 | strcpy(prev_buffer, buffer); | |
156 | idx++; | |
157 | } | |
158 | opcode->idx = idx; | |
159 | ||
160 | ||
161 | /* Find the number of operands */ | |
162 | opcode->noperands = 0; | |
163 | while (opcode->args.nib[opcode->noperands] != E) | |
164 | opcode->noperands ++; | |
165 | /* Find the length of the opcode in bytes */ | |
166 | opcode->length =0; | |
167 | while (opcode->data.nib[opcode->length*2] != E) | |
168 | opcode->length++; | |
169 | } | |
170 | ||
cd8761e1 SC |
171 | } |
172 | ||
173 | ||
174 | struct h8_exp { | |
a39116f1 RP |
175 | char *e_beg; |
176 | char *e_end; | |
177 | expressionS e_exp; | |
cd8761e1 SC |
178 | }; |
179 | struct h8_op | |
180 | { | |
a39116f1 RP |
181 | unsigned int dispreg; |
182 | op_type mode; | |
183 | unsigned reg; | |
184 | expressionS exp; | |
cd8761e1 SC |
185 | }; |
186 | ||
187 | ||
188 | ||
189 | /* | |
a39116f1 RP |
190 | parse operands |
191 | WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp | |
192 | r0l,r0h,..r7l,r7h | |
193 | @WREG | |
194 | @WREG+ | |
195 | @-WREG | |
196 | #const | |
197 | ||
198 | */ | |
cd8761e1 | 199 | |
05b4b0e7 SC |
200 | op_type r8_sord[] = {RS8, RD8}; |
201 | op_type r16_sord[] = {RS16, RD16}; | |
202 | op_type rind_sord[] = {RSIND, RDIND}; | |
203 | op_type abs_sord[2] = {ABS16SRC, ABS16DST}; | |
204 | op_type disp_sord[] = {DISPSRC, DISPDST}; | |
5d9f0ecf | 205 | |
cd8761e1 | 206 | /* try and parse a reg name, returns number of chars consumed */ |
5d9f0ecf | 207 | int |
a39116f1 RP |
208 | DEFUN(parse_reg,(src, mode, reg, dst), |
209 | char *src AND | |
210 | op_type *mode AND | |
211 | unsigned int *reg AND | |
212 | int dst) | |
cd8761e1 | 213 | { |
a39116f1 | 214 | if (src[0] == 's' && src[1] == 'p') |
5d9f0ecf | 215 | { |
a39116f1 RP |
216 | *mode = r16_sord[dst]; |
217 | *reg = 7; | |
218 | return 2; | |
5d9f0ecf | 219 | } |
a39116f1 | 220 | if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') |
5d9f0ecf | 221 | { |
a39116f1 RP |
222 | *mode = CCR; |
223 | *reg = 0; | |
224 | return 3; | |
5d9f0ecf | 225 | } |
a39116f1 RP |
226 | if (src[0] == 'f' && src[1] == 'p') |
227 | { | |
228 | *mode = r16_sord[dst]; | |
229 | *reg = 6; | |
230 | return 2; | |
231 | } | |
232 | if (src[0] == 'r') | |
233 | { | |
234 | if (src[1] >= '0' && src[1] <= '7') | |
235 | { | |
236 | if(src[2] == 'l') | |
237 | { | |
238 | *mode = r8_sord[dst]; | |
239 | *reg = (src[1] - '0') + 8; | |
240 | return 3; | |
241 | } | |
242 | if(src[2] == 'h') | |
243 | { | |
244 | *mode = r8_sord[dst]; | |
245 | *reg = (src[1] - '0') ; | |
246 | return 3; | |
247 | } | |
248 | *mode = r16_sord[dst]; | |
249 | *reg = (src[1] - '0'); | |
250 | return 2; | |
251 | } | |
252 | } | |
253 | return 0; | |
cd8761e1 SC |
254 | } |
255 | ||
256 | char * | |
a39116f1 RP |
257 | DEFUN(parse_exp,(s, op), |
258 | char *s AND | |
259 | expressionS *op) | |
cd8761e1 | 260 | { |
a39116f1 RP |
261 | char *save = input_line_pointer; |
262 | char *new; | |
263 | segT seg; | |
264 | input_line_pointer = s; | |
265 | seg = expr(0,op); | |
266 | new = input_line_pointer; | |
267 | input_line_pointer = save; | |
268 | if (SEG_NORMAL(seg)) | |
269 | return new; | |
270 | switch (seg) { | |
271 | case SEG_ABSOLUTE: | |
272 | case SEG_UNKNOWN: | |
273 | case SEG_DIFFERENCE: | |
274 | case SEG_BIG: | |
275 | case SEG_REGISTER: | |
276 | return new; | |
277 | case SEG_ABSENT: | |
278 | as_bad("Missing operand"); | |
279 | return new; | |
280 | default: | |
281 | as_bad("Don't understand operand of type %s", segment_name (seg)); | |
282 | return new; | |
283 | } | |
5d9f0ecf SC |
284 | } |
285 | ||
286 | static char * | |
a39116f1 RP |
287 | DEFUN(skip_colonthing,(ptr), |
288 | char *ptr) | |
5d9f0ecf | 289 | { |
a39116f1 RP |
290 | if (*ptr == ':') { |
291 | ptr++; | |
292 | while (isdigit(*ptr)) | |
293 | ptr++; | |
294 | ||
5d9f0ecf | 295 | } |
a39116f1 | 296 | return ptr; |
cd8761e1 SC |
297 | } |
298 | ||
5d9f0ecf SC |
299 | /* The many forms of operand: |
300 | ||
a39116f1 RP |
301 | Rn Register direct |
302 | @Rn Register indirect | |
303 | @(exp[:16], Rn) Register indirect with displacement | |
304 | @Rn+ | |
305 | @-Rn | |
306 | @aa:8 absolute 8 bit | |
307 | @aa:16 absolute 16 bit | |
308 | @aa absolute 16 bit | |
309 | ||
310 | #xx[:size] immediate data | |
311 | @(exp:[8], pc) pc rel | |
312 | @@aa[:8] memory indirect | |
313 | ||
314 | */ | |
cd8761e1 SC |
315 | |
316 | static void | |
a39116f1 RP |
317 | DEFUN(get_operand,(ptr, op, dst), |
318 | char **ptr AND | |
319 | struct h8_op *op AND | |
320 | unsigned int dst) | |
cd8761e1 | 321 | { |
a39116f1 RP |
322 | char *src = *ptr; |
323 | op_type mode; | |
324 | unsigned int num; | |
325 | unsigned int len; | |
326 | unsigned int size; | |
327 | op->mode = E; | |
5d9f0ecf | 328 | |
a39116f1 RP |
329 | len = parse_reg(src, &op->mode, &op->reg, dst); |
330 | if (len) { | |
331 | *ptr = src + len; | |
332 | return ; | |
5d9f0ecf | 333 | } |
a39116f1 RP |
334 | |
335 | if (*src == '@') | |
336 | { | |
337 | src++; | |
338 | if (*src == '@') | |
339 | { | |
340 | src++; | |
341 | src = parse_exp(src,&op->exp); | |
342 | src = skip_colonthing(src); | |
343 | ||
344 | *ptr = src; | |
345 | ||
346 | op->mode = MEMIND; | |
347 | return; | |
348 | ||
349 | } | |
350 | ||
351 | ||
352 | if (*src == '-') | |
353 | { | |
354 | src++; | |
355 | len = parse_reg(src, &mode, &num, dst); | |
356 | if (len == 0) | |
357 | { | |
358 | /* Oops, not a reg after all, must be ordinary exp */ | |
359 | src--; | |
360 | /* must be a symbol */ | |
361 | op->mode = abs_sord[dst]; | |
362 | *ptr = skip_colonthing(parse_exp(src, &op->exp)); | |
363 | ||
364 | return; | |
365 | ||
366 | ||
367 | } | |
368 | ||
369 | if (mode != r16_sord[dst]) | |
370 | { | |
371 | as_bad("@- needs word register"); | |
372 | } | |
373 | op->mode = RDDEC; | |
374 | op->reg = num; | |
375 | *ptr = src + len; | |
376 | return; | |
377 | } | |
378 | if (*src == '(' && ')') | |
379 | { | |
380 | /* Disp */ | |
381 | src++; | |
382 | src = parse_exp(src, &op->exp); | |
383 | ||
384 | if (*src == ')') | |
385 | { | |
386 | src++; | |
387 | op->mode = abs_sord[dst]; | |
388 | *ptr = src; | |
389 | return; | |
390 | } | |
391 | src = skip_colonthing(src); | |
392 | ||
393 | if (*src != ',') | |
394 | { | |
395 | as_bad("expected @(exp, reg16)"); | |
396 | } | |
397 | src++; | |
398 | len = parse_reg(src, &mode, &op->reg, dst); | |
399 | if (len == 0 || mode != r16_sord[dst]) | |
400 | { | |
401 | as_bad("expected @(exp, reg16)"); | |
402 | } | |
403 | op->mode = disp_sord[dst]; | |
404 | src += len; | |
405 | src = skip_colonthing(src); | |
406 | ||
407 | if (*src != ')' && '(') | |
408 | { | |
409 | as_bad("expected @(exp, reg16)"); | |
410 | ||
411 | } | |
412 | *ptr = src +1; | |
413 | ||
414 | return; | |
415 | } | |
416 | len = parse_reg(src, &mode, &num, dst); | |
417 | ||
418 | if(len) { | |
419 | src += len; | |
420 | if (*src == '+') | |
421 | { | |
422 | src++; | |
423 | if (mode != RS16) | |
424 | { | |
425 | as_bad("@Rn+ needs src word register"); | |
426 | } | |
427 | op->mode = RSINC; | |
428 | op->reg = num; | |
429 | *ptr = src; | |
430 | return; | |
431 | } | |
432 | if (mode != r16_sord[dst]) | |
433 | { | |
434 | as_bad("@Rn needs word register"); | |
435 | } | |
436 | op->mode =rind_sord[dst]; | |
437 | op->reg = num; | |
438 | *ptr = src; | |
439 | return; | |
440 | } | |
441 | else | |
442 | { | |
443 | /* must be a symbol */ | |
444 | op->mode = abs_sord[dst]; | |
445 | *ptr = skip_colonthing(parse_exp(src, &op->exp)); | |
446 | ||
447 | return; | |
448 | } | |
449 | } | |
450 | ||
451 | ||
452 | if (*src == '#') { | |
453 | src++; | |
454 | op->mode = IMM16; | |
455 | src = parse_exp(src, &op->exp); | |
456 | *ptr= skip_colonthing(src); | |
457 | ||
458 | return; | |
459 | } | |
460 | else { | |
461 | *ptr = parse_exp(src, &op->exp); | |
462 | op->mode = DISP8; | |
cd8761e1 | 463 | } |
5d9f0ecf SC |
464 | } |
465 | ||
466 | ||
467 | static | |
a39116f1 RP |
468 | char * |
469 | DEFUN(get_operands,(noperands,op_end, operand), | |
470 | unsigned int noperands AND | |
471 | char *op_end AND | |
472 | struct h8_op *operand) | |
5d9f0ecf | 473 | { |
a39116f1 RP |
474 | char *ptr = op_end; |
475 | switch (noperands) | |
476 | { | |
477 | case 0: | |
478 | operand[0].mode = 0; | |
479 | operand[1].mode = 0; | |
480 | break; | |
481 | ||
482 | case 1: | |
483 | ptr++; | |
484 | get_operand(& ptr, operand +0,0); | |
485 | operand[1].mode =0; | |
486 | break; | |
487 | ||
488 | case 2: | |
489 | ptr++; | |
490 | get_operand(& ptr, operand +0,0); | |
491 | if (*ptr == ',') ptr++; | |
492 | get_operand(& ptr, operand +1, 1); | |
493 | break; | |
494 | ||
495 | default: | |
496 | abort(); | |
497 | } | |
498 | ||
499 | ||
500 | return ptr; | |
cd8761e1 SC |
501 | } |
502 | ||
5d9f0ecf SC |
503 | /* Passed a pointer to a list of opcodes which use different |
504 | addressing modes, return the opcode which matches the opcodes | |
505 | provided | |
a39116f1 | 506 | */ |
5d9f0ecf | 507 | static |
a39116f1 RP |
508 | struct h8_opcode * |
509 | DEFUN(get_specific,(opcode, operands), | |
510 | struct h8_opcode *opcode AND | |
511 | struct h8_op *operands) | |
5d9f0ecf SC |
512 | |
513 | { | |
a39116f1 RP |
514 | struct h8_opcode *this_try = opcode ; |
515 | int found = 0; | |
516 | unsigned int noperands = opcode->noperands; | |
517 | ||
518 | unsigned int dispreg; | |
519 | unsigned int this_index = opcode->idx; | |
520 | while (this_index == opcode->idx && !found) | |
521 | { | |
522 | unsigned int i; | |
523 | ||
524 | this_try = opcode ++; | |
525 | for (i = 0; i < noperands; i++) | |
526 | { | |
527 | op_type op = (this_try->args.nib[i]) & ~(B30|B31); | |
528 | switch (op) | |
529 | { | |
530 | case Hex0: | |
531 | case Hex1: | |
532 | case Hex2: | |
533 | case Hex3: | |
534 | case Hex4: | |
535 | case Hex5: | |
536 | case Hex6: | |
537 | case Hex7: | |
538 | case Hex8: | |
539 | case Hex9: | |
540 | case HexA: | |
541 | case HexB: | |
542 | case HexC: | |
543 | case HexD: | |
544 | case HexE: | |
545 | case HexF: | |
546 | break; | |
547 | case DISPSRC: | |
548 | case DISPDST: | |
549 | operands[0].dispreg = operands[i].reg; | |
550 | case RD8: | |
551 | case RS8: | |
552 | case RDIND: | |
553 | case RSIND: | |
554 | case RD16: | |
555 | case RS16: | |
556 | case CCR: | |
557 | case RSINC: | |
558 | case RDDEC: | |
559 | if (operands[i].mode != op) goto fail; | |
560 | break; | |
561 | case KBIT: | |
562 | case IMM16: | |
563 | case IMM3: | |
564 | case IMM8: | |
565 | if (operands[i].mode != IMM16) goto fail; | |
566 | break; | |
567 | case MEMIND: | |
568 | if (operands[i].mode != MEMIND) goto fail; | |
569 | break; | |
570 | case ABS16SRC: | |
571 | case ABS8SRC: | |
572 | case ABS16OR8SRC: | |
573 | case ABS16ORREL8SRC: | |
574 | ||
575 | if (operands[i].mode != ABS16SRC) goto fail; | |
576 | break; | |
577 | case ABS16OR8DST: | |
578 | case ABS16DST: | |
579 | case ABS8DST: | |
580 | if (operands[i].mode != ABS16DST) goto fail; | |
581 | break; | |
582 | } | |
583 | } | |
584 | found =1; | |
585 | fail: ; | |
586 | } | |
587 | if (found) | |
588 | return this_try; | |
589 | else | |
590 | return 0; | |
5d9f0ecf SC |
591 | } |
592 | ||
593 | static void | |
a39116f1 RP |
594 | DEFUN(check_operand,(operand, width, string), |
595 | struct h8_op *operand AND | |
596 | unsigned int width AND | |
597 | char *string) | |
5d9f0ecf | 598 | { |
a39116f1 RP |
599 | if (operand->exp.X_add_symbol == 0 |
600 | && operand->exp.X_subtract_symbol == 0) | |
601 | { | |
602 | ||
603 | /* No symbol involved, let's look at offset, it's dangerous if any of | |
604 | the high bits are not 0 or ff's, find out by oring or anding with | |
605 | the width and seeing if the answer is 0 or all fs*/ | |
606 | if ((operand->exp.X_add_number | width) != ~0 && | |
607 | (operand->exp.X_add_number & ~width)!= 0) | |
608 | { | |
609 | as_warn("operand %s0x%x out of range.", string, operand->exp.X_add_number); | |
610 | } | |
611 | } | |
612 | ||
5d9f0ecf SC |
613 | } |
614 | ||
615 | /* Now we know what sort of opcodes it is, lets build the bytes - | |
a39116f1 | 616 | */ |
5d9f0ecf | 617 | static void |
a39116f1 RP |
618 | DEFUN (build_bytes,(this_try, operand), |
619 | struct h8_opcode *this_try AND | |
620 | struct h8_op *operand) | |
5d9f0ecf SC |
621 | |
622 | { | |
a39116f1 RP |
623 | unsigned int i; |
624 | ||
625 | char *output = frag_more(this_try->length); | |
626 | char *output_ptr = output; | |
627 | op_type *nibble_ptr = this_try->data.nib; | |
628 | char part; | |
629 | op_type c; | |
630 | char high; | |
631 | int nib; | |
5d9f0ecf | 632 | top: ; |
a39116f1 RP |
633 | while (*nibble_ptr != E) |
634 | { | |
635 | int nibble; | |
636 | for (nibble = 0; nibble <2; nibble++) | |
637 | { | |
638 | c = *nibble_ptr & ~(B30|B31); | |
639 | switch (c) | |
640 | { | |
641 | default: | |
642 | abort(); | |
643 | case KBIT: | |
644 | switch (operand[0].exp.X_add_number) | |
645 | { | |
646 | case 1: | |
647 | nib = 0; | |
648 | break; | |
649 | case 2: | |
650 | nib = 8; | |
651 | break; | |
652 | default: | |
653 | as_bad("Need #1 or #2 here"); | |
654 | break; | |
655 | } | |
656 | /* stop it making a fix */ | |
657 | operand[0].mode = 0; | |
658 | break; | |
659 | case 0: | |
660 | case 1: | |
661 | case 2: case 3: case 4: case 5: case 6: | |
662 | case 7: case 8: case 9: case 10: case 11: | |
663 | case 12: case 13: case 14: case 15: | |
664 | nib = c; | |
665 | break; | |
666 | case DISPREG: | |
667 | nib = operand[0].dispreg; | |
668 | break; | |
669 | case IMM8: | |
670 | operand[0].mode = IMM8; | |
671 | nib = 0; | |
672 | break; | |
673 | ||
674 | case DISPDST: | |
675 | nib = 0; | |
676 | break; | |
677 | case IMM3: | |
678 | if (operand[0].exp.X_add_symbol == 0) { | |
679 | operand[0].mode = 0; /* stop it making a fix */ | |
680 | nib = (operand[0].exp.X_add_number); | |
681 | } | |
682 | else as_bad("can't have symbol for bit number"); | |
683 | if (nib < 0 || nib > 7) | |
684 | { | |
685 | as_bad("Bit number out of range %d", nib); | |
686 | } | |
687 | ||
688 | break; | |
689 | ||
690 | case ABS16DST: | |
691 | nib = 0; | |
692 | break; | |
693 | case ABS8DST: | |
694 | operand[1].mode = ABS8DST; | |
695 | nib = 0; | |
696 | break; | |
697 | case ABS8SRC: | |
698 | operand[0].mode = ABS8SRC; | |
699 | nib = 0; | |
700 | break; | |
701 | case ABS16OR8DST: | |
702 | operand[1].mode = c; | |
703 | ||
704 | nib = 0; | |
705 | ||
706 | break; | |
707 | ||
708 | case ABS16ORREL8SRC: | |
709 | operand[0].mode = c; | |
710 | nib=0; | |
711 | break; | |
712 | ||
713 | case ABS16OR8SRC: | |
714 | operand[0].mode = ABS16OR8SRC; | |
715 | nib = 0; | |
716 | break; | |
717 | case DISPSRC: | |
718 | operand[0].mode = ABS16SRC; | |
719 | nib = 0; | |
720 | break; | |
721 | ||
722 | case DISP8: | |
723 | operand[0].mode = DISP8; | |
724 | nib = 0; | |
725 | break; | |
726 | ||
727 | case ABS16SRC: | |
728 | case IMM16: | |
729 | case IGNORE: | |
730 | case MEMIND: | |
731 | ||
732 | nib=0; | |
733 | break; | |
734 | case RS8: | |
735 | case RS16: | |
736 | case RSIND: | |
737 | case RSINC: | |
738 | nib = operand[0].reg; | |
739 | break; | |
740 | ||
741 | case RD8: | |
742 | case RD16: | |
743 | case RDDEC: | |
744 | case RDIND: | |
745 | nib = operand[1].reg; | |
746 | break; | |
747 | ||
748 | case E: | |
749 | abort(); | |
750 | break; | |
751 | } | |
752 | if (*nibble_ptr & B31) { | |
753 | nib |=0x8; | |
754 | } | |
755 | ||
756 | if (nibble == 0) { | |
757 | *output_ptr = nib << 4; | |
758 | } | |
759 | else { | |
760 | *output_ptr |= nib; | |
761 | output_ptr++; | |
762 | } | |
763 | nibble_ptr++; | |
764 | } | |
765 | ||
766 | } | |
5d9f0ecf | 767 | |
a39116f1 RP |
768 | /* output any fixes */ |
769 | for (i = 0; i < 2; i++) | |
770 | { | |
771 | switch (operand[i].mode) { | |
772 | case 0: | |
773 | break; | |
774 | ||
775 | case DISP8: | |
776 | check_operand(operand+i, 0x7f,"@"); | |
777 | ||
778 | fix_new(frag_now, | |
779 | output - frag_now->fr_literal + 1, | |
780 | 1, | |
781 | operand[i].exp.X_add_symbol, | |
782 | operand[i].exp.X_subtract_symbol, | |
783 | operand[i].exp.X_add_number -1, | |
784 | 1, | |
785 | R_PCRBYTE); | |
786 | break; | |
787 | case IMM8: | |
788 | check_operand(operand+i, 0xff,"#"); | |
789 | /* If there is nothing else going on we can safely | |
790 | reloc in place */ | |
791 | if (operand[i].exp.X_add_symbol == 0) | |
792 | { | |
793 | output[1] = operand[i].exp.X_add_number; | |
794 | } | |
795 | else | |
796 | { | |
797 | fix_new(frag_now, | |
798 | output - frag_now->fr_literal + 1, | |
799 | 1, | |
800 | operand[i].exp.X_add_symbol, | |
801 | operand[i].exp.X_subtract_symbol, | |
802 | operand[i].exp.X_add_number, | |
803 | 0, | |
804 | R_RELBYTE); | |
805 | } | |
806 | ||
807 | break; | |
808 | case MEMIND: | |
809 | check_operand(operand+i, 0xff,"@@"); | |
810 | fix_new(frag_now, | |
811 | output - frag_now->fr_literal + 1, | |
812 | 1, | |
813 | operand[i].exp.X_add_symbol, | |
814 | operand[i].exp.X_subtract_symbol, | |
815 | operand[i].exp.X_add_number, | |
816 | 0, | |
817 | R_RELBYTE); | |
818 | break; | |
819 | case ABS8DST: | |
820 | case ABS8SRC: | |
821 | check_operand(operand+i, 0xff,"@"); | |
822 | fix_new(frag_now, | |
823 | output - frag_now->fr_literal + 1, | |
824 | 1, | |
825 | operand[i].exp.X_add_symbol, | |
826 | operand[i].exp.X_subtract_symbol, | |
827 | operand[i].exp.X_add_number, | |
828 | 0, | |
829 | R_RELBYTE); | |
830 | break; | |
831 | ||
832 | case ABS16OR8SRC: | |
833 | case ABS16OR8DST: | |
834 | check_operand(operand+i, 0xffff,"@"); | |
835 | ||
836 | fix_new(frag_now, | |
837 | output - frag_now->fr_literal + 2, | |
838 | 2, | |
839 | operand[i].exp.X_add_symbol, | |
840 | operand[i].exp.X_subtract_symbol, | |
841 | operand[i].exp.X_add_number, | |
842 | 0, | |
843 | R_MOVB1); | |
844 | break; | |
845 | ||
846 | case ABS16ORREL8SRC: | |
847 | check_operand(operand+i, 0xffff,"@"); | |
848 | ||
849 | fix_new(frag_now, | |
850 | output - frag_now->fr_literal + 2, | |
851 | 2, | |
852 | operand[i].exp.X_add_symbol, | |
853 | operand[i].exp.X_subtract_symbol, | |
854 | operand[i].exp.X_add_number, | |
855 | 0, | |
856 | R_JMP1); | |
857 | break; | |
858 | ||
859 | ||
860 | case ABS16SRC: | |
861 | case ABS16DST: | |
862 | case IMM16: | |
863 | case DISPSRC: | |
864 | case DISPDST: | |
865 | check_operand(operand+i, 0xffff,"@"); | |
866 | if (operand[i].exp.X_add_symbol == 0) | |
867 | { | |
868 | /* This should be done with bfd */ | |
869 | output[3] = operand[i].exp.X_add_number & 0xff; | |
870 | output[2] = operand[i].exp.X_add_number >> 8; | |
871 | ||
872 | } | |
873 | else | |
874 | { | |
875 | ||
876 | fix_new(frag_now, | |
877 | output - frag_now->fr_literal + 2, | |
878 | 2, | |
879 | operand[i].exp.X_add_symbol, | |
880 | operand[i].exp.X_subtract_symbol, | |
881 | operand[i].exp.X_add_number, | |
882 | 0, | |
883 | R_RELWORD); | |
884 | } | |
885 | ||
886 | break; | |
887 | case RS8: | |
888 | case RD8: | |
889 | case RS16: | |
890 | case RD16: | |
891 | case RDDEC: | |
892 | case KBIT: | |
893 | case RSINC: | |
894 | case RDIND: | |
895 | case RSIND: | |
896 | case CCR: | |
897 | ||
898 | break; | |
899 | default: | |
900 | abort(); | |
901 | } | |
902 | } | |
5d9f0ecf | 903 | |
a39116f1 RP |
904 | } |
905 | /* | |
906 | try and give an intelligent error message for common and simple to | |
907 | detect errors | |
908 | */ | |
5d9f0ecf | 909 | |
a39116f1 RP |
910 | static void |
911 | DEFUN(clever_message, (opcode, operand), | |
912 | struct h8_opcode *opcode AND | |
913 | struct h8_op *operand) | |
914 | { | |
915 | struct h8_opcode *scan = opcode; | |
916 | ||
917 | /* Find out if there was more than one possible opccode */ | |
918 | ||
919 | if ((opcode+1)->idx != opcode->idx) | |
920 | { | |
921 | unsigned int argn; | |
922 | ||
923 | /* Only one opcode of this flavour, try and guess which operand | |
924 | didn't match */ | |
925 | for (argn = 0; argn < opcode->noperands; argn++) | |
926 | { | |
927 | switch (opcode->args.nib[argn]) | |
928 | { | |
929 | case RD16: | |
930 | if (operand[argn].mode != RD16) | |
931 | { | |
932 | as_bad("destination operand must be 16 bit register"); | |
933 | } | |
934 | return; | |
935 | case RS8: | |
936 | ||
937 | if (operand[argn].mode != RS8) | |
938 | { | |
939 | as_bad("source operand must be 8 bit register"); | |
940 | } | |
941 | return; | |
942 | case ABS16DST: | |
943 | if (operand[argn].mode != ABS16DST) | |
944 | { | |
945 | as_bad("destination operand must be 16bit absolute address"); | |
946 | return; | |
947 | } | |
948 | ||
949 | case RD8: | |
950 | if (operand[argn].mode != RD8) | |
951 | { | |
952 | as_bad("destination operand must be 8 bit register"); | |
953 | } | |
954 | return; | |
955 | ||
956 | case ABS16SRC: | |
957 | if (operand[argn].mode != ABS16SRC) | |
958 | { | |
959 | as_bad("source operand must be 16bit absolute address"); | |
960 | return; | |
961 | } | |
962 | } | |
963 | } | |
964 | } | |
965 | as_bad("invalid operands"); | |
5d9f0ecf | 966 | } |
a39116f1 | 967 | |
cd8761e1 SC |
968 | /* This is the guts of the machine-dependent assembler. STR points to a |
969 | machine dependent instruction. This funciton is supposed to emit | |
970 | the frags/bytes it assembles to. | |
a39116f1 RP |
971 | */ |
972 | ||
973 | ||
cd8761e1 SC |
974 | |
975 | void | |
a39116f1 RP |
976 | DEFUN(md_assemble,(str), |
977 | char *str) | |
cd8761e1 | 978 | { |
a39116f1 RP |
979 | char *op_start; |
980 | char *op_end; | |
981 | unsigned int i; | |
982 | struct h8_op operand[2]; | |
983 | struct h8_opcode * opcode; | |
984 | struct h8_opcode * prev_opcode; | |
985 | ||
986 | char *dot = 0; | |
987 | char c; | |
988 | /* Drop leading whitespace */ | |
989 | while (*str == ' ') | |
990 | str++; | |
991 | ||
992 | /* find the op code end */ | |
993 | for (op_start = op_end = str; | |
994 | *op_end != 0 && *op_end != ' '; | |
995 | op_end ++) | |
996 | { | |
997 | if (*op_end == '.') { | |
998 | dot = op_end+1; | |
999 | *op_end = 0; | |
1000 | op_end+=2; | |
1001 | break; | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | ; | |
1006 | ||
1007 | if (op_end == op_start) | |
1008 | { | |
1009 | as_bad("can't find opcode "); | |
1010 | } | |
1011 | c = *op_end; | |
1012 | ||
5d9f0ecf | 1013 | *op_end = 0; |
a39116f1 RP |
1014 | |
1015 | opcode = (struct h8_opcode *) hash_find(opcode_hash_control, | |
1016 | op_start); | |
1017 | ||
1018 | if (opcode == NULL) | |
1019 | { | |
1020 | as_bad("unknown opcode"); | |
1021 | return; | |
1022 | } | |
1023 | ||
1024 | ||
1025 | input_line_pointer = get_operands(opcode->noperands, op_end, | |
1026 | operand); | |
1027 | *op_end = c; | |
1028 | prev_opcode = opcode; | |
1029 | ||
1030 | opcode = get_specific(opcode, operand); | |
1031 | ||
1032 | if (opcode == 0) | |
1033 | { | |
1034 | /* Couldn't find an opcode which matched the operands */ | |
1035 | char *where =frag_more(2); | |
1036 | where[0] = 0x0; | |
1037 | where[1] = 0x0; | |
1038 | clever_message(prev_opcode, operand); | |
1039 | ||
1040 | return; | |
1041 | } | |
1042 | if (opcode->size && dot) | |
1043 | { | |
1044 | if (opcode->size != *dot) | |
1045 | { | |
1046 | as_warn("mismatch between opcode size and operand size"); | |
1047 | } | |
1048 | } | |
1049 | ||
1050 | build_bytes(opcode, operand); | |
1051 | ||
cd8761e1 SC |
1052 | } |
1053 | ||
1054 | void | |
a39116f1 RP |
1055 | DEFUN(tc_crawl_symbol_chain, (headers), |
1056 | object_headers *headers) | |
cd8761e1 | 1057 | { |
a39116f1 | 1058 | printf("call to tc_crawl_symbol_chain \n"); |
cd8761e1 SC |
1059 | } |
1060 | ||
1061 | symbolS *DEFUN(md_undefined_symbol,(name), | |
1062 | char *name) | |
1063 | { | |
a39116f1 | 1064 | return 0; |
cd8761e1 SC |
1065 | } |
1066 | ||
1067 | void | |
a39116f1 RP |
1068 | DEFUN(tc_headers_hook,(headers), |
1069 | object_headers *headers) | |
cd8761e1 | 1070 | { |
a39116f1 | 1071 | printf("call to tc_headers_hook \n"); |
cd8761e1 SC |
1072 | } |
1073 | void | |
a39116f1 | 1074 | DEFUN_VOID(md_end) |
cd8761e1 SC |
1075 | { |
1076 | } | |
1077 | ||
1078 | /* Various routines to kill one day */ | |
05b4b0e7 SC |
1079 | /* Equal to MAX_PRECISION in atof-ieee.c */ |
1080 | #define MAX_LITTLENUMS 6 | |
1081 | ||
1082 | /* Turn a string in input_line_pointer into a floating point constant of type | |
1083 | type, and store the appropriate bytes in *litP. The number of LITTLENUMS | |
1084 | emitted is stored in *sizeP . An error message is returned, or NULL on OK. | |
a39116f1 | 1085 | */ |
05b4b0e7 | 1086 | char * |
a39116f1 | 1087 | md_atof(type,litP,sizeP) |
05b4b0e7 SC |
1088 | char type; |
1089 | char *litP; | |
1090 | int *sizeP; | |
1091 | { | |
1092 | int prec; | |
1093 | LITTLENUM_TYPE words[MAX_LITTLENUMS]; | |
1094 | LITTLENUM_TYPE *wordP; | |
1095 | char *t; | |
1096 | char *atof_ieee(); | |
a39116f1 | 1097 | |
05b4b0e7 SC |
1098 | switch(type) { |
1099 | case 'f': | |
1100 | case 'F': | |
1101 | case 's': | |
1102 | case 'S': | |
1103 | prec = 2; | |
1104 | break; | |
a39116f1 | 1105 | |
05b4b0e7 SC |
1106 | case 'd': |
1107 | case 'D': | |
1108 | case 'r': | |
1109 | case 'R': | |
1110 | prec = 4; | |
1111 | break; | |
a39116f1 | 1112 | |
05b4b0e7 SC |
1113 | case 'x': |
1114 | case 'X': | |
1115 | prec = 6; | |
1116 | break; | |
a39116f1 | 1117 | |
05b4b0e7 SC |
1118 | case 'p': |
1119 | case 'P': | |
1120 | prec = 6; | |
1121 | break; | |
a39116f1 | 1122 | |
05b4b0e7 SC |
1123 | default: |
1124 | *sizeP=0; | |
1125 | return "Bad call to MD_ATOF()"; | |
1126 | } | |
1127 | t=atof_ieee(input_line_pointer,type,words); | |
1128 | if(t) | |
a39116f1 RP |
1129 | input_line_pointer=t; |
1130 | ||
05b4b0e7 SC |
1131 | *sizeP=prec * sizeof(LITTLENUM_TYPE); |
1132 | for(wordP=words;prec--;) { | |
1133 | md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); | |
1134 | litP+=sizeof(LITTLENUM_TYPE); | |
1135 | } | |
1136 | return ""; /* Someone should teach Dean about null pointers */ | |
1137 | } | |
1138 | ||
1139 | int | |
a39116f1 RP |
1140 | md_parse_option(argP, cntP, vecP) |
1141 | char **argP; | |
1142 | int *cntP; | |
1143 | char ***vecP; | |
05b4b0e7 | 1144 | |
a39116f1 RP |
1145 | { |
1146 | return 0; | |
1147 | ||
1148 | } | |
cd8761e1 SC |
1149 | |
1150 | int md_short_jump_size; | |
1151 | ||
1152 | void tc_aout_fix_to_chars () { printf("call to tc_aout_fix_to_chars \n"); | |
a39116f1 | 1153 | abort(); } |
05b4b0e7 SC |
1154 | void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) |
1155 | char *ptr; | |
1156 | long from_addr; | |
1157 | long to_addr; | |
1158 | fragS *frag; | |
1159 | symbolS *to_symbol; | |
1160 | { | |
1161 | as_fatal("failed sanity check."); | |
a39116f1 | 1162 | } |
05b4b0e7 SC |
1163 | |
1164 | void | |
a39116f1 RP |
1165 | md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol) |
1166 | char *ptr; | |
1167 | long from_addr, to_addr; | |
1168 | fragS *frag; | |
1169 | symbolS *to_symbol; | |
05b4b0e7 SC |
1170 | { |
1171 | as_fatal("failed sanity check."); | |
1172 | } | |
1173 | ||
1174 | void | |
a39116f1 | 1175 | md_convert_frag(headers, fragP) |
05b4b0e7 | 1176 | object_headers *headers; |
a39116f1 | 1177 | fragS * fragP; |
05b4b0e7 | 1178 | |
a39116f1 | 1179 | { printf("call to md_convert_frag \n"); abort(); } |
cd8761e1 SC |
1180 | |
1181 | long | |
a39116f1 RP |
1182 | DEFUN(md_section_align,(seg, size), |
1183 | segT seg AND | |
1184 | long size) | |
cd8761e1 SC |
1185 | { |
1186 | return((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); | |
a39116f1 | 1187 | |
cd8761e1 SC |
1188 | } |
1189 | ||
05b4b0e7 | 1190 | void |
a39116f1 RP |
1191 | md_apply_fix(fixP, val) |
1192 | fixS *fixP; | |
1193 | long val; | |
05b4b0e7 SC |
1194 | { |
1195 | char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; | |
a39116f1 | 1196 | |
05b4b0e7 SC |
1197 | switch(fixP->fx_size) { |
1198 | case 1: | |
1199 | *buf++=val; | |
1200 | break; | |
1201 | case 2: | |
1202 | *buf++=(val>>8); | |
1203 | *buf++=val; | |
1204 | break; | |
1205 | case 4: | |
1206 | *buf++=(val>>24); | |
1207 | *buf++=(val>>16); | |
1208 | *buf++=(val>>8); | |
1209 | *buf++=val; | |
1210 | break; | |
1211 | default: | |
1212 | abort(); | |
1213 | ||
1214 | } | |
1215 | } | |
cd8761e1 SC |
1216 | |
1217 | void DEFUN(md_operand, (expressionP),expressionS *expressionP) | |
1218 | { } | |
1219 | ||
1220 | int md_long_jump_size; | |
05b4b0e7 | 1221 | int |
a39116f1 RP |
1222 | md_estimate_size_before_relax(fragP, segment_type) |
1223 | register fragS *fragP; | |
1224 | register segT segment_type; | |
5d9f0ecf | 1225 | { |
a39116f1 | 1226 | printf("call tomd_estimate_size_before_relax \n"); abort(); } |
cd8761e1 | 1227 | /* Put number into target byte order */ |
05b4b0e7 | 1228 | |
cd8761e1 SC |
1229 | void DEFUN(md_number_to_chars,(ptr, use, nbytes), |
1230 | char *ptr AND | |
05b4b0e7 SC |
1231 | long use AND |
1232 | int nbytes) | |
cd8761e1 | 1233 | { |
a39116f1 RP |
1234 | switch (nbytes) { |
1235 | case 4: *ptr++ = (use >> 24) & 0xff; | |
1236 | case 3: *ptr++ = (use >> 16) & 0xff; | |
1237 | case 2: *ptr++ = (use >> 8) & 0xff; | |
1238 | case 1: *ptr++ = (use >> 0) & 0xff; | |
1239 | break; | |
1240 | default: | |
1241 | abort(); | |
1242 | } | |
cd8761e1 | 1243 | } |
05b4b0e7 SC |
1244 | long md_pcrel_from(fixP) |
1245 | fixS *fixP; { abort(); } | |
cd8761e1 SC |
1246 | |
1247 | void tc_coff_symbol_emit_hook() { } | |
5d9f0ecf SC |
1248 | |
1249 | ||
1250 | void tc_reloc_mangle(fix_ptr, intr, base) | |
1251 | fixS *fix_ptr; | |
1252 | struct internal_reloc *intr; | |
1253 | bfd_vma base; | |
1254 | ||
1255 | { | |
a39116f1 RP |
1256 | symbolS *symbol_ptr; |
1257 | ||
1258 | symbol_ptr = fix_ptr->fx_addsy; | |
1259 | ||
1260 | /* If this relocation is attached to a symbol then it's ok | |
1261 | to output it */ | |
1262 | if (fix_ptr->fx_r_type == RELOC_32) { | |
1263 | /* cons likes to create reloc32's whatever the size of the reloc.. | |
1264 | */ | |
1265 | switch (fix_ptr->fx_size) | |
1266 | { | |
1267 | ||
1268 | case 2: | |
1269 | intr->r_type = R_RELWORD; | |
1270 | break; | |
1271 | case 1: | |
1272 | intr->r_type = R_RELBYTE; | |
1273 | break; | |
1274 | default: | |
1275 | abort(); | |
1276 | ||
1277 | } | |
1278 | ||
1279 | } | |
1280 | else { | |
1281 | intr->r_type = fix_ptr->fx_r_type; | |
1282 | } | |
1283 | ||
1284 | intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where +base; | |
1285 | intr->r_offset = fix_ptr->fx_offset; | |
1286 | ||
1287 | if (symbol_ptr) | |
1288 | intr->r_symndx = symbol_ptr->sy_number; | |
1289 | else | |
1290 | intr->r_symndx = -1; | |
5d9f0ecf | 1291 | |
5d9f0ecf | 1292 | |
5d9f0ecf | 1293 | } |