|
|
1.1 root 1: #include <ctype.h>
2: #include <string.h>
3: #include <mach-o/m98k/reloc.h>
4: #include "m98k-opcode.h"
5: #include "as.h"
6: #include "flonum.h"
7: #include "expr.h"
8: #include "hash.h"
9: #include "read.h"
10: #include "md.h"
11: #include "obstack.h"
12: #include "symbols.h"
13: #include "messages.h"
14: #include "atof-ieee.h"
15: #include "input-scrub.h"
16: #include "sections.h"
17:
18:
19: /*
20: * These are the default cputype and cpusubtype for the m98k architecture.
21: */
22: const cpu_type_t md_cputype = CPU_TYPE_MC98000;
23: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC98000_ALL;
24:
25: /* This is the byte sex for the m98k architecture */
26: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
27:
28: /* These characters start a comment anywhere on the line */
29: const char md_comment_chars[] = ";";
30:
31: /* These characters only start a comment at the beginning of a line */
32: const char md_line_comment_chars[] = "#";
33:
34: /*
35: * These characters can be used to separate mantissa decimal digits from
36: * exponent decimal digits in floating point numbers.
37: */
38: const char md_EXP_CHARS[] = "eE";
39:
40: /*
41: * The characters after a leading 0 that means this number is a floating point
42: * constant as in 0f123.456 or 0d1.234E-12 (see md_EXP_CHARS above).
43: */
44: const char md_FLT_CHARS[] = "dDfF";
45:
46: /*
47: * This is the machine dependent pseudo opcode table for this target machine.
48: */
49: static void s_reg(
50: int reg);
51: const pseudo_typeS md_pseudo_table[] =
52: {
53: {"greg", s_reg, 'r' },
54: {0} /* end of table marker */
55: };
56:
57: #define RT(x) (((x) >> 21) & 0x1f)
58: #define RA(x) (((x) >> 16) & 0x1f)
59:
60: struct m98k_insn {
61: unsigned long opcode;
62: expressionS exp;
63: enum reloc_type_m98k reloc;
64: long pcrel;
65: long pcrel_reloc;
66: };
67:
68: /*
69: * The pointer to the opcode hash table built by md_begin() and used by
70: * md_assemble() to look up opcodes.
71: */
72: static struct hash_control *op_hash = NULL;
73:
74: /*
75: * These aid in the printing of better error messages for parameter syntax
76: * errors when there is only one mnemonic in the tables.
77: */
78: static unsigned long error_param_count = 0;
79: static char *error_param_message = NULL;
80:
81: /*
82: * These are name names of the known special registers and the numbers assigned
83: * to them.
84: */
85: struct special_register {
86: unsigned long number;
87: char *name;
88: };
89: static const struct special_register special_registers[] = {
90: { 0, "mq" }, /* 601 only */
91: { 1, "xer" },
92: { 4, "rtcu" },
93: { 5, "rtcl" },
94: { 8, "lr" },
95: { 9, "ctr" },
96: { 18, "dsisr" },
97: { 19, "dar" },
98: { 22, "dec" },
99: { 25, "sdr1" },
100: { 26, "srr0" },
101: { 27, "srr1" },
102: { 272, "sprg0" },
103: { 273, "sprg1" },
104: { 274, "sprg2" },
105: { 275, "sprg3" },
106: { 280, "asr" },
107: { 281, "rtcd" },
108: { 282, "rtci" },
109: { 287, "pvr" },
110: { 528, "ibat0u" },
111: { 529, "ibat0l" },
112: { 530, "ibat1u" },
113: { 531, "ibat1l" },
114: { 532, "ibat2u" },
115: { 533, "ibat2l" },
116: { 534, "ibat3u" },
117: { 535, "ibat3l" },
118: { 528, "bat0u" }, /* 601 only */
119: { 529, "bat0l" }, /* 601 only */
120: { 530, "bat1u" }, /* 601 only */
121: { 531, "bat1l" }, /* 601 only */
122: { 532, "bat2u" }, /* 601 only */
123: { 533, "bat2l" }, /* 601 only */
124: { 534, "bat3u" }, /* 601 only */
125: { 535, "bat3l" }, /* 601 only */
126: { 536, "dbat0u" },
127: { 537, "dbat0l" },
128: { 538, "dbat1u" },
129: { 539, "dbat1l" },
130: { 540, "dbat2u" },
131: { 541, "dbat2l" },
132: { 542, "dbat3u" },
133: { 543, "dbat3l" },
134: { 1008,"hid0" }, /* 601 only */
135: { 1009,"hid1" }, /* 601 only */
136: { 1010,"hid2" }, /* 601 only */
137: { 1013,"hid5" }, /* 601 only */
138: { 1013,"dabr" }, /* 601 only */
139: { 1022,"fpecr" },
140: { 1023,"pid" }, /* 601 only */
141: { 0, "" } /* end of table marker */
142: };
143:
144: /*
145: * These are name names of the condition field special registers and the
146: * numbers assigned to them.
147: */
148: struct condition_symbol {
149: unsigned long value;
150: char *name;
151: };
152: static const struct condition_symbol condition_symbols[] = {
153: { 0, "lt" }, /* less than */
154: { 1, "gt" }, /* greater than */
155: { 2, "eq" }, /* equal */
156: { 3, "so" }, /* summary overflow */
157: { 3, "un" }, /* unordered */
158: { 0, "" } /* end of table marker */
159: };
160:
161: struct CR_field {
162: unsigned long value;
163: char *name;
164: };
165: static const struct CR_field CR_fields[] = {
166: { 0, "cr0" }, /* CR field 0 */
167: { 4, "cr1" }, /* CR field 1 */
168: { 8, "cr2" }, /* CR field 2 */
169: { 12, "cr3" }, /* CR field 3 */
170: { 16, "cr4" }, /* CR field 4 */
171: { 20, "cr5" }, /* CR field 5 */
172: { 24, "cr6" }, /* CR field 6 */
173: { 28, "cr7" }, /* CR field 7 */
174: { 0, "" } /* end of table marker */
175: };
176:
177: /*
178: * These are built in macros because they are trivial to implement as macros
179: * which otherwise be less obvious to do special entries for them.
180: */
181: struct macros {
182: char *name;
183: char *body;
184: };
185: static const struct macros m98k_macros[] = {
186: { "extldi\n", "rldicr $0,$1,$3,$2-1\n" },
187: { "extldi.\n", "rldicr. $0,$1,$3,$2-1\n" },
188: { "extrdi\n", "rldicl $0,$1,$2+$3,64-$2\n" },
189: { "extrdi.\n", "rldicl. $0,$1,$2+$3,64-$2\n" },
190: { "insrdi\n", "rldimi $0,$1,64-($3+$2),$3\n" },
191: { "insrdi.\n", "rldimi. $0,$1,64-($3+$2),$3\n" },
192: { "rotldi\n", "rldicl $0,$1,$2,0\n" },
193: { "rotldi.\n", "rldicl. $0,$1,$2,0\n" },
194: { "rotrdi\n", "rldicl $0,$1,64-$2,0\n" },
195: { "rotrdi.\n", "rldicl. $0,$1,64-$2,0\n" },
196: { "rotld\n", "rldcl $0,$1,$2,0\n" },
197: { "rotld.\n", "rldcl. $0,$1,$2,0\n" },
198: { "sldi\n", "rldicr $0,$1,$2,63-$2\n" },
199: { "sldi.\n", "rldicr. $0,$1,$2,63-$2\n" },
200: { "srdi\n", "rldicl $0,$1,64-$2,$2\n" },
201: { "srdi.\n", "rldicl. $0,$1,64-$2,$2\n" },
202: { "clrldi\n", "rldicl $0,$1,0,$2\n" },
203: { "clrldi.\n", "rldicl. $0,$1,0,$2\n" },
204: { "clrrdi\n", "rldicl $0,$1,0,63-$2\n" },
205: { "clrrdi.\n", "rldicl. $0,$1,0,63-$2\n" },
206: { "clrlsldi\n","rldic $0,$1,$3,$2-$3\n" },
207: { "clrlsldi.\n","rldic. $0,$1,$3,$2-$3\n" },
208:
209: { "extlwi\n", "rlwinm $0,$1,$3,0,$2-1\n" },
210: { "extlwi.\n", "rlwinm. $0,$1,$3,0,$2-1\n" },
211: { "extrwi\n", "rlwinm $0,$1,$2+$3,32-$2,31\n" },
212: { "extrwi.\n", "rlwinm. $0,$1,$2+$3,32-$2,31\n" },
213: { "inslwi\n", "rlwimi $0,$1,32-$3,$3,($3+$2)-1\n" },
214: { "inslwi.\n", "rlwimi. $0,$1,32-$3,$3,($3+$2)-1\n" },
215: { "insrwi\n", "rlwimi $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
216: { "insrwi.\n", "rlwimi. $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
217: { "rotlwi\n", "rlwinm $0,$1,$2,0,31\n" },
218: { "rotlwi.\n", "rlwinm. $0,$1,$2,0,31\n" },
219: { "rotrwi\n", "rlwinm $0,$1,32-$2,0,31\n" },
220: { "rotrwi.\n", "rlwinm. $0,$1,32-$2,0,31\n" },
221: { "rotlw\n", "rlwnm $0,$1,$2,0,31\n" },
222: { "rotlw.\n", "rlwnm. $0,$1,$2,0,31\n" },
223: { "slwi\n", "rlwinm $0,$1,$2,0,31-$2\n" },
224: { "slwi.\n", "rlwinm. $0,$1,$2,0,31-$2\n" },
225: { "srwi\n", "rlwinm $0,$1,32-$2,$2,31\n" },
226: { "srwi.\n", "rlwinm. $0,$1,32-$2,$2,31\n" },
227: { "clrlwi\n", "rlwinm $0,$1,0,$2,31\n" },
228: { "clrlwi.\n", "rlwinm. $0,$1,0,$2,31\n" },
229: { "clrrwi\n", "rlwinm $0,$1,0,0,31-$2\n" },
230: { "clrrwi.\n", "rlwinm. $0,$1,0,0,31-$2\n" },
231: { "clrlslwi\n","rlwinm $0,$1,$3,$2-$3,31-$2\n" },
232: { "clrlslwi.\n","rlwinm. $0,$1,$3,$2-$3,31-$2\n" },
233:
234: { "mtxer\n", "mtspr 1,$0\n"},
235: { "mfxer\n", "mfspr $0,1\n"},
236: { "mtlr\n", "mtspr 8,$0\n"},
237: { "mflr\n", "mfspr $0,8\n"},
238: { "mtctr\n", "mtspr 9,$0\n"},
239: { "mfctr\n", "mfspr $0,9\n"},
240: { "mtdsisr\n", "mtspr 18,$0\n"},
241: { "mfdsisr\n", "mfspr $0,18\n"},
242: { "mtdar\n", "mtspr 19,$0\n"},
243: { "mfdar\n", "mfspr $0,19\n"},
244: { "mtdec\n", "mtspr 22,$0\n"},
245: { "mfdec\n", "mfspr $0,22\n"},
246: { "mtsdr1\n", "mtspr 25,$0\n"},
247: { "mfsdr1\n", "mfspr $0,25\n"},
248: { "mtsrr0\n", "mtspr 26,$0\n"},
249: { "mfsrr0\n", "mfspr $0,26\n"},
250: { "mtsrr1\n", "mtspr 27,$0\n"},
251: { "mfsrr1\n", "mfspr $0,27\n"},
252: { "mtsprg\n", "mtspr 272+$0,$1\n"},
253: { "mfsprg\n", "mfspr $0,272+$1\n"},
254: { "mtasr\n", "mtspr 280,$0\n"},
255: { "mfasr\n", "mfspr $0,280\n"},
256: { "mtrtcd\n", "mtspr 281,$0\n"},
257: { "mfrtcd\n", "mfspr $0,281\n"},
258: { "mtrtci\n", "mtspr 282,$0\n"},
259: { "mfrtci\n", "mfspr $0,282\n"},
260: { "mfpvr\n", "mfspr $0,287\n"},
261: { "mtibatu\n", "mtspr 528+2*$0,$1\n"},
262: { "mfibatu\n", "mfspr $0,528+2*$1\n"},
263: { "mtibatl\n", "mtspr 529+2*$0,$1\n"},
264: { "mfibatl\n", "mfspr $0,529+2*$1\n"},
265: { "mtdbatu\n", "mtspr 536+2*$0,$1\n"},
266: { "mfdbatu\n", "mfspr $0,536+2*$1\n"},
267: { "mtdbatl\n", "mtspr 537+2*$0,$1\n"},
268: { "mfdbatl\n", "mfspr $0,537+2*$1\n"},
269:
270: { "mtbatu\n", "mtspr 528+2*$0,$1\n"},
271: { "mfbatu\n", "mfspr $0,528+2*$1\n"},
272: { "mtbatl\n", "mtspr 529+2*$0,$1\n"},
273: { "mfbatl\n", "mfspr $0,529+2*$1\n"},
274:
275: { "subi\n", "addi $0,$1,-($2)\n"},
276: { "subis\n", "addis $0,$1,-($2)\n"},
277: { "subic\n", "addic $0,$1,-($2)\n"},
278: { "subic.\n", "addic. $0,$1,-($2)\n"},
279:
280: { "", "" } /* end of table marker */
281: };
282:
283: static int calcop(
284: struct m98k_opcode *format,
285: char *param,
286: struct m98k_insn *insn,
287: char *op,
288: char prediction);
289: static char *parse_branch(
290: char *param,
291: struct m98k_insn *insn,
292: struct m98k_opcode *format,
293: int parcnt);
294: static char *parse_displacement(
295: char *param,
296: struct m98k_insn *insn,
297: struct m98k_opcode *format,
298: int parcnt);
299: static char *parse_immediate(
300: char *param,
301: struct m98k_insn *insn,
302: struct m98k_opcode *format,
303: int parcnt);
304: static char *parse_reg(
305: char *reg_name,
306: char *param,
307: struct m98k_insn *insn,
308: struct m98k_opcode *format,
309: unsigned long parcnt);
310: static char *parse_spreg(
311: char *param,
312: struct m98k_insn *insn,
313: struct m98k_opcode *format,
314: unsigned long parcnt);
315: static char *parse_bcnd(
316: char *param,
317: struct m98k_insn *insn,
318: struct m98k_opcode *format,
319: unsigned long parcnt);
320: static char *parse_crf(
321: char *param,
322: struct m98k_insn *insn,
323: struct m98k_opcode *format,
324: unsigned long parcnt);
325: static char *parse_num(
326: char *param,
327: struct m98k_insn *insn,
328: struct m98k_opcode *format,
329: unsigned long parcnt,
330: long max_width_zero);
331: static char *parse_sh(
332: char *param,
333: struct m98k_insn *insn,
334: struct m98k_opcode *format,
335: unsigned long parcnt);
336: static char *parse_mb(
337: char *param,
338: struct m98k_insn *insn,
339: struct m98k_opcode *format,
340: unsigned long parcnt);
341:
342: /*
343: * md_begin() is called from main() in as.c before assembly begins. It is used
344: * to allow target machine dependent initialization.
345: */
346: void
347: md_begin(void)
348: {
349: unsigned long i;
350: char *name, *retval;
351:
352: /* initialize the opcode hash table */
353: op_hash = hash_new();
354: if(op_hash == NULL)
355: as_fatal("Could not initialize the opcode hash table");
356:
357: /* loop until you see the end of the list */
358: i = 0;
359: while(*m98k_opcodes[i].name){
360: name = m98k_opcodes[i].name;
361:
362: /* hash each mnemonic and record its position */
363: retval = hash_insert(op_hash, name, (char *)&m98k_opcodes[i]);
364: if(retval != NULL && *retval != '\0')
365: as_fatal("Can't hash instruction '%s':%s",
366: m98k_opcodes[i].name, retval);
367:
368: /* skip to next unique mnemonic or end of list */
369: for(i++; strcmp(m98k_opcodes[i].name, name) == 0; i++)
370: ;
371: }
372:
373: /*
374: * Load the builtin macros for extended mnemonics for rotate and
375: * shift mnemonics.
376: */
377: for(i = 0; *m98k_macros[i].name != '\0'; i++){
378: input_line_pointer = m98k_macros[i].name;
379: s_macro(0);
380: add_to_macro_definition(m98k_macros[i].body);
381: s_endmacro(0);
382: }
383: }
384:
385: /*
386: * md_end() is called from main() in as.c after assembly ends. It is used
387: * to allow target machine dependent clean up.
388: */
389: void
390: md_end(void)
391: {
392: }
393:
394: /*
395: * md_parse_option() is called from main() in as.c to parse target machine
396: * dependent command line options. This routine returns 0 if it is passed an
397: * option that is not recognized non-zero otherwise.
398: */
399: int
400: md_parse_option(
401: char **argP,
402: int *cntP,
403: char ***vecP)
404: {
405: return(0);
406: }
407:
408: /*
409: * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
410: * which set symbol to 1 or 0 depending on if the expression is a general
411: * register or extended register respectfully. These are intended for use in
412: * macros.
413: */
414: static
415: void
416: s_reg(
417: int reg)
418: {
419: char *name, *end_name, delim;
420: symbolS *symbolP;
421: unsigned long n_value, val;
422:
423: if( * input_line_pointer == '"')
424: name = input_line_pointer + 1;
425: else
426: name = input_line_pointer;
427: delim = get_symbol_end();
428: end_name = input_line_pointer;
429: *end_name = delim;
430: SKIP_WHITESPACE();
431: if ( * input_line_pointer != ',' ) {
432: *end_name = 0;
433: as_warn("Expected comma after name \"%s\"", name);
434: *end_name = delim;
435: ignore_rest_of_line();
436: return;
437: }
438: input_line_pointer ++;
439: *end_name = 0;
440:
441: SKIP_WHITESPACE();
442: n_value = 0;
443: if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
444: input_line_pointer++;
445: if(isdigit(*input_line_pointer)){
446: val = 0;
447: while (isdigit(*input_line_pointer)){
448: if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
449: break;
450: }
451: SKIP_WHITESPACE();
452: if(val <= 31 &&
453: (*input_line_pointer == '\n' || *input_line_pointer == '@'))
454: n_value = 1;
455: }
456: }
457:
458: symbolP = symbol_find_or_make (name);
459: symbolP -> sy_type = N_ABS;
460: symbolP -> sy_other = 0; /* NO_SECT */
461: symbolP -> sy_value = n_value;
462: symbolP -> sy_frag = & zero_address_frag;
463:
464: *end_name = delim;
465: totally_ignore_line();
466: }
467:
468: /*
469: * md_assemble() is passed a pointer to a string that should be a assembly
470: * statement for the target machine.
471: */
472: void
473: md_assemble(
474: char *op)
475: {
476: char *param, *thisfrag, prediction;
477: struct m98k_opcode *format;
478: struct m98k_insn insn;
479: unsigned long retry;
480:
481: /*
482: * Pick up the instruction and any trailing branch prediction character
483: * (a trailing '+' or '-' on the instruction).
484: */
485: prediction = '\0';
486: for(param = op; !isspace(*param) && *param != '\0' ; param++)
487: prediction = *param;
488: if(prediction == '+' || prediction == '-')
489: param[-1] = '\0';
490: else
491: prediction = '\0';
492: if(*param != '\0')
493: *param++ = '\0';
494:
495: /* try to find the instruction in the hash table */
496: if((format = (struct m98k_opcode *)hash_find(op_hash, op)) == NULL){
497: as_warn("Invalid mnemonic '%s'", op);
498: return;
499: }
500:
501: /* try parsing this instruction into insn */
502: retry = 0;
503: error_param_count = 0;
504: error_param_message = NULL;
505: while(calcop(format, param, &insn, op, prediction) == 0){
506: /* if it doesn't parse try the next instruction */
507: if(strcmp(format->name, format[1].name) == 0){
508: format++;
509: retry = 1;
510: }
511: else{
512: if(retry == 0){
513: if(error_param_message != NULL)
514: as_warn(error_param_message, error_param_count + 1);
515: else
516: as_warn("Parameter syntax error (parameter %lu)",
517: error_param_count + 1);
518: }
519: else
520: as_warn("Parameter syntax error");
521: return;
522: }
523: }
524:
525: /*
526: * Check for invalid forms of instructions. For the following
527: * instructions: lbzu, lbzux, lhzu, lhzux, lhau, lhaux, lwzu, lwzux,
528: * lwaux, ldu, ldux
529: * if RA == 0 or RA == RT the instruction form is invalid.
530: */
531: if((insn.opcode & 0xfc000000) == 0x8c000000 || /* lbzu */
532: (insn.opcode & 0xfc0007fe) == 0x7c0000ee || /* lbzux */
533: (insn.opcode & 0xfc000000) == 0xa4000000 || /* lhzu */
534: (insn.opcode & 0xfc0007fe) == 0x7c00026e || /* lbzux */
535: (insn.opcode & 0xfc000000) == 0xac000000 || /* lhau */
536: (insn.opcode & 0xfc0007fe) == 0x7c0002ee || /* lhaux */
537: (insn.opcode & 0xfc000000) == 0x84000000 || /* lwzu */
538: (insn.opcode & 0xfc0007fe) == 0x7c00006e || /* lwzux */
539: (insn.opcode & 0xfc0007fe) == 0x7c0002ea || /* lwaux */
540: (insn.opcode & 0xfc000000) == 0xe8000000 || /* ldu */
541: (insn.opcode & 0xfc0007fe) == 0x7c00006a){ /* ldux */
542: if(RA(insn.opcode) == 0)
543: as_warn("Invalid form of the instruction (RA must not be 0)");
544: if(RA(insn.opcode) == RT(insn.opcode))
545: as_warn("Invalid form of the instruction (RA must not the same "
546: "as RT)");
547: }
548: /*
549: * For the following instructions: stbu, stbux, sthu, sthux, stwu,
550: * stwux, stdu, stdux, lfsu, lfsux, lfdu, lfdux, stfsu, stfsux, stfdu,
551: * stfdux
552: * if RA == 0 the instruction form is invalid.
553: */
554: if((insn.opcode & 0xfc000000) == 0x9c000000 || /* stbu */
555: (insn.opcode & 0xfc0007fe) == 0x7c0001ee || /* stbux */
556: (insn.opcode & 0xfc000000) == 0xb4000000 || /* sthu */
557: (insn.opcode & 0xfc0007fe) == 0x7c00036e || /* sthux */
558: (insn.opcode & 0xfc000000) == 0x94000000 || /* stwu */
559: (insn.opcode & 0xfc0007fe) == 0x7c00016e || /* stwux */
560: (insn.opcode & 0xfc000003) == 0xf8000001 || /* stdu */
561: (insn.opcode & 0xfc0007fe) == 0x7c00016a || /* stdux */
562: (insn.opcode & 0xfc000000) == 0xc4000000 || /* lfsu */
563: (insn.opcode & 0xfc0007fe) == 0x7c00046e || /* lfsux */
564: (insn.opcode & 0xfc000000) == 0xcc000000 || /* lfdu */
565: (insn.opcode & 0xfc0007fe) == 0x7c0004ee || /* lfdux */
566: (insn.opcode & 0xfc000000) == 0xd4000000 || /* stfsu */
567: (insn.opcode & 0xfc0007fe) == 0x7c00056e || /* stfsux */
568: (insn.opcode & 0xfc000000) == 0xdc000000 || /* stfdu */
569: (insn.opcode & 0xfc0007fe) == 0x7c0005ee){ /* stfdux */
570: if(RA(insn.opcode) == 0)
571: as_warn("Invalid form of the instruction (RA must not be 0)");
572: }
573: /*
574: * For the following instructions: lmw, lmd, lswi, lswx
575: * if RA is in the range of registers to be loaded or RT == RA == 0
576: * the instruction form is invalid. WHAT does this mean?
577: */
578: if((insn.opcode & 0xfc000000) == 0xb8000000 || /* lmw */
579: (insn.opcode & 0xfc000003) == 0xe8000003 || /* lmw */
580: (insn.opcode & 0xfc0007fe) == 0x7c0004aa || /* lswi */
581: (insn.opcode & 0xfc0007fe) == 0x7c00042a){ /* lswx */
582: }
583:
584: /* grow the current frag and plop in the opcode */
585: thisfrag = frag_more(4);
586: md_number_to_chars(thisfrag, insn.opcode, 4);
587:
588: /*
589: * If the -g flag is present generate a line number stab for the
590: * instruction.
591: *
592: * See the detailed comments about stabs in read_a_source_file() for a
593: * description of what is going on here.
594: */
595: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
596: (void)symbol_new(
597: "",
598: 68 /* N_SLINE */,
599: text_nsect,
600: logical_input_line /* n_desc, line number */,
601: obstack_next_free(&frags) - frag_now->fr_literal,
602: frag_now);
603: }
604:
605: /* if this instruction requires labels mark it for later */
606: switch(insn.reloc){
607: case NO_RELOC:
608: break;
609: case M98K_RELOC_HI16:
610: case M98K_RELOC_LO16:
611: case M98K_RELOC_HA16:
612: case M98K_RELOC_LO14:
613: fix_new(frag_now,
614: thisfrag - frag_now->fr_literal,
615: 4,
616: insn.exp.X_add_symbol,
617: insn.exp.X_subtract_symbol,
618: insn.exp.X_add_number,
619: 0, 0,
620: insn.reloc);
621: break;
622: case M98K_RELOC_BR14:
623: fix_new(frag_now,
624: thisfrag - frag_now->fr_literal,
625: 4,
626: insn.exp.X_add_symbol,
627: insn.exp.X_subtract_symbol,
628: insn.exp.X_add_number,
629: insn.pcrel,
630: insn.pcrel_reloc,
631: insn.reloc);
632: break;
633:
634: case M98K_RELOC_BR24:
635: fix_new(frag_now,
636: thisfrag - frag_now->fr_literal,
637: 4,
638: insn.exp.X_add_symbol,
639: insn.exp.X_subtract_symbol,
640: insn.exp.X_add_number,
641: insn.pcrel,
642: insn.pcrel_reloc,
643: insn.reloc);
644: break;
645: default:
646: as_warn("Unknown relocation type");
647: break;
648: }
649: }
650:
651: static
652: int
653: calcop(
654: struct m98k_opcode *format,
655: char *param,
656: struct m98k_insn *insn,
657: char *op,
658: char prediction)
659: {
660: unsigned long parcnt;
661:
662: /* initial the passed structure */
663: memset(insn, '\0', sizeof(struct m98k_insn));
664: insn->opcode = format->opcode;
665: insn->reloc = NO_RELOC;
666:
667: /* parse all parameters */
668: for(parcnt = 0; parcnt < 5 &&
669: format->ops[parcnt].type != NONE; parcnt++){
670: error_param_count = parcnt;
671:
672: switch(format->ops[parcnt].type){
673: case PCREL:
674: case BADDR:
675: param = parse_branch(param, insn, format, parcnt);
676: break;
677: case D:
678: case DS:
679: param = parse_displacement(param, insn, format, parcnt);
680: break;
681: case SI:
682: case UI:
683: param = parse_immediate(param, insn, format, parcnt);
684: break;
685: case GREG:
686: case G0REG:
687: param = parse_reg("r", param, insn, format, parcnt);
688: break;
689: case FREG:
690: param = parse_reg("f", param, insn, format, parcnt);
691: break;
692: case SGREG:
693: param = parse_reg("sr", param, insn, format, parcnt);
694: break;
695: case SPREG:
696: param = parse_spreg(param, insn, format, parcnt);
697: break;
698: case BCND:
699: param = parse_bcnd(param, insn, format, parcnt);
700: break;
701: case CRF:
702: case CRFONLY:
703: param = parse_crf(param, insn, format, parcnt);
704: break;
705: case NUM:
706: param = parse_num(param, insn, format, parcnt, 0);
707: break;
708: case NUM0:
709: param = parse_num(param, insn, format, parcnt, 1);
710: break;
711: case sh:
712: param = parse_sh(param, insn, format, parcnt);
713: break;
714: case mb:
715: param = parse_mb(param, insn, format, parcnt);
716: break;
717: default:
718: as_fatal("Unknown parameter type");
719: }
720:
721: /* see if parser failed or not */
722: if (param == NULL)
723: return(0);
724: }
725: if(format->ops[0].type == NONE && *param != '\0'){
726: error_param_message = "too many parameters";
727: return(0);
728: }
729:
730: if(IS_BRANCH_CONDITIONAL(insn->opcode)){
731: if(prediction != '\0'){
732: /*
733: * Set the Y_BIT assuming the displacement is non-negitive.
734: * If the displacement is negitive then the Y_BIT is flipped
735: * in md_number_to_imm().
736: */
737: if(prediction == '+')
738: insn->opcode |= Y_BIT;
739: else{ /* prediction == '-' */
740: if((insn->opcode & Y_BIT) != 0)
741: as_warn("branch prediction ('-') ignored (specified "
742: "operand has prediction bit set)");
743: else
744: insn->opcode &= ~(Y_BIT);
745: }
746: }
747: }
748: else{
749: if(prediction != '\0')
750: as_warn("branch prediction ignored (instruction is not a "
751: "conditional branch)");
752: }
753: return(1);
754: }
755:
756: static
757: char *
758: parse_displacement(
759: char *param,
760: struct m98k_insn *insn,
761: struct m98k_opcode *format,
762: int parcnt)
763: {
764: unsigned long val;
765: char *end, *saveptr, *saveparam;
766: segT seg;
767:
768:
769: if(parcnt != 1 || format->ops[2].type != G0REG)
770: as_fatal("internal error, bad table entry for instruction %s "
771: "(displacement operand not second operand or general "
772: "register not third operand)", format->name);
773:
774: /*
775: * There must be "(rX)" (where X is a number between 0-31) or "(0)"
776: * at the end of the parameter string. To know out where the
777: * displacement expression ends determine the begining the "(rX)"
778: * by looking for the last '(' in the string. The parsing of this
779: * trailing string will be done in another routine.
780: */
781: end = strrchr(param, '(');
782: if(end == NULL)
783: return(NULL);
784: *end = '\0';
785:
786: /*
787: * The expression may have one of the following: hi16(exp), ha16(exp),
788: * or lo16(exp) around the expression which determines the relocation
789: * type.
790: */
791: if(strncmp(param,"hi16(",5) == 0){
792: insn->reloc = M98K_RELOC_HI16;
793: param += 5;
794: }
795: else if(strncmp(param,"ha16(",5) == 0){
796: insn->reloc = M98K_RELOC_HA16;
797: param += 5;
798: }
799: else if(strncmp(param,"lo16(",5) == 0){
800: if(format->ops[parcnt].type == DS)
801: insn->reloc = M98K_RELOC_LO14;
802: else
803: insn->reloc = M98K_RELOC_LO16;
804: param += 5;
805: }
806:
807: saveptr = input_line_pointer;
808: input_line_pointer = param;
809:
810: seg = expression(&insn->exp);
811: try_to_make_absolute(&insn->exp);
812: seg = insn->exp.X_seg;
813:
814: saveparam = input_line_pointer;
815: input_line_pointer = saveptr;
816: *end = '(';
817:
818: if(insn->reloc != NO_RELOC){
819: if(*saveparam != ')' || ++saveparam != end)
820: return(NULL);
821: }
822: else{
823: if(saveparam != end)
824: return(NULL);
825: val = insn->exp.X_add_number;
826: if(seg != SEG_ABSOLUTE){
827: error_param_message = "Parameter error: expression must be "
828: "absolute (parameter %lu)";
829: return(NULL);
830: }
831: if(val & 0x8000){
832: if((val & 0xffff0000) != 0xffff0000){
833: error_param_message = "Parameter error: expression out of "
834: "range (parameter %lu)";
835: return(NULL);
836: }
837: val = val & 0xffff;
838: }
839: else{
840: if((val & 0xffff0000) != 0){
841: error_param_message = "Parameter error: expression out of "
842: "range (parameter %lu)";
843: return(NULL);
844: }
845: }
846: if(format->ops[parcnt].type == DS){
847: if((val & 0x3) != 0){
848: error_param_message = "Parameter error: expression must be "
849: "a multiple of 4 (parameter %lu)";
850: return(NULL);
851: }
852: val >>= 2;
853: }
854: insn->opcode |= val << format->ops[parcnt].offset;
855: }
856: return(saveparam);
857: }
858:
859: static
860: char *
861: parse_immediate(
862: char *param,
863: struct m98k_insn *insn,
864: struct m98k_opcode *format,
865: int parcnt)
866: {
867: unsigned long val;
868: char *saveptr, *saveparam;
869: segT seg;
870:
871: /*
872: * The expression may have one of the following: hi16(exp), ha16(exp),
873: * or lo16(exp) around the expression which determines the relocation
874: * type.
875: */
876: if(strncmp(param,"hi16(",5) == 0){
877: insn->reloc = M98K_RELOC_HI16;
878: param += 5;
879: }
880: else if(strncmp(param,"ha16(",5) == 0){
881: insn->reloc = M98K_RELOC_HA16;
882: param += 5;
883: }
884: else if(strncmp(param,"lo16(",5) == 0){
885: if(format->ops[parcnt].type == DS)
886: insn->reloc = M98K_RELOC_LO14;
887: else
888: insn->reloc = M98K_RELOC_LO16;
889: param += 5;
890: }
891:
892: saveptr = input_line_pointer;
893: input_line_pointer = param;
894:
895: seg = expression(&insn->exp);
896: try_to_make_absolute(&insn->exp);
897: seg = insn->exp.X_seg;
898:
899: saveparam = input_line_pointer;
900: input_line_pointer = saveptr;
901:
902: if(insn->reloc != NO_RELOC){
903: if(*saveparam != ')')
904: return(NULL);
905: saveparam++;
906: if(*saveparam == '\0'){
907: if(parcnt == 4 || format->ops[parcnt+1].type == NONE)
908: return(saveparam);
909: else
910: return(NULL);
911: }
912: else if(*saveparam == ','){
913: if(parcnt != 4 && format->ops[parcnt+1].type != NONE)
914: return(saveparam+1);
915: else
916: return(NULL);
917: }
918: else
919: return(NULL);
920: }
921: else{
922: val = insn->exp.X_add_number;
923: if(seg != SEG_ABSOLUTE){
924: error_param_message = "Parameter error: expression must be "
925: "absolute (parameter %lu)";
926: return(NULL);
927: }
928: if(format->ops[parcnt].type == SI){
929: if(val & 0x8000){
930: if((val & 0xffff0000) != 0xffff0000){
931: error_param_message = "Parameter error: expression out "
932: "of range (parameter %lu)";
933: return(NULL);
934: }
935: val = val & 0xffff;
936: }
937: else{
938: if((val & 0xffff0000) != 0){
939: error_param_message = "Parameter error: expression out "
940: "of range (parameter %lu)";
941: return(NULL);
942: }
943: }
944: }
945: else{
946: if((val & 0xffff0000) != 0){
947: error_param_message = "Parameter error: expression out "
948: "of range (parameter %lu)";
949: return(NULL);
950: }
951: }
952: if(*saveparam == '\0'){
953: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
954: insn->opcode |= val << format->ops[parcnt].offset;
955: return(saveparam);
956: }
957: else
958: return(NULL);
959: }
960: else if(*saveparam == ','){
961: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
962: insn->opcode |= val << format->ops[parcnt].offset;
963: return(saveparam+1);
964: }
965: else
966: return(NULL);
967: }
968: else
969: return(NULL);
970: }
971: return(saveparam);
972: }
973:
974: static
975: char *
976: parse_branch(
977: char *param,
978: struct m98k_insn *insn,
979: struct m98k_opcode *format,
980: int parcnt)
981: {
982: char *saveptr, *saveparam;
983: segT seg;
984:
985: saveptr = input_line_pointer;
986: input_line_pointer = param;
987:
988: seg = expression(&insn->exp);
989: try_to_make_absolute(&insn->exp);
990: seg = insn->exp.X_seg;
991:
992: saveparam = input_line_pointer;
993: input_line_pointer = saveptr;
994:
995: insn->pcrel = 0;
996: insn->pcrel_reloc = 0;
997: if(format->ops[parcnt].type == PCREL){
998: /*
999: * The NeXT linker has the ability to scatter blocks of
1000: * sections between labels. This requires that brances to
1001: * labels that survive to the link phase must be able to
1002: * be relocated.
1003: */
1004: if(insn->exp.X_add_symbol != NULL &&
1005: (insn->exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
1006: insn->pcrel_reloc = 1;
1007: else
1008: insn->pcrel_reloc = 0;
1009: insn->pcrel = 1;
1010: }
1011: switch(format->ops[parcnt].width){
1012: case 14:
1013: insn->reloc = M98K_RELOC_BR14;
1014: break;
1015: case 24:
1016: insn->reloc = M98K_RELOC_BR24;
1017: break;
1018: default:
1019: as_fatal("Unknown branch instruction width %d",
1020: format->ops[parcnt].width);
1021: break;
1022: }
1023: return(saveparam);
1024: }
1025:
1026: static
1027: char *
1028: parse_reg(
1029: char *reg_name,
1030: char *param,
1031: struct m98k_insn *insn,
1032: struct m98k_opcode *format,
1033: unsigned long parcnt)
1034: {
1035: unsigned long val, d;
1036:
1037: d = 0;
1038: if(*param == '(' && parcnt == 2 &&
1039: (format->ops[1].type == D || format->ops[1].type == DS)){
1040: d = 1;
1041: param++;
1042: }
1043:
1044: if(format->ops[parcnt].type == G0REG && *param == '0'){
1045: val = 0;
1046: param++;
1047: }
1048: else{
1049: val = 0;
1050: while(*reg_name){
1051: if(*param++ != *reg_name++)
1052: return(NULL);
1053: }
1054: if(!isdigit(*param))
1055: return(NULL);
1056:
1057: while(isdigit(*param))
1058: if((val = val * 10 + *param++ - '0') >=
1059: 1 << format->ops[parcnt].width)
1060: return(NULL);
1061:
1062: if(format->ops[parcnt].type == G0REG && val == 0){
1063: error_param_message = "Parameter error: r0 not allowed "
1064: "for parameter %lu (code as 0 not r0)";
1065: return(NULL);
1066: }
1067: }
1068:
1069: if(*param == '\0'){
1070: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1071: insn->opcode |= val << format->ops[parcnt].offset;
1072: return(param);
1073: }
1074: else
1075: return(NULL);
1076: }
1077: else if(*param == ','){
1078: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1079: insn->opcode |= val << format->ops[parcnt].offset;
1080: return(param+1);
1081: }
1082: else
1083: return(NULL);
1084: }
1085: else if(d == 1 && *param == ')' && param[1] == '\0'){
1086: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1087: insn->opcode |= val << format->ops[parcnt].offset;
1088: return(++param);
1089: }
1090: else
1091: return(NULL);
1092: }
1093: return(NULL);
1094: }
1095:
1096: static
1097: char *
1098: parse_spreg(
1099: char *param,
1100: struct m98k_insn *insn,
1101: struct m98k_opcode *format,
1102: unsigned long parcnt)
1103: {
1104: int val;
1105: unsigned long i;
1106: char *saveptr, save_c;
1107: expressionS exp;
1108: segT seg;
1109:
1110: saveptr = input_line_pointer;
1111: input_line_pointer = param;
1112: while(*param != ',' && *param != '\0')
1113: param++;
1114: save_c = *param;
1115: *param = '\0';
1116:
1117: seg = SEG_ABSOLUTE;
1118: val = 0;
1119: for(i = 0; *special_registers[i].name != '\0'; i++){
1120: if(strcmp(input_line_pointer, special_registers[i].name) == 0){
1121: val = special_registers[i].number;
1122: break;
1123: }
1124: }
1125: if(*special_registers[i].name == '\0'){
1126: seg = expression(&exp);
1127: try_to_make_absolute(&exp);
1128: seg = exp.X_seg;
1129: val = exp.X_add_number;
1130: }
1131: *param = save_c;
1132: input_line_pointer = saveptr;
1133:
1134: if(seg != SEG_ABSOLUTE){
1135: error_param_message = "Parameter error: expression must be "
1136: "absolute (parameter %lu)";
1137: return(NULL);
1138: }
1139: if(val > 1024 || val < 0){
1140: error_param_message = "Parameter error: expression out "
1141: "of range (parameter %lu)";
1142: return(NULL);
1143: }
1144:
1145: val = ((val & 0x1f) << 5) | ((val >> 5) & 0x1f);
1146:
1147: if(*param == '\0'){
1148: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1149: insn->opcode |= val << format->ops[parcnt].offset;
1150: return(param);
1151: }
1152: else
1153: return(NULL);
1154: }
1155: else if(*param == ','){
1156: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1157: insn->opcode |= val << format->ops[parcnt].offset;
1158: return(param+1);
1159: }
1160: else
1161: return(NULL);
1162: }
1163: return(NULL);
1164: }
1165:
1166: static
1167: char *
1168: parse_bcnd(
1169: char *param,
1170: struct m98k_insn *insn,
1171: struct m98k_opcode *format,
1172: unsigned long parcnt)
1173: {
1174: int val;
1175: unsigned long i, j;
1176: char *saveptr, save_c, *plus, save_plus;
1177: expressionS exp;
1178: segT seg;
1179:
1180: saveptr = input_line_pointer;
1181: input_line_pointer = param;
1182: while(*param != ',' && *param != '\0')
1183: param++;
1184: save_c = *param;
1185: *param = '\0';
1186:
1187: /*
1188: * look for "[CR_field+]condition_symbol".
1189: */
1190: val = -1;
1191: for(plus = input_line_pointer; *plus != '+' && *plus != '\0'; plus++)
1192: ;
1193: if(*plus == '+'){
1194: save_plus = *plus;
1195: *plus = '\0';
1196: for(i = 0; *CR_fields[i].name != '\0'; i++)
1197: if(strcmp(input_line_pointer, CR_fields[i].name) == 0)
1198: break;
1199: *plus = save_plus;
1200: if(*CR_fields[i].name != '\0'){
1201: for(j = 0; *condition_symbols[j].name != '\0'; j++)
1202: if(strcmp(plus+1, condition_symbols[j].name) == 0)
1203: break;
1204: if(*condition_symbols[j].name != '\0'){
1205: val = CR_fields[i].value + condition_symbols[j].value;
1206: }
1207: }
1208: }
1209: else{
1210: for(i = 0; *condition_symbols[i].name != '\0'; i++)
1211: if(strcmp(input_line_pointer, condition_symbols[i].name) == 0)
1212: break;
1213: if(*condition_symbols[i].name != '\0')
1214: val = condition_symbols[i].value;
1215: }
1216: if(val == -1){
1217: seg = expression(&exp);
1218: try_to_make_absolute(&exp);
1219: seg = exp.X_seg;
1220: val = exp.X_add_number;
1221: if(seg != SEG_ABSOLUTE){
1222: error_param_message = "Parameter error: expression must be "
1223: "absolute (parameter %lu)";
1224: *param = save_c;
1225: input_line_pointer = saveptr;
1226: return(NULL);
1227: }
1228: if(val >= (1 << format->ops[parcnt].width) || val < 0){
1229: error_param_message = "Parameter error: expression out "
1230: "of range (parameter %lu)";
1231: *param = save_c;
1232: input_line_pointer = saveptr;
1233: return(NULL);
1234: }
1235: }
1236:
1237: *param = save_c;
1238: input_line_pointer = saveptr;
1239:
1240:
1241: if(*param == '\0'){
1242: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1243: insn->opcode |= val << format->ops[parcnt].offset;
1244: return(param);
1245: }
1246: else
1247: return(NULL);
1248: }
1249: else if(*param == ','){
1250: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1251: insn->opcode |= val << format->ops[parcnt].offset;
1252: return(param+1);
1253: }
1254: else
1255: return(NULL);
1256: }
1257: return(NULL);
1258:
1259: }
1260:
1261: static
1262: char *
1263: parse_crf(
1264: char *param,
1265: struct m98k_insn *insn,
1266: struct m98k_opcode *format,
1267: unsigned long parcnt)
1268: {
1269: int val;
1270: unsigned long i;
1271: char *saveptr, save_c;
1272: expressionS exp;
1273: segT seg;
1274:
1275: saveptr = input_line_pointer;
1276: input_line_pointer = param;
1277: while(*param != ',' && *param != '\0')
1278: param++;
1279: save_c = *param;
1280: *param = '\0';
1281: val = -1;
1282: for(i = 0; *CR_fields[i].name != '\0'; i++){
1283: if(strcmp(input_line_pointer, CR_fields[i].name) == 0){
1284: val = CR_fields[i].value;
1285: break;
1286: }
1287: }
1288: if(val == -1){
1289: if(format->ops[parcnt].type == CRFONLY){
1290: *param = save_c;
1291: input_line_pointer = saveptr;
1292: return(NULL);
1293: }
1294: seg = expression(&exp);
1295: try_to_make_absolute(&exp);
1296: seg = exp.X_seg;
1297: val = exp.X_add_number;
1298: if(seg != SEG_ABSOLUTE){
1299: error_param_message = "Parameter error: expression must be "
1300: "absolute (parameter %lu)";
1301: *param = save_c;
1302: input_line_pointer = saveptr;
1303: return(NULL);
1304: }
1305: if(val >= (1 << format->ops[parcnt].width) || val < 0){
1306: error_param_message = "Parameter error: expression out "
1307: "of range (parameter %lu)";
1308: *param = save_c;
1309: input_line_pointer = saveptr;
1310: return(NULL);
1311: }
1312: }
1313: *param = save_c;
1314: input_line_pointer = saveptr;
1315:
1316: if(*param == '\0'){
1317: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1318: insn->opcode |= val << format->ops[parcnt].offset;
1319: return(param);
1320: }
1321: else
1322: return(NULL);
1323: }
1324: else if(*param == ','){
1325: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1326: insn->opcode |= val << format->ops[parcnt].offset;
1327: return(param+1);
1328: }
1329: else
1330: return(NULL);
1331: }
1332: return(NULL);
1333: }
1334:
1335: static
1336: char *
1337: parse_num(
1338: char *param,
1339: struct m98k_insn *insn,
1340: struct m98k_opcode *format,
1341: unsigned long parcnt,
1342: long max_width_zero)
1343: {
1344: int val;
1345: char *saveptr, save_c;
1346: expressionS exp;
1347: segT seg;
1348:
1349: saveptr = input_line_pointer;
1350: input_line_pointer = param;
1351: while(*param != ',' && *param != '\0')
1352: param++;
1353: save_c = *param;
1354: *param = '\0';
1355: seg = expression(&exp);
1356: try_to_make_absolute(&exp);
1357: seg = exp.X_seg;
1358: *param = save_c;
1359: input_line_pointer = saveptr;
1360:
1361: val = exp.X_add_number;
1362: if(seg != SEG_ABSOLUTE){
1363: error_param_message = "Parameter error: expression must be "
1364: "absolute (parameter %lu)";
1365: return(NULL);
1366: }
1367: if(max_width_zero){
1368: if(val == (1 << format->ops[parcnt].width))
1369: val = 0;
1370: }
1371: if(val >= (1 << format->ops[parcnt].width) || val < 0){
1372: error_param_message = "Parameter error: expression out "
1373: "of range (parameter %lu)";
1374: return(NULL);
1375: }
1376:
1377: if(*param == '\0'){
1378: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1379: insn->opcode |= val << format->ops[parcnt].offset;
1380: return(param);
1381: }
1382: else
1383: return(NULL);
1384: }
1385: else if(*param == ','){
1386: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1387: insn->opcode |= val << format->ops[parcnt].offset;
1388: return(param+1);
1389: }
1390: else
1391: return(NULL);
1392: }
1393: return(NULL);
1394:
1395: }
1396:
1397: static
1398: char *
1399: parse_sh(
1400: char *param,
1401: struct m98k_insn *insn,
1402: struct m98k_opcode *format,
1403: unsigned long parcnt)
1404: {
1405: int val;
1406: char *saveptr, save_c;
1407: expressionS exp;
1408: segT seg;
1409:
1410: saveptr = input_line_pointer;
1411: input_line_pointer = param;
1412: while(*param != ',' && *param != '\0')
1413: param++;
1414: save_c = *param;
1415: *param = '\0';
1416: seg = expression(&exp);
1417: try_to_make_absolute(&exp);
1418: seg = exp.X_seg;
1419: *param = save_c;
1420: input_line_pointer = saveptr;
1421:
1422: val = exp.X_add_number;
1423: if(seg != SEG_ABSOLUTE){
1424: error_param_message = "Parameter error: expression must be "
1425: "absolute (parameter %lu)";
1426: return(NULL);
1427: }
1428: if(val == 64)
1429: val = 0;
1430: if(val >= 64 || val < 0){
1431: error_param_message = "Parameter error: expression out "
1432: "of range (parameter %lu)";
1433: return(NULL);
1434: }
1435:
1436: if(*param == '\0'){
1437: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1438: insn->opcode |= (val & 0x1f) << 11;
1439: insn->opcode |= ((val >> 5) & 0x1) << 1;
1440: return(param);
1441: }
1442: else
1443: return(NULL);
1444: }
1445: else if(*param == ','){
1446: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1447: insn->opcode |= (val & 0x1f) << 11;
1448: insn->opcode |= ((val >> 5) & 0x1) << 1;
1449: return(param+1);
1450: }
1451: else
1452: return(NULL);
1453: }
1454: return(NULL);
1455:
1456: }
1457:
1458: static
1459: char *
1460: parse_mb(
1461: char *param,
1462: struct m98k_insn *insn,
1463: struct m98k_opcode *format,
1464: unsigned long parcnt)
1465: {
1466: int val;
1467: char *saveptr, save_c;
1468: expressionS exp;
1469: segT seg;
1470:
1471: saveptr = input_line_pointer;
1472: input_line_pointer = param;
1473: while(*param != ',' && *param != '\0')
1474: param++;
1475: save_c = *param;
1476: *param = '\0';
1477: seg = expression(&exp);
1478: try_to_make_absolute(&exp);
1479: seg = exp.X_seg;
1480: *param = save_c;
1481: input_line_pointer = saveptr;
1482:
1483: val = exp.X_add_number;
1484: if(seg != SEG_ABSOLUTE){
1485: error_param_message = "Parameter error: expression must be "
1486: "absolute (parameter %lu)";
1487: return(NULL);
1488: }
1489: if(val > 64 || val < 0){
1490: error_param_message = "Parameter error: expression out "
1491: "of range (parameter %lu)";
1492: return(NULL);
1493: }
1494:
1495: if(*param == '\0'){
1496: if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
1497: insn->opcode |= (val & 0x1f) << 6;
1498: insn->opcode |= ((val >> 5) & 0x1) << 5;
1499: return(param);
1500: }
1501: else
1502: return(NULL);
1503: }
1504: else if(*param == ','){
1505: if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
1506: insn->opcode |= (val & 0x1f) << 6;
1507: insn->opcode |= ((val >> 5) & 0x1) << 5;
1508: return(param+1);
1509: }
1510: else
1511: return(NULL);
1512: }
1513: return(NULL);
1514:
1515: }
1516:
1517: /*
1518: * md_number_to_chars() is the target machine dependent routine that puts out
1519: * a binary value of size 4, 2, or 1 bytes into the specified buffer. This is
1520: * done in the target machine's byte sex. In this case the byte order is
1521: * big endian.
1522: */
1523: void
1524: md_number_to_chars(
1525: char *buf,
1526: long val,
1527: int nbytes)
1528: {
1529: switch(nbytes){
1530: case 4:
1531: *buf++ = val >> 24;
1532: *buf++ = val >> 16;
1533: case 2:
1534: *buf++ = val >> 8;
1535: case 1:
1536: *buf = val;
1537: break;
1538:
1539: default:
1540: abort();
1541: }
1542: }
1543:
1544: /*
1545: * md_number_to_imm() is the target machine dependent routine that puts out
1546: * a binary value of size 4, 2, or 1 bytes into the specified buffer with
1547: * reguard to a possible relocation entry (the fixP->fx_r_type field in the fixS
1548: * structure pointed to by fixP) for the section with the ordinal nsect. This
1549: * is done in the target machine's byte sex using it's relocation types.
1550: * In this case the byte order is big endian.
1551: */
1552: void
1553: md_number_to_imm(
1554: unsigned char *buf,
1555: long val,
1556: int nbytes,
1557: fixS *fixP,
1558: int nsect)
1559: {
1560: unsigned long opcode;
1561:
1562: if(fixP->fx_r_type == NO_RELOC ||
1563: fixP->fx_r_type == M98K_RELOC_VANILLA){
1564: switch(nbytes){
1565: case 4:
1566: *buf++ = val >> 24;
1567: *buf++ = val >> 16;
1568: case 2:
1569: *buf++ = val >> 8;
1570: case 1:
1571: *buf = val;
1572: break;
1573:
1574: default:
1575: abort();
1576: }
1577: return;
1578: }
1579: switch(fixP->fx_r_type){
1580: case M98K_RELOC_HI16:
1581: buf[2] = val >> 24;
1582: buf[3] = val >> 16;
1583: break;
1584:
1585: case M98K_RELOC_LO16:
1586: buf[2] = val >> 8;
1587: buf[3] = val;
1588: break;
1589:
1590: case M98K_RELOC_HA16:
1591: val += 0x00008000;
1592: buf[2] = val >> 24;
1593: buf[3] = val >> 16;
1594: break;
1595:
1596: case M98K_RELOC_LO14:
1597: buf[2] = val >> 8;
1598: buf[3] = val & 0xfc;
1599: break;
1600:
1601: case M98K_RELOC_BR14:
1602: if((val & 0x00008000) != 0){
1603: opcode = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
1604: if(((opcode) & 0x03e00000) != 0x02800000){
1605: opcode ^= Y_BIT;
1606: buf[0] = opcode >> 24;
1607: buf[1] = opcode >> 16;
1608: buf[2] = opcode >> 8;
1609: buf[3] = opcode;
1610: }
1611: }
1612: if(fixP->fx_pcrel)
1613: val += 4;
1614: buf[2] = val >> 8;
1615: buf[3] |= val & 0xfc;
1616: break;
1617:
1618: case M98K_RELOC_BR24:
1619: if(fixP->fx_pcrel)
1620: val += 4;
1621: buf[0] |= (val >> 24) & 0x03;
1622: buf[1] = val >> 16;
1623: buf[2] = val >> 8;
1624: buf[3] |= val & 0xfc;
1625: break;
1626:
1627: default:
1628: as_warn("Bad relocation type");
1629: break;
1630: }
1631: }
1632:
1633: /*
1634: * md_atof() turns a string pointed to by input_line_pointer into a floating
1635: * point constant of type type, and store the appropriate bytes in *litP.
1636: * The number of LITTLENUMS emitted is stored indirectly through *sizeP.
1637: * An error message is returned, or a string containg only a '\0' for OK.
1638: * For this machine only IEEE single and IEEE double floating-point formats
1639: * are allowed.
1640: */
1641: char *
1642: md_atof(
1643: int type,
1644: char *litP,
1645: int *sizeP)
1646: {
1647: int prec;
1648: LITTLENUM_TYPE words[6];
1649: LITTLENUM_TYPE *wordP;
1650: char *t;
1651:
1652: switch(type){
1653: case 'f':
1654: case 'F':
1655: case 's':
1656: case 'S':
1657: prec = 2;
1658: break;
1659:
1660: case 'd':
1661: case 'D':
1662: case 'r':
1663: case 'R':
1664: prec = 4;
1665: break;
1666:
1667: default:
1668: *sizeP = 0;
1669: return("Bad call to MD_ATOF()");
1670: }
1671: t = atof_ieee(input_line_pointer, type, words);
1672: if(t != NULL)
1673: input_line_pointer = t;
1674:
1675: *sizeP = prec * sizeof(LITTLENUM_TYPE);
1676: for(wordP = words; prec--; ){
1677: md_number_to_chars(litP, (long)(*wordP++), sizeof(LITTLENUM_TYPE));
1678: litP += sizeof(LITTLENUM_TYPE);
1679: }
1680: return ""; /* OK */
1681: }
1682:
1683: int
1684: md_estimate_size_before_relax(
1685: fragS *fragP,
1686: int segment_type)
1687: {
1688: as_warn("Relaxation should never occur");
1689: return(sizeof(long));
1690: }
1691:
1692: const relax_typeS md_relax_table[] = {0};
1693:
1694: void
1695: md_convert_frag(
1696: fragS *fragP)
1697: {
1698: as_warn("Relaxation should never occur");
1699: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.